ee5e9c753a5630e23e25d28114d35bc478b82258
[vlp.git] / src / kernel / kernel.cpp
1 /**************************************************************
2
3   Copyright (C) 1997  Oskar Swida
4
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License
7  as published by the Free Software Foundation; either version 2
8  of the License, or (at your option) any later version.
9
10  This program is distributed in the hope that it will be useful, 
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
20
21
22  NOTE: This software is using the free software license of 
23        the QT library v.1.30 from Troll Tech AS.
24        See the file LICENSE.QT.
25
26  
27   To contact the author, write:
28      e-mail: swida@aragorn.pb.bialystok.pl
29
30 ************************************************************/
31
32 #include <QtGui/QApplication>
33 #include <QtGui/QMainWindow>
34 #include <QtGui/QTextEdit>
35 #include <QtGui/QMenuBar>
36 #include <QtGui/QMessageBox>
37 #include <QtGui/QFileDialog>
38 #include <QtGui/QDialog>
39 #include <QtCore/QString>
40 #include <QtGui/QLabel>
41 #include <QtGui/QLineEdit>
42 #include <QtGui/QPushButton>
43 #include <QtGui/QRadioButton>
44 #include <QtGui/QGroupBox>
45 #include <QtGui/QVBoxLayout>
46 #include <QtCore/QList>
47 #include <QtGui/QListWidget>
48 #include <qfile.h>
49 #include <qcursor.h>
50 #include <QtCore/QSocketNotifier>
51 #include <QtGui/QCloseEvent>
52 #include <QtCore/QDir>
53 #include <QtCore/QProcess>
54
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <unistd.h>
58 #include <fcntl.h>
59
60 #include "genint1.h"
61 #include "socu.h"
62 #include <netinet/in.h>
63
64 #include <libconfig.h>
65 #include <X11/Xlib.h>
66
67 #include "kernel.h"
68 #include "ui/KernelWindow.h"
69 #include "ConnectDialog.h"
70 #include "KillDialog.h"
71 #include "LockDialog.h"
72 #include "OptionsDialog.h"
73 #include "MessageDialog.h"
74
75 #include "vlp/config.h"
76
77 #include <sys/prctl.h>
78 /* File resides in top directory (where are Makefiles)*/
79 #include "../../config.h"
80
81
82 namespace loglan {
83 namespace vlp {
84
85 char CharLine[25] = "________________________";
86
87 /**
88  * Event invoked on program close.
89  * Closes application. Displays additional window to confirm exit.
90  */
91 void QKernel::closeEvent(QCloseEvent * e)
92 {
93         e->ignore();
94
95         if (!LOCKED) {
96                 on_actionQuit_triggered();
97         }
98 }
99
100 void QKernel::setLocked(bool locked)
101 {
102         LOCKED = locked;
103
104         actionQuit->setDisabled(locked);
105
106         actionExecute->setDisabled(locked);
107         actionKill->setDisabled(locked);
108         actionMessage->setDisabled(locked);
109         actionConnect->setDisabled(locked);
110         actionDisconnect->setDisabled(locked);
111         actionInfo->setDisabled(locked);
112
113
114         /* Enable only menu entry for unlocking */
115         actionEditor->setDisabled(locked);
116         actionOptions->setDisabled(locked);
117         actionLock_console->setDisabled(locked);
118         actionUnlock_console->setDisabled(!locked);
119 }
120
121 /**
122  * Kernel program constructor.
123  * Prepares everything to work.
124  */
125 QKernel::QKernel(int argc, char **argv)
126 {
127         setupUi(this);
128
129         QString arg0(argv[0]);
130         arg0 += "/";
131         homeDir = QDir(arg0);
132         homeDir.cdUp();
133
134         
135         int i;
136         for(i = 0; (i < 5) && (i < argc-1); i++) {
137                 strcpy(myargs[i], "");
138                 if (i < argc) {
139                         strcpy(myargs[i], argv[i+1]);
140                 }
141         }
142
143         QDir q(getRemoteDir());
144
145         if (!q.exists()) {
146                 q.mkpath(getRemoteDir());
147         }
148
149         info_messages = actionInfo_messages->isChecked();
150         wait_for_info = FALSE;
151
152         setWindowTitle(PACKAGE_NAME);
153
154         LOCKED = FALSE;
155
156         Tasks = 0;
157         freeINTid = 1;
158         ActiveConnections = 0;
159         strcpy(LockPasswd, "");
160
161         loadConfig(getConfigFilePath());
162
163         RunNetModule();
164
165         Net_Notify = new QSocketNotifier(net_sock, QSocketNotifier::Read, this);
166         connect(Net_Notify, SIGNAL(activated(int)), this, SLOT(NetMessage()));
167
168         WriteMessage("\n " PACKAGE_STRING ": READY \n");
169 }
170
171 QString QKernel::getConfigFilePath()
172 {
173         return homeDir.absoluteFilePath("vlp.cfg");
174 }
175
176 const char * QKernel::getHomeDir()
177 {
178         return homeDir.absolutePath().toStdString().c_str();
179 }
180
181 const char * QKernel::getRemoteDir()
182 {
183         return homeDir.absoluteFilePath(REMOTE_PATH).toStdString().c_str();
184 }
185
186 const char * QKernel::getNetModuleSocket()
187 {
188         return homeDir.absoluteFilePath(NPATH).toStdString().c_str();
189 }
190
191 const char * QKernel::getGraphModuleSocket()
192 {
193         return homeDir.absoluteFilePath(GPATH).toStdString().c_str();
194 }
195
196 void QKernel::loadConfig(const QString & fname)
197 {
198         loadConfig(fname.toStdString().c_str());
199 }
200 /**
201  * Loads configuration from the given file.
202  * @param fname Filename of the configuration file.
203  */
204 void QKernel::loadConfig(const char * fname)
205 {
206         loglan::vlp::Config config;
207         if(config.load(fname)) {
208                 NodeNumber = config.getNodeNumber();
209                 ConType = config.getConnectionType();
210
211
212                 std::vector<std::string> hosts = config.getHosts();
213                 for (unsigned int i = 0; i < hosts.size(); i++) {
214                         ConnectList.append(new ConnectEntry(hosts[i].c_str()));
215                 }
216
217                 strncpy(progdir, config.getProgramDir(), 256);
218         }
219 }
220
221 /**
222  * Executes program.
223  * Additional window id displayed to set which code to execute.
224  */
225 void QKernel::on_actionExecute_triggered()
226 {
227         QString s = QFileDialog::getOpenFileName(this, "Execute", progdir, "*.log");
228
229         if (!s.isNull()) {
230                 int i = s.indexOf(".log");
231
232                 if (i > 0)
233                         s.remove(i, 4);
234
235                 // @TODO: if no interpreter is running will result in killing app
236                 RunIntModule((char*)s.toAscii().data(), 0);
237         }
238 }
239
240 /**
241  * Invokes editor program
242  */
243 void QKernel::on_actionEditor_triggered()
244 {
245         QString program = getHomeDir();
246         program += "/modules/logedit";
247
248         fprintf(stderr, "Run EDIT Module: %s, %s\n", program.toStdString().c_str(), getHomeDir());
249         pid_t pid = fork();
250         if (pid == 0) {
251                 if (execl(program.toStdString().c_str(),
252                         getHomeDir(),
253                         myargs[0],
254                         myargs[1],
255                         myargs[2],
256                         myargs[3],
257                         myargs[4],
258                         NULL
259                 ) == -1) {
260                         WriteMessage("Executing logedit failed!");
261                 }
262         }
263         else if (pid < 0) {
264                 WriteMessage("fork(logedit) failed!");
265                 WriteMessage("Exiting...");
266                 sleep(2);
267                 on_actionQuit_triggered();
268                 exit(3);
269         }
270 }
271
272 /**
273  * Invokes help program
274  */
275 void QKernel::on_actionHelp_triggered()
276 {
277         QString program = getHomeDir();
278         program += "/modules/loghelp";
279         
280         QString docDir = getHomeDir();
281         docDir += "/doc";
282
283         fprintf(stderr, "Run HELP Module: %s, %s\n", program.toStdString().c_str(), docDir.toStdString().c_str());
284
285         pid_t pid = fork();
286         if (pid == 0) {
287                 if (execl(program.toStdString().c_str(),
288                         docDir.toStdString().c_str(),
289                         myargs[0],
290                         myargs[1],
291                         myargs[2],
292                         myargs[3],
293                         myargs[4],
294                         NULL
295                 ) == -1) {
296
297                         WriteMessage("Executing loghelp failed!");
298                 }
299         }
300         else if (pid < 0) {
301                 WriteMessage("fork(loghelp) failed!");
302                 WriteMessage("Exiting...");
303                 sleep(2);
304                 on_actionQuit_triggered();
305                 exit(3);
306         }
307 }
308
309 /**
310  * Invokes graphics module
311  */
312 void QKernel::RunGraphModule(char *sk)
313 {
314         QString program = getHomeDir();
315         program += "/modules/loggraph";
316
317         fprintf(stderr, "Run GRAPH Module: %s, %s\n", program.toStdString().c_str(), sk);
318
319         pid_t pid = fork();
320         if (pid == 0) {
321                 if (execl(program.toStdString().c_str(),
322                         program.toStdString().c_str(),
323                         sk,
324                         myargs[0],
325                         myargs[1],
326                         myargs[2],
327                         myargs[3],
328                         myargs[4],
329                         NULL
330                 ) == -1) {
331
332                         WriteMessage("Executing loggraph failed!");
333                         WriteMessage("Exiting...");
334                         sleep(2);
335                         on_actionQuit_triggered();
336                 }
337         }
338         else if (pid < 0) {
339                 WriteMessage("fork(loggraph) failed!");
340                 WriteMessage("Exiting...");
341                 sleep(2);
342                 on_actionQuit_triggered();
343                 exit(3);
344         }
345 }
346
347 /**
348  * Invokes net module
349  */
350 void QKernel::RunNetModule()
351 {
352
353         struct sockaddr_un svr;
354         int len;
355         int on;
356         int sock;
357
358         QString program = getHomeDir();
359         program += "/modules/lognet";
360
361         fprintf(stderr, "Run NET Module: %s, %s %s\n", program.toStdString().c_str(), getNetModuleSocket(), getConfigFilePath().toStdString().c_str());
362         pid_t pid = fork();
363         if (pid == 0) {
364                 if (execl(program.toStdString().c_str(),
365                         program.toStdString().c_str(),
366                         getNetModuleSocket(),
367                         getConfigFilePath().toStdString().c_str(),
368                         myargs[0],
369                         myargs[1],
370                         myargs[2],
371                         myargs[3],
372                         myargs[4],
373                         NULL
374                 ) == -1) {
375
376                         WriteMessage("Executing lognet failed!");
377                         WriteMessage("Exiting...");
378                         sleep(2);
379                         on_actionQuit_triggered();
380                 }
381         }
382         else if (pid < 0) {
383                 WriteMessage("fork(lognet) failed!");
384                 WriteMessage("Exiting...");
385                 sleep(2);
386                 on_actionQuit_triggered();
387                 exit(3);
388         }
389
390         /* -------- socket for NET module -------- */
391         unlink(getNetModuleSocket());
392         sock = socket(AF_UNIX, SOCK_STREAM, 0);
393         bzero(&svr, sizeof(svr));
394         svr.sun_family = AF_UNIX;
395         strcpy(svr.sun_path, getNetModuleSocket());
396         len = strlen(svr.sun_path) + sizeof(svr.sun_family);
397         bind(sock, (struct sockaddr*)&svr, len);
398         listen(sock, 5);
399
400         net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
401         // close(sock); 
402         if (net_sock != 0) {
403                 WriteMessage("NETWORK successfully connected");
404                 fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock, F_GETFL, 0));
405                 on = 1;
406                 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
407         } else {
408                 WriteMessage("Cannot connect NETWORK resources");
409                 WriteMessage("Exiting...");
410                 sleep(2);
411                 on_actionQuit_triggered();
412         }
413 }
414
415 /**
416  * Connects to the specified address
417  * Additional window is displayed to connect to the specified address
418  */
419 void QKernel::on_actionConnect_triggered()
420 {
421         MESSAGE m;
422
423         dialog::ConnectDialog dialog(this);
424
425         if (dialog.exec()) {
426                 m.msg_type = MSG_NET;
427                 m.param.pword[0] = NET_CONNECT_TO;
428                 strcpy(m.param.pstr, dialog.getAddress().toStdString().c_str());
429                 write(net_sock, &m, sizeof(MESSAGE));
430         }
431 }
432
433 /**
434  * Disconnects from virtual machine
435  */
436 void QKernel::on_actionDisconnect_triggered()
437 {
438         MESSAGE msg;
439
440         if (info_messages)
441                 WriteMessage("Disconnecting from virtual machine");
442
443         msg.msg_type = MSG_NET;
444         msg.param.pword[0] = NET_DISCONNECT;
445         write(net_sock, &msg, sizeof(MESSAGE));
446 }
447
448 /**
449  * Quits process. Closes VLP. Shows additional window to confirm exit. 
450  */
451 void QKernel::on_actionQuit_triggered()
452 {
453         MESSAGE msg;
454
455         QMessageBox::StandardButton response = QMessageBox::question(this,
456                 "Close VLP",
457                 "Terminate VLP ?",
458                 QMessageBox::Ok | QMessageBox::Cancel
459         );
460
461
462         if (response == QMessageBox::Cancel) {
463                 return;
464         }
465         /*
466         msg.msg_type = MSG_NET;
467         msg.param.pword[0] = NET_DISCONNECT;
468         write(net_sock, &msg, sizeof(MESSAGE));*/
469         delete Net_Notify;
470
471         msg.msg_type = MSG_NET;
472         msg.param.pword[0] = NET_EXIT;
473         write(net_sock, &msg, sizeof(MESSAGE));
474         /*  ::close(net_sock);*/
475         QApplication::instance()->quit();
476 }
477
478 /**
479  * Sends message to node.
480  * Additional window is displayed to set Node Number of node where send message,
481  * and textfield to enter message.
482  */
483 void QKernel::on_actionMessage_triggered()
484 {
485         dialog::MessageDialog dialog(this);
486         MESSAGE m;
487
488         if (dialog.exec()) {
489                 m.msg_type = MSG_NET;
490                 m.param.pword[0] = NET_PROPAGATE;
491                 m.param.pword[1] = MSG_VLP;
492                 m.param.pword[2] = NodeNumber;
493                 m.param.pword[4] = dialog.getNodeNumber();
494                 m.param.pword[6] = VLP_WRITE;
495                 strcpy(m.param.pstr, dialog.getMessage().toStdString().c_str());
496                 write(net_sock, &m, sizeof(MESSAGE));
497         }
498 }
499
500 /**
501  * Kills interpreter.
502  * Additional window is displayed to get ID of interpreter which should be
503  * killed.
504  */
505 void QKernel::on_actionKill_triggered()
506 {
507         dialog::KillInterpreterDialog dialog(this);
508
509         if (dialog.exec()) {
510                 MESSAGE m;
511                 m.msg_type = MSG_INT;
512                 m.param.pword[0] = INT_KILL;
513                 
514                 InterpEntry *interpreter;
515                 interpreter = findINTbyID(dialog.getInterpreterId());
516
517                 if (interpreter != NULL) {
518                         if (!(interpreter->remote)) {
519                                 write(interpreter->sock, &m, sizeof(MESSAGE));
520                         }
521                         else {
522                                 WriteMessage("This is a remote instance of a program!");
523                         }
524                 }
525                 else {
526                         WriteMessage("Interpreter not found");
527                 }
528         }
529 }
530
531 /**
532  * Sends message to the net module.
533  */
534 void QKernel::NetMessage()
535 {
536         
537         /* TODO: It has to be rewritten */
538         MESSAGE msg;
539         int cnt;
540         InterpEntry *pom;
541
542         cnt = read(net_sock, &msg, sizeof(MESSAGE));
543         if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
544                 char ss[255];
545
546                 switch(msg.param.pword[0]) {
547                 case NET_CSWRITELN:
548                         WriteMessage(msg.param.pstr);
549                         break;
550                 case NET_PROPAGATE: 
551                         switch(msg.param.pword[1]) {
552                         case MSG_INT:
553                                 /*  pom = find_link_by_ID(msg.param.pword[5]);
554                                 msg.msg_type = MSG_NET;
555                                 msg.param.pword[0] = NET_PROPAGATE;
556                                 send_int(pom, &msg);*/
557                                 break;
558                         case MSG_VLP:
559                                 switch(msg.param.pword[6]) {
560                                 case VLP_WRITE:
561                                         QApplication::beep();
562                                         WriteMessage(CharLine);
563                                         WriteMessage("### Incoming Messsage ###");
564                                         sprintf(ss,
565                                                 "Mesg from Node %d: %s",
566                                                 msg.param.pword[2],
567                                                 msg.param.pstr
568                                         );
569                                         WriteMessage(ss);
570                                         WriteMessage(CharLine);
571                                         break;
572                                 case VLP_REMOTE_INSTANCE:
573                                         sprintf(ss, "%s/%s", getRemoteDir(), msg.param.pstr);
574
575                                         if (info_messages) { 
576                                                 WriteMessage("Running program:");
577                                                 WriteMessage(ss);
578                                         }
579                                         pom = RunIntModule(ss, 1);
580                                         if (pom != NULL) {
581                                                 pom->p_ctx.node = msg.param.pword[2];
582                                                 pom->p_ctx.program_id = 
583                                                         msg.param.pword[7];
584                                                 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
585                                         }
586                                         break;
587                                 case VLP_CLOSE_INSTANCE:
588                                         msg.msg_type = MSG_INT;
589                                         msg.param.pword[0] = INT_CLOSE_INSTANCE;
590                                         pom = findINTbyID(msg.param.pword[7]);
591                                         if (pom != NULL) {
592                                                 write(pom->sock, &msg,
593                                                         sizeof(MESSAGE));
594                                                 MESSAGE m1;
595                                                 m1.msg_type = MSG_VLP;
596                                                 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
597                                                 m1.param.pword[1] = pom->ID;
598                                                 write(net_sock, &m1,
599                                                         sizeof(MESSAGE));
600                                         } else {
601                                                 WriteMessage("Instance not found"); 
602                                         }
603                                         break; 
604                                 } /* VLP switch */
605                         }/* switch */
606                         break;
607                 case NET_CONNECTIONS:
608                         ActiveConnections = msg.param.pword[1];
609                         WriteMessage(msg.param.pstr);
610                         if (!synchro) 
611                                 synchro = TRUE;
612                         break;
613                 case NET_INFO:
614                         /* TODO: It has to be rewritten */
615                         if (wait_for_info) {
616                                 QString poms, poms1, poms2;
617                                 poms.sprintf("%s", msg.param.pstr);
618                                 while (poms.length() > 0) {
619                                         cnt = poms.indexOf(';');
620                                         if (cnt!=-1) {
621                                                 poms1 = poms.left(cnt);
622                                                 poms = poms.right(poms.length() - cnt - 1);
623                                                 cnt = poms1.indexOf('=');
624                                                 if (cnt != -1) {
625                                                         poms2 = poms1.left(cnt);
626                                                         poms1 = poms1.right(poms1.length() - cnt - 1);
627                                                         sprintf(ss, "Node: %s Addr: %s", poms2.toStdString().c_str(), poms1.toStdString().c_str());
628                                                         WriteMessage(ss); 
629                                                 }
630                                         } 
631                                 }
632                         } 
633                         break;
634                 case NET_INFO_END:
635                         wait_for_info = FALSE;
636                         WriteMessage(CharLine);
637                         break;
638                 } /* switch */
639         }
640 }
641
642 /**
643  * Sends message to the interpreter program.
644  * @param sock Interpreter socket to whom the message will be send.
645  */
646 void QKernel::IntMessage(int sock)
647 {
648         MESSAGE msg;
649         int cnt;
650         InterpEntry *e;
651
652         cnt = read(sock, &msg, sizeof(MESSAGE));
653         e = findINTbySocket(sock);
654         if ((cnt > 0) && (e != NULL)) {
655                 switch (msg.msg_type) { 
656                 case MSG_GRAPH:
657                         if (msg.param.pword[0] == GRAPH_ALLOCATE) {
658                                 fprintf(stderr, "Running graph module with arg: %s\n", msg.param.pstr);
659                                 RunGraphModule(msg.param.pstr);
660                         }
661                         break;
662                 case MSG_NET:
663                         write(net_sock, &msg, sizeof(MESSAGE));
664                         break;
665                 case MSG_VLP:
666                         switch(msg.param.pword[0]) {
667                         case VLP_REMOTE_INSTANCE_PLEASE:
668                                 RemoteInstance(e, msg.param.pword[2]);
669                                 break;
670                         }/* switch */
671                         break;
672                 case MSG_INT:
673                         switch(msg.param.pword[0]) {
674                         case INT_EXITING:
675                                 char ss[255];
676
677                                 MESSAGE m;
678                                 m.msg_type = MSG_VLP;
679                                 m.param.pword[0] = VLP_INTERPRETER_DOWN;
680                                 m.param.pword[1] = e->ID;
681                                 write(net_sock, &m, sizeof(MESSAGE));
682                                 if (e->remote == 0)
683                                         CloseInstances(e);
684                                 delete e->notify;
685                                 ::close(e->sock);
686                                 /* TODO: Check this */
687                                 Interpreters.removeOne(e);
688                                 delete e;
689
690                                 if (info_messages) {
691                                         sprintf(ss, "%s : End of program "
692                                                 "execution", msg.param.pstr);
693                                         WriteMessage(ss);
694                                 }
695                                 break;
696                         case INT_CTX_REQ:
697                                 msg.msg_type = MSG_INT;
698                                 msg.param.pword[0] = INT_CTX;
699                                 msg.param.pword[1] = NodeNumber;
700                                 msg.param.pword[2] = e->ID;
701                                 if (e->remote) {
702                                         msg.param.pword[3] = e->p_ctx.node;
703                                         msg.param.pword[4] = 
704                                                         e->p_ctx.program_id;
705                                 }
706                                 write(sock, &msg, sizeof(MESSAGE)); 
707                                 break;
708                         };
709                         break;
710                 }
711         }
712 }
713
714 /**
715  * Writes message to kernel logger.
716  * @parame msg String with message to log
717  */
718 void QKernel::WriteMessage(const char *msg)
719 {
720         int x;
721 //      int y;
722         x = desktop->textCursor().blockNumber();
723 //      y = desktop->textCursor().columnNumber();
724
725         if (x > 100) {
726                 desktop->clear();
727         }
728         
729         desktop->setReadOnly(FALSE);
730         desktop->append(msg);
731         desktop->setReadOnly(TRUE);
732
733         QTextCursor tmpCursor = desktop->textCursor();
734         tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
735         desktop->setTextCursor(tmpCursor);
736
737         desktop->repaint();
738         
739         if (desktop->document()->blockCount() > 100) {
740                 desktop->clear();
741         }
742 }
743
744 /**
745  * Adds checkbox to menu item. If it is checked additional info messages are
746  * shown.
747  */
748 void QKernel::on_actionInfo_messages_triggered()
749 {
750         if (toolsMenu != NULL) {
751                 info_messages = actionInfo_messages->isChecked();
752                 actionInfo_messages->setChecked(info_messages);
753         }
754 }
755
756 /**
757  * Allows to set options in GUI window.
758  * Additional window is displayed to set kernel options which are saved in 
759  * vlp.cfg file in kernel executable directory.
760  */
761 void QKernel::on_actionOptions_triggered()
762 {
763         dialog::OptionsDialog optionsDialog(getConfigFilePath(), this);
764         if (optionsDialog.exec()) {
765                 optionsDialog.saveConfig(getConfigFilePath());
766
767                 loadConfig(getConfigFilePath());
768         }
769 }
770
771 /**
772  * Locks kernel program.
773  * Additional window is displayed to enter password and retype it. If both are
774  * same kernel window is locked.
775  */
776 void QKernel::on_actionLock_console_triggered()
777 {
778         dialog::LockDialog lockDialog(this);
779
780         if (lockDialog.exec()) {
781                 QString password = lockDialog.getPassword();
782                 if (lockDialog.getPassword().size() > 0) {
783                         strcpy(LockPasswd, password.toStdString().c_str());
784                         lockDialog.retype();
785
786                         if (lockDialog.exec()) {
787                                 password = lockDialog.getPassword();
788                                 if (password == LockPasswd) {
789                                         setLocked(TRUE);
790                                         WriteMessage("CONSOLE LOCKED");
791                                 } else {
792                                         QMessageBox msg(this);
793                                         msg.setText("Not matching!");
794                                         msg.setButtonText(0, "Close");
795                                         msg.show();
796                                         strcpy(LockPasswd, "");
797                                 }
798                         } else {
799                                 strcpy(LockPasswd, "");
800                         }
801                 }
802         }
803 }
804
805 /**
806  * Unlocks kernel program.
807  * Additional window is displayed to enter password. If it is correct, kernel 
808  * window is unlocked
809  */
810 void QKernel::on_actionUnlock_console_triggered()
811 {
812         dialog::LockDialog lockDialog(this);
813
814         if (lockDialog.exec()) {
815                 QString password = lockDialog.getPassword();
816                 if (strcmp(password.toStdString().c_str(), LockPasswd) == 0) {
817                         setLocked(FALSE);
818                         WriteMessage("CONSOLE UNLOCKED");
819                 } else {
820                         QMessageBox msg(this);
821                         msg.setText("Wrong password!");
822                         msg.setButtonText(0, "Close");
823                         msg.show();
824                 }
825         }
826 }
827
828 /**
829  * Finds Interpreter by its socket
830  * @param _id ID of the socket
831  * @return returns pointer to the found interpreter slot. NULL otherwise
832  */
833 InterpEntry *QKernel::findINTbySocket(int _id)
834 {
835         InterpEntry *pom = NULL;
836         
837         for (auto interpreter : Interpreters) {
838                 if (interpreter->sock == _id) {
839                         pom = interpreter;
840                         break;
841                 }
842         }
843
844         return pom;
845 }
846
847 /**
848  * Finds Interpreter by its ID.
849  * @param _id ID of the interpreter
850  * @return returns pointer to the found interpreter slot. NULL otherwise
851  */
852 InterpEntry *QKernel::findINTbyID(int _id)
853 {
854         InterpEntry *pom = NULL;
855         
856         for (auto interpreter : Interpreters) {
857                 if (interpreter->ID == _id) {
858                         pom = interpreter;
859                         break;
860                 }
861         }
862
863         return pom;
864 }
865
866
867 /**
868  * Connects interpreter
869  * @param ss full filepath with filename but without extension of the loglan
870  *           program to run.
871  * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
872  *          remote
873  * @return Returns pointer to newly created interpreter slot, or NULL on error.
874  */
875 InterpEntry *QKernel::RunIntModule(char *ss, int r)
876 {
877         fprintf(stderr, "Run INT Module: %s, %d\n", ss, r);
878         char a[256], b[255];
879         struct sockaddr_un svr;
880         int len, sock, on;
881         unsigned int i;
882         int newint=-1;
883         char cmd[255];
884         FILE *cf;
885         MESSAGE msg;
886         InterpEntry *newINT = NULL;
887
888         strcpy(a, ss);
889         strcat(a, ".ccd");
890         cf = fopen(a, "r");
891         if (cf == NULL) {
892                 WriteMessage("File not found: no .ccd file");
893                 return NULL;
894         }
895         fclose(cf);
896
897         strcpy(a, ss);
898         strcat(a, ".pcd");
899         cf = fopen(a, "r");
900         if (cf == NULL) {
901                 WriteMessage("File not found: no .pcd file");
902                 return NULL;
903         }
904         fclose(cf);
905
906         newINT = new InterpEntry;
907         for(i = 0; i < MAXINSTANCES; i++) 
908                 newINT->RInstances[i] =- 1;
909
910         strcpy(b, rindex(ss, '/'));
911         for(i = 0; i < strlen(b); i++)
912                 b[i] = b[i+1];
913         if (info_messages) {
914                 sprintf(a, "%s : Start execution", b);
915                 WriteMessage(a); 
916         }
917
918         newint = freeINTid;
919         freeINTid++;
920         newINT->ID = newint;
921         strcpy(newINT->shortname, b);
922         strcpy(newINT->fullname, ss);
923
924         sprintf(a, "%s%d", IPATH, newint);
925         sprintf(cmd, "%s/modules/logint %s %s",
926                 getHomeDir(),
927                 a,
928                 ss);
929         if (r) {
930                 strcat(cmd, " r");
931         }
932         sprintf(b, " %s %s %s %s %s",
933                 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
934         strcat(cmd, b);
935         strcat(cmd, " &");
936
937         sock = socket(AF_UNIX, SOCK_STREAM, 0);
938         unlink(a);
939         bzero(&svr, sizeof(svr));
940         svr.sun_family = AF_UNIX;
941         strcpy(svr.sun_path, a);
942         len = strlen(svr.sun_path)+sizeof(svr.sun_family);
943         bind(sock, (struct sockaddr*)&svr, len);
944         listen(sock, 5);
945         system(cmd);
946         newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
947         //::close(sock);
948
949         if (newINT->sock > 0) { 
950                 fcntl(newINT->sock, F_SETFL, 
951                                 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
952                 on=1; 
953                 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
954                                                                 sizeof(on));
955                 if (r)
956                         newINT->remote = 1;
957                 else 
958                         newINT->remote = 0;
959
960                 bzero(&msg, sizeof(MESSAGE));
961                 msg.msg_type = MSG_VLP;
962                 msg.param.pword[0] = VLP_REGINT;
963                 msg.param.pword[1] = newINT->ID;
964                 sprintf(msg.param.pstr, "logi%d.net", newint);
965                 write(net_sock, &msg, sizeof(MESSAGE)); 
966
967                 Interpreters.append(newINT);
968                 newINT->notify = new QSocketNotifier(newINT->sock,
969                                                         QSocketNotifier::Read);
970                 connect(newINT->notify, SIGNAL(activated(int)), this,
971                                                         SLOT(IntMessage(int)));
972                 if (info_messages)
973                         WriteMessage("INTERPRETER successfully connected");
974         } else {
975                 WriteMessage("Cannot connect interpreter");
976         }
977
978         return newINT;
979 }
980
981 /**
982  * Allocates remote instance of interpreter
983  * @param interp Interpreter slot 
984  * @param on Node Number
985  */
986 void QKernel::RemoteInstance(InterpEntry *interp, int on)
987 {
988         MESSAGE m;
989
990         m.msg_type = MSG_NET;
991         m.param.pword[0] = NET_NODE_EXIST;
992         m.param.pword[1] = on;
993         m.param.pword[2] = interp->ID;
994         write(net_sock, &m, sizeof(MESSAGE));
995         bzero(&m, sizeof(MESSAGE));
996         while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
997                 read(net_sock, &m, sizeof(MESSAGE));
998
999          /* means node exists */
1000         if (m.param.pword[1] == 1) {
1001                 m.msg_type = MSG_NET;
1002                 m.param.pword[0] = NET_TRANSMIT_CODE;
1003                 m.param.pword[1] = interp->ID;
1004                 m.param.pword[2] = on;
1005                 strcpy(m.param.pstr, interp->fullname);
1006                 write(net_sock, &m, sizeof(MESSAGE));
1007
1008                 Net_Notify->setEnabled(FALSE);
1009                 while ((m.msg_type != MSG_NET) ||
1010                         (m.param.pword[0] != NET_TRANSMITTED))
1011                         read(net_sock, &m, sizeof(MESSAGE));
1012
1013                 m.msg_type = MSG_NET;
1014                 m.param.pword[0] = NET_PROPAGATE;
1015                 m.param.pword[1] = MSG_VLP;
1016                 m.param.pword[2] = NodeNumber;
1017                 m.param.pword[3] = 0;
1018                 m.param.pword[4] = on;
1019                 m.param.pword[5] = 0;
1020                 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1021                 m.param.pword[7] = interp->ID;
1022                 strcpy(m.param.pstr, interp->shortname);
1023                 write(net_sock, &m, sizeof(MESSAGE));
1024
1025                 read(net_sock, &m, sizeof(MESSAGE));
1026                 while (1) {
1027                         if ((m.param.pword[0] == NET_PROPAGATE) &&
1028                                 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1029                                 interp->RInstances[on] = m.param.pword[7];
1030                                 break;
1031                         }
1032                         read(net_sock, &m, sizeof(MESSAGE));
1033                 }
1034
1035                 Net_Notify->setEnabled(TRUE);
1036
1037                 /*bzero(&m, sizeof(MESSAGE));*/
1038                 m.msg_type = MSG_VLP;
1039                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1040                 m.param.pword[1] = interp->RInstances[on];
1041                 write(interp->sock, &m, sizeof(MESSAGE));
1042         } else { /* There is no such a node! */
1043                 char s[255];
1044                 sprintf(s, "Warning: Node number %d not found!", on); 
1045                 WriteMessage(s);
1046                 WriteMessage("Allocating O-process on the local node");
1047                 bzero(&m, sizeof(MESSAGE));
1048                 m.msg_type = MSG_VLP;
1049                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1050                 m.param.pword[1] = interp->ID;
1051                 write(interp->sock, &m, sizeof(MESSAGE));
1052         }
1053 }
1054
1055 /**
1056  * Closes all remote instances
1057  */
1058 void QKernel::CloseInstances(InterpEntry *e)
1059 {
1060         MESSAGE msg;
1061         int i;
1062
1063         if (info_messages)
1064                 WriteMessage("Closing remote instances");
1065
1066         for(i=0; i < MAXINSTANCES; i++)
1067                 if (e->RInstances[i]>=0) {
1068                         msg.msg_type = MSG_NET;
1069                         msg.param.pword[0] = NET_PROPAGATE;
1070                         msg.param.pword[1] = MSG_VLP;
1071                         msg.param.pword[2] = NodeNumber;
1072                         msg.param.pword[4] = i;
1073                         msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1074                         msg.param.pword[7] = e->RInstances[i];
1075                         write(net_sock, &msg, sizeof(MESSAGE));
1076                 }
1077 }
1078
1079 /**
1080  * Displays information about virtual machine
1081  */
1082 void QKernel::on_actionInfo_triggered()
1083 {
1084         MESSAGE m;
1085
1086         WriteMessage(CharLine);
1087         WriteMessage("### Virtual Machine Information ###");
1088         m.msg_type = MSG_NET;
1089         m.param.pword[0] = NET_GET_INFO;
1090         write(net_sock, &m, sizeof(MESSAGE));
1091         wait_for_info = TRUE;
1092 }
1093
1094 }
1095 }
1096
1097 /**
1098  * Program main function
1099  * All program arguments but the first one (argv[0]: program name) are saved and
1100  * passed to all dependent programs on their invocation.
1101  * @param argc Number of program arguments
1102  * @param argv Program arguments
1103  */
1104 int main(int argc, char **argv)
1105 {
1106         XInitThreads();
1107
1108         QApplication * app = new QApplication(argc, argv);
1109         loglan::vlp::QKernel kernel(argc, argv);
1110         kernel.show();
1111         
1112         return app->exec();
1113 }