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