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