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