Fix warnings
[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 (unsigned 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         QString program = getHomeDir();
308         program += "/modules/loggraph";
309
310         pid_t pid = fork();
311         if (pid == 0) {
312                 if (execl(program.toStdString().c_str(),
313                         program.toStdString().c_str(),
314                         sk,
315                         myargs[0],
316                         myargs[1],
317                         myargs[2],
318                         myargs[3],
319                         myargs[4],
320                         NULL
321                 ) == -1) {
322
323                         WriteMessage("Executing loggraph failed!");
324                         WriteMessage("Exiting...");
325                         sleep(2);
326                         on_actionQuit_triggered();
327                 }
328         }
329         else if (pid < 0) {
330                 WriteMessage("fork(loggraph) failed!");
331                 WriteMessage("Exiting...");
332                 sleep(2);
333                 on_actionQuit_triggered();
334                 exit(3);
335         }
336 }
337
338 /**
339  * Invokes net module
340  */
341 void QKernel::RunNetModule()
342 {
343         struct sockaddr_un svr;
344         int len;
345         int on;
346         int sock;
347
348         QString program = getHomeDir();
349         program += "/modules/lognet";
350
351         pid_t pid = fork();
352         if (pid == 0) {
353                 if (execl(program.toStdString().c_str(),
354                         program.toStdString().c_str(),
355                         getNetModuleSocket(),
356                         getConfigFilePath().toStdString().c_str(),
357                         myargs[0],
358                         myargs[1],
359                         myargs[2],
360                         myargs[3],
361                         myargs[4],
362                         NULL
363                 ) == -1) {
364
365                         WriteMessage("Executing lognet failed!");
366                         WriteMessage("Exiting...");
367                         sleep(2);
368                         on_actionQuit_triggered();
369                 }
370         }
371         else if (pid < 0) {
372                 WriteMessage("fork(lognet) failed!");
373                 WriteMessage("Exiting...");
374                 sleep(2);
375                 on_actionQuit_triggered();
376                 exit(3);
377         }
378
379         /* -------- socket for NET module -------- */
380         unlink(getNetModuleSocket());
381         sock = socket(AF_UNIX, SOCK_STREAM, 0);
382         bzero(&svr, sizeof(svr));
383         svr.sun_family = AF_UNIX;
384         strcpy(svr.sun_path, getNetModuleSocket());
385         len = strlen(svr.sun_path) + sizeof(svr.sun_family);
386         bind(sock, (struct sockaddr*)&svr, len);
387         listen(sock, 5);
388
389         net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
390         // close(sock); 
391         if (net_sock != 0) {
392                 WriteMessage("NETWORK successfully connected");
393                 fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock, F_GETFL, 0));
394                 on = 1;
395                 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
396         } else {
397                 WriteMessage("Cannot connect NETWORK resources");
398                 WriteMessage("Exiting...");
399                 sleep(2);
400                 on_actionQuit_triggered();
401         }
402 }
403
404 /**
405  * Connects to the specified address
406  * Additional window is displayed to connect to the specified address
407  */
408 void QKernel::on_actionConnect_triggered()
409 {
410         MESSAGE m;
411
412         ConnectDialog dialog(this);
413         dialog.setWindowTitle("IP Address:");
414
415         if (dialog.exec()) {
416                 m.msg_type = MSG_NET;
417                 m.param.pword[0] = NET_CONNECT_TO;
418                 strcpy(m.param.pstr, dialog.getAddress().toStdString().c_str());
419                 write(net_sock, &m, sizeof(MESSAGE));
420         }
421 }
422
423 /**
424  * Disconnects from virtual machine
425  */
426 void QKernel::on_actionDisconnect_triggered()
427 {
428         MESSAGE msg;
429
430         if (info_messages)
431                 WriteMessage("Disconnecting from virtual machine");
432
433         msg.msg_type = MSG_NET;
434         msg.param.pword[0] = NET_DISCONNECT;
435         write(net_sock, &msg, sizeof(MESSAGE));
436 }
437
438 /**
439  * Quits process. Closes VLP. Shows additional window to confirm exit. 
440  */
441 void QKernel::on_actionQuit_triggered()
442 {
443         MESSAGE msg;
444
445         QMessageBox::StandardButton response = QMessageBox::question(this,
446                 "Close VLP",
447                 "Terminate VLP ?",
448                 QMessageBox::Ok | QMessageBox::Cancel
449         );
450
451
452         if (response == QMessageBox::Cancel) {
453                 return;
454         }
455         /*
456         msg.msg_type = MSG_NET;
457         msg.param.pword[0] = NET_DISCONNECT;
458         write(net_sock, &msg, sizeof(MESSAGE));*/
459         delete Net_Notify;
460
461         msg.msg_type = MSG_NET;
462         msg.param.pword[0] = NET_EXIT;
463         write(net_sock, &msg, sizeof(MESSAGE));
464         /*  ::close(net_sock);*/
465         QApplication::instance()->quit();
466 }
467
468 /**
469  * Sends message to node.
470  * Additional window is displayed to set Node Number of node where send message,
471  * and textfield to enter message.
472  */
473 void QKernel::on_actionMessage_triggered()
474 {
475         QDialog *dlg;
476         QLineEdit *nodenr;
477         MESSAGE m;
478
479         dlg = new QDialog(this, Qt::Dialog);
480         dlg->setWindowTitle("Send message to node");
481
482         nodenr = new QLineEdit("number", dlg);
483         nodenr->setGeometry(90, 10, 50, 30);
484         nodenr->setText("");
485
486         QLabel *tmpQLabel;
487         tmpQLabel = new QLabel("Node number:", dlg);
488         tmpQLabel->setGeometry(10, 10, 77, 30);
489
490         tmpQLabel = new QLabel("Message:", dlg);
491         tmpQLabel->setGeometry(10, 50, 70, 30);
492
493         QLineEdit *msg;
494         msg = new QLineEdit("", dlg);
495         msg->setGeometry(80, 60, 330, 30);
496
497         QPushButton *ob;
498         ob = new QPushButton("Send", dlg);
499         ob->setGeometry(230, 10, 80, 30);
500         ob->setDefault(TRUE);
501         
502         QPushButton *cb;
503         cb = new QPushButton("Cancel", dlg);
504         cb->setGeometry(330, 10, 80, 30);
505         dlg->resize(430, 110);
506         connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
507         connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
508
509         if (dlg->exec()) {
510                 m.msg_type = MSG_NET;
511                 m.param.pword[0] = NET_PROPAGATE;
512                 m.param.pword[1] = MSG_VLP;
513                 m.param.pword[2] = NodeNumber;
514                 m.param.pword[4] = atoi(nodenr->text().toAscii().data());
515                 m.param.pword[6] = VLP_WRITE;
516                 strcpy(m.param.pstr, msg->text().toAscii().data());
517                 write(net_sock, &m, sizeof(MESSAGE));
518         }
519 }
520
521 /**
522  * Kills interpreter.
523  * Additional window is displayed to get ID of interpreter which should be
524  * killed.
525  */
526 void QKernel::on_actionKill_triggered()
527 {
528         KillInterpreterDialog dialog(this);
529         dialog.setWindowTitle("Kill interpreter");
530
531         MESSAGE m;
532         InterpEntry *interpreter;
533
534         if (dialog.exec()) {
535                 m.msg_type = MSG_INT;
536                 m.param.pword[0] = INT_KILL;
537                 interpreter = findINTbyID(dialog.getInterpreterId());
538                 if (interpreter != NULL) {
539                         if (!(interpreter->remote))
540                                 write(interpreter->sock, &m, sizeof(MESSAGE));
541                         else
542                                 WriteMessage("This is a remote instance of a program!");
543                 }
544                 else {
545                         WriteMessage("Interpreter not found");
546                 }
547         }
548 }
549
550 /**
551  * Sends message to the net module.
552  */
553 void QKernel::NetMessage()
554 {
555         
556         /* TODO: It has to be rewritten */
557         MESSAGE msg;
558         int cnt;
559         char ss[255];
560         InterpEntry *pom;
561
562         cnt = read(net_sock, &msg, sizeof(MESSAGE));
563         if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
564                 switch(msg.param.pword[0]) {
565                 case NET_CSWRITELN:
566                         WriteMessage(msg.param.pstr);
567                         break;
568                 case NET_PROPAGATE: 
569                         switch(msg.param.pword[1]) {
570                         case MSG_INT:
571                                 /*  pom = find_link_by_ID(msg.param.pword[5]);
572                                 msg.msg_type = MSG_NET;
573                                 msg.param.pword[0] = NET_PROPAGATE;
574                                 send_int(pom, &msg);*/
575                                 break;
576                         case MSG_VLP:
577                                 switch(msg.param.pword[6]) {
578                                 case VLP_WRITE:
579                                         QApplication::beep();
580                                         WriteMessage(CharLine);
581                                         WriteMessage(
582                                                 "### Incoming Messsage ###");
583                                         sprintf(ss, "Mesg from Node %d: %s",
584                                                         msg.param.pword[2],
585                                                         msg.param.pstr);
586                                         WriteMessage(ss);
587                                         WriteMessage(CharLine);
588                                         break;
589                                 case VLP_REMOTE_INSTANCE:
590                                         sprintf(ss, "%s/%s", getRemoteDir(),
591                                                                 msg.param.pstr);
592
593                                         if (info_messages) { 
594                                                 WriteMessage("Running program:");
595                                                 WriteMessage(ss);
596                                         }
597                                         pom = RunIntModule(ss, 1);
598                                         if (pom != NULL) {
599                                                 pom->p_ctx.node = msg.param.pword[2];
600                                                 pom->p_ctx.program_id = 
601                                                         msg.param.pword[7];
602                                                 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
603                                         }
604                                         break;
605                                 case VLP_CLOSE_INSTANCE:
606                                         msg.msg_type = MSG_INT;
607                                         msg.param.pword[0] = INT_CLOSE_INSTANCE;
608                                         pom = findINTbyID(msg.param.pword[7]);
609                                         if (pom != NULL) {
610                                                 write(pom->sock, &msg,
611                                                         sizeof(MESSAGE));
612                                                 MESSAGE m1;
613                                                 m1.msg_type = MSG_VLP;
614                                                 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
615                                                 m1.param.pword[1] = pom->ID;
616                                                 write(net_sock, &m1,
617                                                         sizeof(MESSAGE));
618                                         } else {
619                                                 WriteMessage("Instance not found"); 
620                                         }
621                                         break; 
622                                 } /* VLP switch */
623                         }/* switch */
624                         break;
625                 case NET_CONNECTIONS:
626                         ActiveConnections = msg.param.pword[1];
627                         WriteMessage(msg.param.pstr);
628                         if (!synchro) 
629                                 synchro = TRUE;
630                         break;
631                 case NET_INFO:
632                         /* TODO: It has to be rewritten */
633                         if (wait_for_info) {
634                                 QString poms, poms1, poms2;
635                                 poms.sprintf("%s", msg.param.pstr);
636                                 while (poms.length() > 0) {
637                                         cnt = poms.indexOf(';');
638                                         if (cnt!=-1) {
639                                                 poms1 = poms.left(cnt);
640                                                 poms = poms.right(poms.length() - cnt - 1);
641                                                 cnt = poms1.indexOf('=');
642                                                 if (cnt != -1) {
643                                                         poms2 = poms1.left(cnt);
644                                                         poms1 = poms1.right(poms1.length() - cnt - 1);
645                                                         sprintf(ss, "Node: %s Addr: %s", poms2.toStdString().c_str(), poms1.toStdString().c_str());
646                                                         WriteMessage(ss); 
647                                                 }
648                                         } 
649                                 }
650                         } 
651                         break;
652                 case NET_INFO_END:
653                         wait_for_info = FALSE;
654                         WriteMessage(CharLine);
655                         break;
656                 } /* switch */
657         }
658 }
659
660 /**
661  * Sends message to the interpreter program.
662  * @param sock Interpreter socket to whom the message will be send.
663  */
664 void QKernel::IntMessage(int sock)
665 {
666         MESSAGE msg;
667         int cnt;
668         InterpEntry *e;
669
670         cnt = read(sock, &msg, sizeof(MESSAGE));
671         e = findINTbySocket(sock);
672         if ((cnt > 0) && (e != NULL)) {
673                 switch (msg.msg_type) { 
674                 case MSG_GRAPH:
675                         if (msg.param.pword[0] == GRAPH_ALLOCATE) {
676                                 RunGraphModule(msg.param.pstr);
677                         }
678                         break;
679                 case MSG_NET:
680                         write(net_sock, &msg, sizeof(MESSAGE));
681                         break;
682                 case MSG_VLP:
683                         switch(msg.param.pword[0]) {
684                         case VLP_REMOTE_INSTANCE_PLEASE:
685                                 RemoteInstance(e, msg.param.pword[2]);
686                                 break;
687                         }/* switch */
688                         break;
689                 case MSG_INT:
690                         switch(msg.param.pword[0]) {
691                         case INT_EXITING:
692                                 char ss[255];
693
694                                 MESSAGE m;
695                                 m.msg_type = MSG_VLP;
696                                 m.param.pword[0] = VLP_INTERPRETER_DOWN;
697                                 m.param.pword[1] = e->ID;
698                                 write(net_sock, &m, sizeof(MESSAGE));
699                                 if (e->remote == 0)
700                                         CloseInstances(e);
701                                 delete e->notify;
702                                 ::close(e->sock);
703                                 /* TODO: Check this */
704                                 Interpreters.removeOne(e);
705                                 delete e;
706
707                                 if (info_messages) {
708                                         sprintf(ss, "%s : End of program "
709                                                 "execution", msg.param.pstr);
710                                         WriteMessage(ss);
711                                 }
712                                 break;
713                         case INT_CTX_REQ:
714                                 msg.msg_type = MSG_INT;
715                                 msg.param.pword[0] = INT_CTX;
716                                 msg.param.pword[1] = NodeNumber;
717                                 msg.param.pword[2] = e->ID;
718                                 if (e->remote) {
719                                         msg.param.pword[3] = e->p_ctx.node;
720                                         msg.param.pword[4] = 
721                                                         e->p_ctx.program_id;
722                                 }
723                                 write(sock, &msg, sizeof(MESSAGE)); 
724                                 break;
725                         };
726                         break;
727                 }
728         }
729 }
730
731 /**
732  * Writes message to kernel logger.
733  * @parame msg String with message to log
734  */
735 void QKernel::WriteMessage(const char *msg)
736 {
737         int x;
738 //      int y;
739         x = desktop->textCursor().blockNumber();
740 //      y = desktop->textCursor().columnNumber();
741
742         if (x > 100) {
743                 desktop->clear();
744         }
745         
746         desktop->setReadOnly(FALSE);
747         desktop->append(msg);
748         desktop->setReadOnly(TRUE);
749
750         QTextCursor tmpCursor = desktop->textCursor();
751         tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
752         desktop->setTextCursor(tmpCursor);
753
754         desktop->repaint();
755         
756         if (desktop->document()->blockCount() > 100) {
757                 desktop->clear();
758         }
759 }
760
761 /**
762  * Adds checkbox to menu item. If it is checked additional info messages are
763  * shown.
764  */
765 void QKernel::on_actionInfo_messages_triggered()
766 {
767         if (toolsMenu != NULL) {
768                 info_messages = actionInfo_messages->isChecked();
769                 actionInfo_messages->setChecked(info_messages);
770         }
771 }
772
773 /**
774  * Allows to set options in GUI window.
775  * Additional window is displayed to set kernel options which are saved in 
776  * vlp.cfg file in kernel executable directory.
777  */
778 void QKernel::on_actionOptions_triggered()
779 {
780         OptionsDialog optionsDialog(getConfigFilePath(), this);
781         if (optionsDialog.exec()) {
782                 optionsDialog.saveConfig(getConfigFilePath());
783
784                 loadConfig(getConfigFilePath());
785         }
786 }
787
788 /**
789  * Locks kernel program.
790  * Additional window is displayed to enter password and retype it. If both are
791  * same kernel window is locked.
792  */
793 void QKernel::on_actionLock_console_triggered()
794 {
795         LockDialog lockDialog(this);
796
797         if (lockDialog.exec()) {
798                 QString password = lockDialog.getPassword();
799                 if (lockDialog.getPassword().size() > 0) {
800                         strcpy(LockPasswd, password.toStdString().c_str());
801                         lockDialog.retype();
802
803                         if (lockDialog.exec()) {
804                                 password = lockDialog.getPassword();
805                                 if (password == LockPasswd) {
806                                         setLocked(TRUE);
807                                         WriteMessage("CONSOLE LOCKED");
808                                 } else {
809                                         QMessageBox msg(this);
810                                         msg.setText("Not matching!");
811                                         msg.setButtonText(0, "Close");
812                                         msg.show();
813                                         strcpy(LockPasswd, "");
814                                 }
815                         } else {
816                                 strcpy(LockPasswd, "");
817                         }
818                 }
819         }
820 }
821
822 /**
823  * Unlocks kernel program.
824  * Additional window is displayed to enter password. If it is correct, kernel 
825  * window is unlocked
826  */
827 void QKernel::on_actionUnlock_console_triggered()
828 {
829         LockDialog lockDialog(this);
830
831         if (lockDialog.exec()) {
832                 QString password = lockDialog.getPassword();
833                 if (strcmp(password.toStdString().c_str(), LockPasswd) == 0) {
834                         setLocked(FALSE);
835                         WriteMessage("CONSOLE UNLOCKED");
836                 } else {
837                         QMessageBox msg(this);
838                         msg.setText("Wrong password!");
839                         msg.setButtonText(0, "Close");
840                         msg.show();
841                 }
842         }
843 }
844
845 /**
846  * Finds Interpreter by its socket
847  * @param _id ID of the socket
848  * @return returns pointer to the found interpreter slot. NULL otherwise
849  */
850 InterpEntry *QKernel::findINTbySocket(int _id)
851 {
852         InterpEntry *pom = NULL;
853         
854         for (int i = 0; i < Interpreters.size(); i++) {
855                 if (Interpreters.at(i)->sock == _id) {
856                         pom = Interpreters.at(i);
857                         break;
858                 }
859         }
860
861         return pom;
862 }
863
864 /**
865  * Finds Interpreter by its ID.
866  * @param _id ID of the interpreter
867  * @return returns pointer to the found interpreter slot. NULL otherwise
868  */
869 InterpEntry *QKernel::findINTbyID(int _id)
870 {
871         InterpEntry *pom = NULL;
872         
873         for (int i = 0; i < Interpreters.size(); i++) {
874                 if (Interpreters.at(i)->ID == _id) {
875                         pom = Interpreters.at(i);
876                         break;
877                 }
878         }
879
880         return pom;
881 }
882
883
884 /**
885  * Connects interpreter
886  * @param ss full filepath with filename but without extension of the loglan
887  *           program to run.
888  * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
889  *          remote
890  * @return Returns pointer to newly created interpreter slot, or NULL on error.
891  */
892 InterpEntry *QKernel::RunIntModule(char *ss, int r)
893 {
894         char a[256], b[255];
895         struct sockaddr_un svr;
896         int len, sock, on;
897         unsigned int i;
898         int newint=-1;
899         char cmd[255];
900         FILE *cf;
901         MESSAGE msg;
902         InterpEntry *newINT = NULL;
903
904         strcpy(a, ss);
905         strcat(a, ".ccd");
906         cf = fopen(a, "r");
907         if (cf == NULL) {
908                 WriteMessage("File not found: no .ccd file");
909                 return NULL;
910         }
911         fclose(cf);
912
913         strcpy(a, ss);
914         strcat(a, ".pcd");
915         cf = fopen(a, "r");
916         if (cf == NULL) {
917                 WriteMessage("File not found: no .pcd file");
918                 return NULL;
919         }
920         fclose(cf);
921
922         newINT = new InterpEntry;
923         for(i = 0; i < MAXINSTANCES; i++) 
924                 newINT->RInstances[i] =- 1;
925
926         strcpy(b, rindex(ss, '/'));
927         for(i = 0; i < strlen(b); i++)
928                 b[i] = b[i+1];
929         if (info_messages) {
930                 sprintf(a, "%s : Start execution", b);
931                 WriteMessage(a); 
932         }
933
934         newint = freeINTid;
935         freeINTid++;
936         newINT->ID = newint;
937         strcpy(newINT->shortname, b);
938         strcpy(newINT->fullname, ss);
939
940         sprintf(a, "%s%d", IPATH, newint);
941         sprintf(cmd, "%s/modules/logint %s %s",
942                 getHomeDir(),
943                 a,
944                 ss);
945         if (r) {
946                 strcat(cmd, " r");
947         }
948         sprintf(b, " %s %s %s %s %s",
949                 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
950         strcat(cmd, b);
951         strcat(cmd, " &");
952
953         sock = socket(AF_UNIX, SOCK_STREAM, 0);
954         unlink(a);
955         bzero(&svr, sizeof(svr));
956         svr.sun_family = AF_UNIX;
957         strcpy(svr.sun_path, a);
958         len = strlen(svr.sun_path)+sizeof(svr.sun_family);
959         bind(sock, (struct sockaddr*)&svr, len);
960         listen(sock, 5);
961         system(cmd);
962         newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
963         //::close(sock);
964
965         if (newINT->sock > 0) { 
966                 fcntl(newINT->sock, F_SETFL, 
967                                 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
968                 on=1; 
969                 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
970                                                                 sizeof(on));
971                 if (r)
972                         newINT->remote = 1;
973                 else 
974                         newINT->remote = 0;
975
976                 bzero(&msg, sizeof(MESSAGE));
977                 msg.msg_type = MSG_VLP;
978                 msg.param.pword[0] = VLP_REGINT;
979                 msg.param.pword[1] = newINT->ID;
980                 sprintf(msg.param.pstr, "logi%d.net", newint);
981                 write(net_sock, &msg, sizeof(MESSAGE)); 
982
983                 Interpreters.append(newINT);
984                 newINT->notify = new QSocketNotifier(newINT->sock,
985                                                         QSocketNotifier::Read);
986                 connect(newINT->notify, SIGNAL(activated(int)), this,
987                                                         SLOT(IntMessage(int)));
988                 if (info_messages)
989                         WriteMessage("INTERPRETER successfully connected");
990         } else {
991                 WriteMessage("Cannot connect interpreter");
992         }
993
994         return newINT;
995 }
996
997 /**
998  * Allocates remote instance of interpreter
999  * @param interp Interpreter slot 
1000  * @param on Node Number
1001  */
1002 void QKernel::RemoteInstance(InterpEntry *interp, int on)
1003 {
1004         MESSAGE m;
1005         char s[255];
1006
1007         m.msg_type = MSG_NET;
1008         m.param.pword[0] = NET_NODE_EXIST;
1009         m.param.pword[1] = on;
1010         m.param.pword[2] = interp->ID;
1011         write(net_sock, &m, sizeof(MESSAGE));
1012         bzero(&m, sizeof(MESSAGE));
1013         while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
1014                 read(net_sock, &m, sizeof(MESSAGE));
1015
1016          /* means node exists */
1017         if (m.param.pword[1] == 1) {
1018                 m.msg_type = MSG_NET;
1019                 m.param.pword[0] = NET_TRANSMIT_CODE;
1020                 m.param.pword[1] = interp->ID;
1021                 m.param.pword[2] = on;
1022                 strcpy(m.param.pstr, interp->fullname);
1023                 write(net_sock, &m, sizeof(MESSAGE));
1024
1025                 Net_Notify->setEnabled(FALSE);
1026                 while ((m.msg_type != MSG_NET) ||
1027                         (m.param.pword[0] != NET_TRANSMITTED))
1028                         read(net_sock, &m, sizeof(MESSAGE));
1029
1030                 m.msg_type = MSG_NET;
1031                 m.param.pword[0] = NET_PROPAGATE;
1032                 m.param.pword[1] = MSG_VLP;
1033                 m.param.pword[2] = NodeNumber;
1034                 m.param.pword[3] = 0;
1035                 m.param.pword[4] = on;
1036                 m.param.pword[5] = 0;
1037                 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1038                 m.param.pword[7] = interp->ID;
1039                 strcpy(m.param.pstr, interp->shortname);
1040                 write(net_sock, &m, sizeof(MESSAGE));
1041
1042                 read(net_sock, &m, sizeof(MESSAGE));
1043                 while (1) {
1044                         if ((m.param.pword[0] == NET_PROPAGATE) &&
1045                                 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1046                                 interp->RInstances[on] = m.param.pword[7];
1047                                 break;
1048                         }
1049                         read(net_sock, &m, sizeof(MESSAGE));
1050                 }
1051
1052                 Net_Notify->setEnabled(TRUE);
1053
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->RInstances[on];
1058                 write(interp->sock, &m, sizeof(MESSAGE));
1059         } else { /* There is no such a node! */
1060                 sprintf(s, "Warning: Node number %d not found!", on); 
1061                 WriteMessage(s);
1062                 WriteMessage("Allocating O-process on the local node");
1063                 bzero(&m, sizeof(MESSAGE));
1064                 m.msg_type = MSG_VLP;
1065                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1066                 m.param.pword[1] = interp->ID;
1067                 write(interp->sock, &m, sizeof(MESSAGE));
1068         }
1069 }
1070
1071 /**
1072  * Closes all remote instances
1073  */
1074 void QKernel::CloseInstances(InterpEntry *e)
1075 {
1076         MESSAGE msg;
1077         int i;
1078
1079         if (info_messages)
1080                 WriteMessage("Closing remote instances");
1081
1082         for(i=0; i < MAXINSTANCES; i++)
1083                 if (e->RInstances[i]>=0) {
1084                         msg.msg_type = MSG_NET;
1085                         msg.param.pword[0] = NET_PROPAGATE;
1086                         msg.param.pword[1] = MSG_VLP;
1087                         msg.param.pword[2] = NodeNumber;
1088                         msg.param.pword[4] = i;
1089                         msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1090                         msg.param.pword[7] = e->RInstances[i];
1091                         write(net_sock, &msg, sizeof(MESSAGE));
1092                 }
1093 }
1094
1095 /**
1096  * Displays information about virtual machine
1097  */
1098 void QKernel::on_actionInfo_triggered()
1099 {
1100         MESSAGE m;
1101
1102         WriteMessage(CharLine);
1103         WriteMessage("### Virtual Machine Information ###");
1104         m.msg_type = MSG_NET;
1105         m.param.pword[0] = NET_GET_INFO;
1106         write(net_sock, &m, sizeof(MESSAGE));
1107         wait_for_info = TRUE;
1108 }
1109
1110 /**
1111  * Program main function
1112  * All program arguments but the first one (argv[0]: program name) are saved and
1113  * passed to all dependent programs on their invocation.
1114  * @param argc Number of program arguments
1115  * @param argv Program arguments
1116  */
1117 int main(int argc, char **argv)
1118 {
1119         XInitThreads();
1120
1121         QApplication * app = new QApplication(argc, argv);
1122         QKernel kernel(argc, argv);
1123         kernel.show();
1124         
1125         return app->exec();
1126 }