VLP-28 Removed helper comments from old code.
[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
33 #include <QtGui/QApplication>
34 #include <QtGui/QMainWindow>
35 #include <QtGui/QTextEdit>
36 #include <QtGui/QMenuBar>
37 #include <QtGui/QMessageBox>
38 #include <QtGui/QFileDialog>
39 #include <QtGui/QDialog>
40 #include <qstring.h>
41 #include <QtGui/QLabel>
42 #include <QtGui/QLineEdit>
43 #include <QtGui/QPushButton>
44 #include <QtGui/QRadioButton>
45 #include <QtGui/QGroupBox>
46 #include <QtGui/QVBoxLayout>
47 #include <QtCore/QList>
48 #include <QtGui/QListWidget>
49 #include <qfile.h>
50 #include <qcursor.h>
51 #include <QtCore/QSocketNotifier>
52 #include <qdir.h>
53
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <fcntl.h>
58
59 #include "genint1.h"
60 #include "comm.h"
61 #include "socu.h"
62 #include <netinet/in.h>
63
64 #include <libconfig.h>
65
66 /* File resides in top directory (where are Makefiles)*/
67 #include "../../config.h"
68
69 #define GPATH "loggr"
70 #define IPATH "logi"
71 #define NPATH "logn"
72 #define REMOTE_PATH "REMOTE"
73 #define MAXINTERP 20
74 #define MAXINSTANCES 256 
75
76
77 #define MESG_COL        0
78 #define WARN_COL        1
79 #define NORM_COL        2
80
81
82 char CharLine[25] = "________________________";
83 char myargs[5][255];
84
85 /**
86  * Interpreter slot
87  */
88 class InterpEntry {
89 public:
90         /** Interpreter identifier */
91         int ID;
92         /** Defines if interpreter is remote or not */
93         bool remote;
94         /* Program name */
95         char fullname[255];
96         char shortname[255];
97         
98         /* Socket */
99         int sock;
100         QSocketNotifier *notify;
101         /* IDs of my remote INT modules */
102         int RInstances[MAXINSTANCES];
103         /* Parent interpreter info */
104         ctx_struct p_ctx;
105 };
106
107 /**
108  * Connection slot
109  */
110 class ConnectEntry {
111 public:
112         char addr[256];
113         
114         ConnectEntry(char *s) {
115                 strcpy(addr, s);
116         };
117 };
118
119 QApplication *app;
120
121 /**
122  * Kernel class
123  */
124 class QKernel : public QMainWindow {
125         Q_OBJECT
126 public:
127         QTextEdit *desktop;
128         QMenuBar *bar;
129         QMenu *programMenu;
130         QMenu *machineMenu;
131         QMenu *toolsMenu;
132         char progdir[256];
133         int NodeNumber;
134         int ConType;
135
136         QKernel();
137
138         virtual void resizeEvent(QResizeEvent *ev);
139
140         void WriteMessage(char* msg);
141         void InitMessage();
142
143 public slots:
144         void n_impl();
145         void Run_Prog();
146         void Edit();
147         void Help();
148         void SetOptions();
149         void AddAddress();
150         void DelAddress();
151         void LockConsole();
152         void UnlockConsole();
153         void MessageToNode();
154         void QuitProc();
155         void NetMessage();
156         void IntMessage(int);
157         void KillInterpreter();
158         void Disconnect();
159         void SetMessages();
160         void Connect();
161         void Info();
162
163 protected:
164         virtual void closeEvent (QCloseEvent * e);
165
166 private:
167         QList<InterpEntry*> Interpreters;
168         QList<ConnectEntry*> ConnectList;
169         QListWidget *connections;
170         
171         /**
172          * number of working interpreters
173          * @attention Currently not in use
174          */
175         int Tasks;
176         
177         /**
178          * number of connected VLPs
179          */
180         int ActiveConnections;
181         bool LOCKED;
182         bool synchro;
183         bool wait_for_info;
184         char LockPasswd[25];
185         QAction * lockid;
186         QAction * unlockid;
187         QAction * qid;
188         QAction * cwid;
189         QAction * optid;
190         QAction * prid;
191         QAction * mid;
192         QAction * msgid;
193         QAction * toolsid;
194         QAction * hid;
195         
196         int net_sock;
197         int freeINTid;
198         QSocketNotifier *Net_Notify;
199         char HomeDir[255];
200         bool info_messages;
201
202         void LoadConfig(char *);
203         void RunGraphModule(char*);
204         void RunNetModule();
205         InterpEntry *findINTbySocket(int);
206         InterpEntry *findINTbyID(int);
207         InterpEntry *RunIntModule(char *ss, int r);
208         void RemoteInstance(InterpEntry*, int);
209         void CloseInstances(InterpEntry*);
210 };
211
212 /**
213  * Event invoked on program close.
214  * Closes application. Displays additional window to confirm exit.
215  */
216 void QKernel::closeEvent(QCloseEvent * e)
217 {
218         QuitProc();
219 }
220
221 /**
222  * Kernel program constructor.
223  * Prepares everything to work.
224  */
225 QKernel::QKernel()
226 {
227         QDir q(REMOTE_PATH);
228         char ss[255];
229
230         if (!q.exists()) {
231                 sprintf(ss, "mkdir %s", REMOTE_PATH);
232                 system(ss);
233         } 
234
235         info_messages = TRUE;
236         wait_for_info = FALSE;
237
238         setWindowTitle(PACKAGE_NAME);
239
240         QMenu * programMenu = NULL;
241         programMenu = menuBar()->addMenu("&Program");
242         programMenu->addAction("Execute", this, SLOT(Run_Prog()));
243         programMenu->addAction("Kill", this, SLOT(KillInterpreter()));
244         
245
246         machineMenu = menuBar()->addMenu("&Machine");
247         machineMenu->addAction("Message", this, SLOT(MessageToNode()));
248         machineMenu->addSeparator();
249         machineMenu->addAction("Connect", this, SLOT(Connect()));
250         machineMenu->addAction("Disconnect", this, SLOT(Disconnect()));
251         machineMenu->addAction("Info", this, SLOT(Info()));
252
253         toolsMenu = menuBar()->addMenu("&Tools");
254         cwid = toolsMenu->addAction("Editor", this, SLOT(Edit()));
255         hid = toolsMenu->addAction("Help", this, SLOT(Help()));
256         toolsMenu->addSeparator(); 
257         optid = toolsMenu->addAction("Options", this, SLOT(SetOptions()));
258         msgid = toolsMenu->addAction("Info messages", this, SLOT(SetMessages()));
259         msgid->setCheckable(TRUE);
260         msgid->setChecked(TRUE);
261         toolsMenu->addSeparator(); 
262         lockid = toolsMenu->addAction("Lock console", this, SLOT(LockConsole()));
263         unlockid = toolsMenu->addAction("Unlock console", this, 
264                                                         SLOT(UnlockConsole()));
265         unlockid->setDisabled(TRUE);
266         LOCKED = FALSE;
267
268         qid = menuBar()->addAction("&Quit", this, SLOT(QuitProc()));
269
270         desktop = new QTextEdit(this);
271         desktop->setReadOnly(TRUE);
272         QVBoxLayout * layout = new QVBoxLayout();
273         layout->setContentsMargins (3, 0, 3, 0);
274         layout->addWidget(desktop);
275         QWidget *window = new QWidget();
276         window->setLayout(layout);
277         setCentralWidget(window);
278
279         resize(400, 200);
280         Tasks = 0;
281         freeINTid = 1;
282         ActiveConnections = 0;
283         strcpy(LockPasswd, "");
284         LoadConfig("vlp.cfg");
285         RunNetModule();
286
287         Net_Notify = new QSocketNotifier(net_sock, QSocketNotifier::Read, this);
288         connect(Net_Notify, SIGNAL(activated(int)), this, SLOT(NetMessage()));
289 }
290
291 /**
292  * Event invoked on resizing kernel application window.
293  * @copydoc QWidget::resizeEvent(QResizeEvent*)
294  */
295 void QKernel::resizeEvent(QResizeEvent *ev)
296 {
297 //      QFrame::resizeEvent(ev);
298 //      if (desktop)
299 //              desktop->setGeometry(0, bar->height(), width(), 
300 //                                              height() - bar->height());
301 }
302
303 /**
304  * Displays window with information about not implemented functionality.
305  */
306 void QKernel::n_impl()
307 {
308         QMessageBox::information(this, "Function info", "This function is not "
309                                                 "implemented yet...", "Ok");
310 }
311
312 /**
313  * Loads configuration from the given file.
314  * @param fname Filename of the configuration file.
315  */
316 void QKernel::LoadConfig(char * fname)
317 {
318         config_t cfg;
319         config_setting_t *setting;
320         const char *str;
321
322         /* Hack for checking if file exists without using external libs.*/
323         FILE * file = fopen(fname, "rt");
324         if (!file) {
325                 fprintf(stderr, "Error: Cannot load configuration file %s!\n", 
326                                                                         fname);
327                 exit(3);
328         }
329         /* File exists, so file has been locked. Release it. */
330
331         config_init(&cfg);
332
333         /* Read the file. If there is an error, report it and exit. */
334         if (!config_read(&cfg, file)) {
335                 fprintf(stderr, "%s! In file %s, line %d\n", 
336                         config_error_text(&cfg), 
337                         config_error_file(&cfg), 
338                         config_error_line(&cfg));
339                 config_destroy(&cfg);
340                 fclose(file);
341                 exit(3);/* from original code. */
342         }
343
344         setting = config_lookup(&cfg, "node_number");
345         if (setting) {
346                 NodeNumber = config_setting_get_int(setting);
347         } else {
348                 fprintf(stderr, "%s! In file %s, '%s' was not found.\n", 
349                                         "Warning", fname, "node_number");
350                 config_destroy(&cfg);
351                 fclose(file);
352                 exit(3);
353         }
354
355         setting = config_lookup(&cfg, "type");
356         if (setting) {
357                 /* same as strcmp(..) == 0 */
358                 if (!strcmp(config_setting_get_string(setting), "explicit")) {
359                         ConType = 1;
360                 } else {
361                         ConType = 2;
362                 }
363         } else {
364                 fprintf(stderr, "%s! In file %s, '%s' was not found.\n", 
365                                                 "Warning", fname, "type");
366         }
367
368         setting = config_lookup(&cfg, "host");
369         if (setting) {
370                 switch(config_setting_type(setting)) {
371                 /* TODO: Deprecated. Made for back compatibility. */
372                 case CONFIG_TYPE_STRING:
373                         ConnectList.append(new ConnectEntry((char*)
374                                         config_setting_get_string(setting)));
375                         break;
376                 case CONFIG_TYPE_ARRAY: {
377                         int size = config_setting_length(setting);
378                         for (int i = 0; i < size; i++) {
379                                 ConnectList.append(new ConnectEntry((char*)
380                                         config_setting_get_string_elem(setting,
381                                                                         i)));
382                         }
383                         break;
384                 }
385                 default:
386                         fprintf(stderr, "%s! In file %s, bad entry type for %s."
387                                                         " Will not be read.\n", 
388                                                         "Error", fname, "host");
389                 }
390         } else {
391                 fprintf(stderr, "%s! In file %s, '%s' was not found.\n", 
392                                                 "Warning", fname, "host");
393         }
394
395         setting = config_lookup(&cfg, "progdir");
396         if (setting){
397                 strncpy(progdir, config_setting_get_string(setting), 256);
398         } else {
399                 fprintf(stderr, "%s! In file %s, '%s' was not found.\n", 
400                                                 "Warning", fname, "progdir");
401         }
402
403         setting = config_lookup(&cfg, "homedir");
404         if (setting) {
405                 strncpy(HomeDir, config_setting_get_string(setting), 255);
406         } else {
407                 fprintf(stderr, "%s! In file %s, '%s' was not found.\n", 
408                                                 "Warning", fname, "homedir");
409         }
410
411         config_destroy(&cfg);
412         fclose(file);
413 }
414
415 /**
416  * Executes program.
417  * Additional window id displayed to set which code to execute.
418  */
419 void QKernel::Run_Prog()
420 {
421         int i;
422         QString s = QFileDialog::getOpenFileName(this, "Execute", progdir, "*.log");
423
424         if (!s.isNull()) {
425                 i = s.indexOf(".log");
426
427                 if (i > 0)
428                         s.remove(i, 4);
429
430                 RunIntModule((char*)s.toAscii().data(), 0);
431         }
432 }
433
434 /**
435  * Invokes editor program
436  */
437 void QKernel::Edit()
438 {
439         char cmd[255];
440         sprintf(cmd, "%s/modules/logedit %s %s %s %s %s %s &", HomeDir, HomeDir, 
441                         myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
442         system(cmd);
443 }
444
445 /**
446  * Invokes help program
447  */
448 void QKernel::Help()
449 {
450         char cmd[255];
451         sprintf(cmd, "%s/modules/loghelp %s/doc %s %s %s %s %s &", HomeDir, 
452                 HomeDir, myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
453         system(cmd);
454 }
455
456 /**
457  * Invokes graphics module
458  */
459 void QKernel::RunGraphModule(char *sk)
460 {
461         char cmd[255];
462
463         sprintf(cmd, "%s/modules/loggraph %s %s %s %s %s %s", HomeDir, sk, 
464                         myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
465         strcat(cmd, " &");
466
467         if (system(cmd) != 0)
468                 WriteMessage("Cannot connect GRAPH resources");
469 }
470
471 /**
472  * Invokes net module
473  */
474 void QKernel::RunNetModule()
475 {
476         struct sockaddr_un svr;
477         int len, on;
478         int sock;
479         char cmd[255];
480         sprintf(cmd, "%s/modules/lognet %s %s %s %s %s %s", HomeDir, NPATH, 
481                         myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
482         strcat(cmd, " &");
483
484         /* -------- socket for NET module -------- */
485         unlink(NPATH);
486         sock = socket(AF_UNIX, SOCK_STREAM, 0);
487         bzero(&svr, sizeof(svr));
488         svr.sun_family = AF_UNIX;
489         strcpy(svr.sun_path, NPATH);
490         len = strlen(svr.sun_path) + sizeof(svr.sun_family);
491         bind(sock, (struct sockaddr*)&svr, len);      
492         listen(sock, 5);
493
494         if (system(cmd) == 0) {
495                 net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
496                 // close(sock); 
497                 if (net_sock != 0) {
498                         WriteMessage("NETWORK successfully connected");
499                         fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock,
500                                                                 F_GETFL, 0));
501                         on=1;
502                         setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY,
503                                                         (char*)&on, sizeof(on)); 
504                 } else {
505                         WriteMessage("Cannot connect NETWORK resources");
506                         WriteMessage("Exiting...");
507                         sleep(2);
508                         QuitProc(); 
509                 }
510         /* system OK */
511         } else {
512                 WriteMessage("Cannot connect NETWORK resources");
513                 WriteMessage("Exiting...");
514                 sleep(2);
515                 QuitProc(); 
516         }
517 }
518
519 /**
520  * Connects to the specified address
521  * Additional window is displayed to connect to the specified address
522  */
523 void QKernel::Connect()
524 {
525         QDialog d(this, Qt::Dialog);
526         QLabel lab("IP Address:", &d);
527         QLineEdit ed("", &d);
528         QPushButton ob("", &d);
529         QPushButton cb("", &d);
530         MESSAGE m;
531
532         ob.setGeometry(30, 60, 80, 30);
533         ob.setText("Ok");
534         ob.setDefault(TRUE);
535         lab.setGeometry(10, 10, 60, 30);
536         lab.setText("Address");
537         ed.setGeometry(70, 10, 140, 30);
538         cb.setGeometry(130, 60, 80, 30);
539         cb.setText("Cancel");
540         d.resize(240, 100);
541
542         connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
543         connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
544         if (d.exec()) {
545                 m.msg_type = MSG_NET;
546                 m.param.pword[0] = NET_CONNECT_TO;
547                 strcpy(m.param.pstr, ed.text().toAscii().data());
548                 write(net_sock, &m, sizeof(MESSAGE)); 
549         }
550 }
551
552 /**
553  * Disconnects from virtual machine
554  */
555 void QKernel::Disconnect()
556 {
557         MESSAGE msg;
558
559         if (info_messages)
560                 WriteMessage("Disconnecting from virtual machine");
561
562         msg.msg_type = MSG_NET;
563         msg.param.pword[0] = NET_DISCONNECT;
564         write(net_sock, &msg, sizeof(MESSAGE));
565 }
566
567 /**
568  * Quits process. Closes VLP. Shows additional window to confirm exit. 
569  */
570 void QKernel::QuitProc()
571 {
572         MESSAGE msg;
573
574         if (QMessageBox::question(this, "Close VLP", "Terminate VLP ?", 
575                 QMessageBox::Yes, QMessageBox::No, 0) == QMessageBox::No) {
576                 return;
577         }
578         
579         if (!LOCKED) {
580                 /* 
581                 msg.msg_type = MSG_NET;
582                 msg.param.pword[0] = NET_DISCONNECT;
583                 write(net_sock, &msg, sizeof(MESSAGE));*/
584                 delete Net_Notify;
585
586                 msg.msg_type = MSG_NET;
587                 msg.param.pword[0] = NET_EXIT;
588                 write(net_sock, &msg, sizeof(MESSAGE));
589                 /*  ::close(net_sock);*/
590                 app->quit();
591         }
592 }
593
594 /**
595  * Adds IP address to the configuration.
596  * Additional window is displayed to add address to the list
597  */
598 void QKernel::AddAddress()
599 {
600         QDialog d(this, Qt::Dialog);
601         QLabel lab("IP Address:", &d);
602         QLineEdit ed("", &d);
603         QPushButton ob("", &d);
604         QPushButton cb("", &d);
605
606         if (connections) {
607                 ob.setGeometry(30, 60, 80, 30);
608                 ob.setText("Ok");
609                 ob.setDefault(TRUE);
610                 lab.setGeometry(10, 10, 60, 30);
611                 lab.setText("Address");
612                 ed.setGeometry(70, 10, 140, 30);
613                 cb.setGeometry(130, 60, 80, 30);
614                 cb.setText("Cancel");
615                 d.resize(240, 100);
616                 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
617                 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject())); 
618                 if (d.exec())
619                         if (strcmp(ed.text().toAscii().data(), "") != 0) {
620                                 connections->addItem(ed.text());
621                         }
622         }
623 }
624
625 /**
626  * Deletes current address from available connections.
627  */
628 void QKernel::DelAddress()
629 {
630         if (connections) {
631                 if (connections->currentRow() != -1) {
632                         /* TODO: Checki if this work correctly after porting */
633                         connections->removeItemWidget(connections->currentItem());
634                 }
635         }
636 }
637
638 /**
639  * Sends message to node.
640  * Additional window is displayed to set Node Number of node where send message,
641  * and textfield to enter message.
642  */
643 void QKernel::MessageToNode()
644 {
645         QDialog *dlg;
646         QLineEdit *nodenr;
647         MESSAGE m;
648
649         dlg = new QDialog(this, Qt::Dialog);
650         dlg->setWindowTitle("Send message to node");
651
652         nodenr = new QLineEdit("number", dlg);
653         nodenr->setGeometry(90, 10, 50, 30);
654         nodenr->setText("");
655
656         QLabel *tmpQLabel;
657         tmpQLabel = new QLabel("Node number:", dlg);
658         tmpQLabel->setGeometry(10, 10, 77, 30);
659
660         tmpQLabel = new QLabel("Message:", dlg);
661         tmpQLabel->setGeometry(10, 50, 70, 30);
662
663         QLineEdit *msg;
664         msg = new QLineEdit("", dlg);
665         msg->setGeometry(80, 60, 330, 30);
666
667         QPushButton *ob;
668         ob = new QPushButton("Send", dlg);
669         ob->setGeometry(230, 10, 80, 30);
670         ob->setDefault(TRUE);
671         
672         QPushButton *cb;
673         cb = new QPushButton("Cancel", dlg);
674         cb->setGeometry(330, 10, 80, 30);
675         dlg->resize(430, 110);
676         connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
677         connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
678
679         if (dlg->exec()) {
680                 m.msg_type = MSG_NET;
681                 m.param.pword[0] = NET_PROPAGATE;
682                 m.param.pword[1] = MSG_VLP;
683                 m.param.pword[2] = NodeNumber;
684                 m.param.pword[4] = atoi(nodenr->text().toAscii().data());
685                 m.param.pword[6] = VLP_WRITE;
686                 strcpy(m.param.pstr, msg->text().toAscii().data());
687                 write(net_sock, &m, sizeof(MESSAGE));
688         }
689 }
690
691 /**
692  * Kills interpreter.
693  * Additional window is displayed to get ID of interpreter which should be
694  * killed.
695  */
696 void QKernel::KillInterpreter()
697 {
698         QDialog *dlg;
699         QLineEdit *nodenr;
700         MESSAGE m;
701         InterpEntry *pom;
702
703         dlg = new QDialog(this, Qt::Dialog);
704         dlg->setWindowTitle("Kill interpreter");
705
706         nodenr = new QLineEdit("", dlg); 
707         nodenr->setGeometry(90, 10, 50, 30);
708
709         QLabel * tmpQLabel = new QLabel("Interp. ID:", dlg);
710         tmpQLabel->setGeometry(10, 10, 77, 30);
711
712         QPushButton * ob = new QPushButton("Kill", dlg);
713         ob->setGeometry( 160, 10, 80, 30);
714         ob->setDefault(TRUE);
715
716         QPushButton * cb = new QPushButton("Cancel", dlg);
717         cb->setGeometry(260, 10, 80, 30);
718         dlg->resize(360, 50);
719
720         connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
721         connect(cb, SIGNAL(clicked()), dlg, SLOT(reject())); 
722
723         if (dlg->exec()) {
724                 m.msg_type = MSG_INT;
725                 m.param.pword[0] = INT_KILL;
726                 pom = findINTbyID(atoi(nodenr->text().toAscii().data()));
727                 if (pom != NULL) {
728                         if (!(pom->remote))
729                                 write(pom->sock, &m, sizeof(MESSAGE));
730                         else
731                                 WriteMessage("This is a remote instance of "
732                                                                 "a program!");
733                 }
734                 else {
735                         WriteMessage("Interpreter not found");
736                 }
737         }
738 }
739
740 /**
741  * Sends message to the net module.
742  */
743 void QKernel::NetMessage()
744 {
745         
746         /* TODO: It has to be rewritten */
747         MESSAGE msg;
748         int cnt;
749         char ss[255];
750         InterpEntry *pom;
751
752         cnt = read(net_sock, &msg, sizeof(MESSAGE));
753         if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
754                 switch(msg.param.pword[0]) {
755                 case NET_CSWRITELN:
756                         WriteMessage(msg.param.pstr);
757                         break;
758                 case NET_PROPAGATE: 
759                         switch(msg.param.pword[1]) {
760                         case MSG_INT:
761                                 /*  pom = find_link_by_ID(msg.param.pword[5]);
762                                 msg.msg_type = MSG_NET;
763                                 msg.param.pword[0] = NET_PROPAGATE;
764                                 send_int(pom, &msg);*/
765                                 break;
766                         case MSG_VLP:
767                                 switch(msg.param.pword[6]) {
768                                 case VLP_WRITE:
769                                         QApplication::beep();
770                                         WriteMessage(CharLine);
771                                         WriteMessage(
772                                                 "### Incoming Messsage ###");
773                                         sprintf(ss, "Mesg from Node %d: %s",
774                                                         msg.param.pword[2],
775                                                         msg.param.pstr);
776                                         WriteMessage(ss);
777                                         WriteMessage(CharLine);
778                                         break;
779                                 case VLP_REMOTE_INSTANCE:
780                                         sprintf(ss, "%s/%s", REMOTE_PATH,
781                                                                 msg.param.pstr);
782
783                                         if (info_messages) { 
784                                                 WriteMessage("Running program:");
785                                                 WriteMessage(ss);
786                                         }
787                                         pom = RunIntModule(ss, 1);
788                                         if (pom != NULL) {
789                                                 pom->p_ctx.node = msg.param.pword[2];
790                                                 pom->p_ctx.program_id = 
791                                                         msg.param.pword[7];
792                                                 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
793                                         }
794                                         break;
795                                 case VLP_CLOSE_INSTANCE:
796                                         msg.msg_type = MSG_INT;
797                                         msg.param.pword[0] = INT_CLOSE_INSTANCE;
798                                         pom = findINTbyID(msg.param.pword[7]);
799                                         if (pom != NULL) {
800                                                 write(pom->sock, &msg,
801                                                         sizeof(MESSAGE));
802                                                 MESSAGE m1;
803                                                 m1.msg_type = MSG_VLP;
804                                                 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
805                                                 m1.param.pword[1] = pom->ID;
806                                                 write(net_sock, &m1,
807                                                         sizeof(MESSAGE));
808                                         } else {
809                                                 WriteMessage("Instance not found"); 
810                                         }
811                                         break; 
812                                 } /* VLP switch */
813                         }/* switch */
814                         break;
815                 case NET_CONNECTIONS:
816                         ActiveConnections = msg.param.pword[1];
817                         WriteMessage(msg.param.pstr);
818                         if (!synchro) 
819                                 synchro = TRUE;
820                         break;
821                 case NET_INFO:
822                         /* TODO: It has to be rewritten */
823                         if (wait_for_info) {
824                                 QString poms, poms1, poms2;
825                                 poms.sprintf("%s", msg.param.pstr);
826                                 while (poms.length() > 0) {
827                                         cnt = poms.indexOf(';');
828                                         if (cnt!=-1) {
829                                                 poms1 = poms.left(cnt);
830                                                 poms = poms.right(poms.length() - cnt - 1);
831                                                 cnt = poms1.indexOf('=');
832                                                 if (cnt != -1) {
833                                                         poms2 = poms1.left(cnt);
834                                                         poms1 = poms1.right(
835                                                                 poms1.length() -
836                                                                 cnt - 1);
837                                                         sprintf(ss, "Node: %s Addr: %s", poms2.data(), poms1.data());
838                                                         WriteMessage(ss); 
839                                                 }
840                                         } 
841                                 }
842                         } 
843                         break;
844                 case NET_INFO_END:
845                         wait_for_info = FALSE;
846                         WriteMessage(CharLine);
847                         break;
848                 } /* switch */
849         }
850 }
851
852 /**
853  * Sends message to the interpreter program.
854  * @param sock Interpreter socket to whom the message will be send.
855  */
856 void QKernel::IntMessage(int sock)
857 {
858         MESSAGE msg;
859         int cnt;
860         InterpEntry *e;
861
862         cnt = read(sock, &msg, sizeof(MESSAGE));
863         e = findINTbySocket(sock);
864         if ((cnt > 0) && (e != NULL)) {
865                 switch (msg.msg_type) { 
866                 case MSG_GRAPH:
867                         if (msg.param.pword[0] == GRAPH_ALLOCATE) {
868                                 RunGraphModule(msg.param.pstr);
869                         }
870                         break;
871                 case MSG_NET:
872                         write(net_sock, &msg, sizeof(MESSAGE));
873                         break;
874                 case MSG_VLP:
875                         switch(msg.param.pword[0]) {
876                         case VLP_REMOTE_INSTANCE_PLEASE:
877                                 RemoteInstance(e, msg.param.pword[2]);
878                                 break;
879                         }/* switch */
880                         break;
881                 case MSG_INT:
882                         switch(msg.param.pword[0]) {
883                         case INT_EXITING:
884                                 char ss[255];
885
886                                 MESSAGE m;
887                                 m.msg_type = MSG_VLP;
888                                 m.param.pword[0] = VLP_INTERPRETER_DOWN;
889                                 m.param.pword[1] = e->ID;
890                                 write(net_sock, &m, sizeof(MESSAGE));
891                                 if (e->remote == 0)
892                                         CloseInstances(e);
893                                 delete e->notify;
894                                 ::close(e->sock);
895                                 /* TODO: Check this */
896                                 Interpreters.removeOne(e);
897                                 delete e;
898
899                                 if (info_messages) {
900                                         sprintf(ss, "%s : End of program "
901                                                 "execution", msg.param.pstr);
902                                         WriteMessage(ss);
903                                 }
904                                 break;
905                         case INT_CTX_REQ:
906                                 msg.msg_type = MSG_INT;
907                                 msg.param.pword[0] = INT_CTX;
908                                 msg.param.pword[1] = NodeNumber;
909                                 msg.param.pword[2] = e->ID;
910                                 if (e->remote) {
911                                         msg.param.pword[3] = e->p_ctx.node;
912                                         msg.param.pword[4] = 
913                                                         e->p_ctx.program_id;
914                                 }
915                                 write(sock, &msg, sizeof(MESSAGE)); 
916                                 break;
917                         };
918                         break;
919                 }
920         }
921 }
922
923 /**
924  * Writes message to kernel logger.
925  * @parame msg String with message to log
926  */
927 void QKernel::WriteMessage(char *msg)
928 {
929         int x;
930         int y;
931         x = desktop->textCursor().blockNumber();
932         y = desktop->textCursor().columnNumber();
933
934         if (x > 100) {
935                 desktop->clear();
936         }
937         
938         desktop->setReadOnly(FALSE);
939         desktop->append(msg);
940         desktop->setReadOnly(TRUE);
941
942         QTextCursor tmpCursor = desktop->textCursor();
943         tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
944         desktop->setTextCursor(tmpCursor);
945
946         desktop->repaint();
947         
948         if (desktop->document()->blockCount() > 100) {
949                 desktop->clear();
950         }
951 }
952
953 /**
954  * Adds checkbox to menu item. If it is checked additional info messages are
955  * shown.
956  */
957 void QKernel::SetMessages()
958 {
959         if (toolsMenu != NULL) {
960                 if (msgid->isChecked()) {
961                         msgid->setChecked(FALSE);
962                         info_messages = FALSE;
963                 } else {
964                         msgid->setChecked(TRUE);
965                         info_messages = TRUE;
966                 }
967         }
968         /* bar->repaint(); */
969 }
970
971 /**
972  * Allows to set options in GUI window.
973  * Additional window is displayed to set kernel options which are saved in 
974  * vlp.cfg file in kernel executable directory.
975  */
976 void QKernel::SetOptions()
977 {
978         QDialog dlg(this, Qt::Dialog);
979         dlg.setWindowTitle("Options");
980         ConnectEntry *e;
981         unsigned int i;
982
983         QLineEdit* progs;
984         progs = new QLineEdit(progdir, &dlg);
985         progs->setGeometry(150, 20, 180, 30);
986
987         QLabel* tmpQLabel;
988         tmpQLabel = new QLabel("Programs directory", &dlg);
989         tmpQLabel->setGeometry(30, 20, 120, 30);
990
991         QFrame* tmpQFrame;
992         tmpQFrame = new QFrame(&dlg);
993         tmpQFrame->setGeometry(10, 60, 380, 30);
994         tmpQFrame->setFrameStyle(52);
995
996         tmpQLabel = new QLabel("Virtual Processor properties (activated after "
997                                                 "restarting VLP):", &dlg);
998         tmpQLabel->setGeometry(10, 80, 340, 30);
999
1000         QLineEdit *nn;
1001         char nns[256];
1002         sprintf(nns, "%d", NodeNumber);
1003         nn = new QLineEdit(nns, &dlg);
1004         nn->setGeometry(110, 110, 40, 30);
1005
1006         tmpQLabel = new QLabel("Node number:", &dlg);
1007         tmpQLabel->setGeometry(20, 110, 90, 30);
1008
1009         QRadioButton *exp, *reg;
1010         exp = new QRadioButton("Explicit", &dlg);
1011         exp->setGeometry(30, 170, 100, 30);
1012         exp->setChecked(TRUE);
1013
1014         reg = new QRadioButton("Registration", &dlg);
1015         reg->setGeometry(30, 200, 100, 30);
1016         reg->setEnabled(FALSE);
1017
1018         connections = new QListWidget(&dlg);
1019         connections->setGeometry(170, 140, 130, 100);
1020
1021         for (int i = 0; i < ConnectList.size(); i++) {
1022                 e = ConnectList.at(i);
1023                 connections->addItem(e->addr);
1024         }
1025
1026         tmpQLabel = new QLabel("Connection list:", &dlg);
1027         tmpQLabel->setGeometry(170, 110, 100, 30);
1028
1029         QPushButton *addbtn;
1030         QPushButton *delbtn;
1031         QPushButton *okbtn;
1032         QPushButton *cancelbtn;
1033         addbtn = new QPushButton("Add", &dlg);
1034         addbtn->setGeometry(310, 150, 60, 30);
1035         connect(addbtn, SIGNAL(clicked()), this, SLOT(AddAddress()));
1036
1037         delbtn = new QPushButton("Del", &dlg);
1038         delbtn->setGeometry(310, 200, 60, 30);
1039         connect(delbtn, SIGNAL(clicked()), this, SLOT(DelAddress()));
1040
1041         okbtn = new QPushButton("Ok", &dlg);
1042         okbtn->setGeometry(80, 260, 100, 30);
1043         okbtn->setDefault(TRUE);
1044         connect(okbtn, SIGNAL(clicked()), &dlg, SLOT(accept()));
1045
1046         cancelbtn = new QPushButton("Cancel", &dlg);
1047         cancelbtn->setGeometry(210, 260, 100, 30);
1048         connect(cancelbtn, SIGNAL(clicked()), &dlg, SLOT(reject()));
1049
1050         QGroupBox* group;
1051         group = new QGroupBox("Connection type", &dlg);
1052         group->setGeometry(20, 150, 120, 90);
1053         group->setAlignment(Qt::AlignLeft);
1054         group->lower();
1055
1056         QVBoxLayout *vbox = new QVBoxLayout();
1057         vbox->addWidget(exp);
1058         vbox->addWidget(reg);
1059         vbox->addStretch(1);
1060         group->setLayout(vbox);
1061
1062         dlg.resize(400, 310);
1063         if (dlg.exec()) {
1064                 config_t cfg;
1065                 config_setting_t *root;
1066                 config_setting_t *setting;
1067                 config_init(&cfg);
1068
1069                 root = config_root_setting(&cfg);
1070
1071                 setting = config_setting_add(root, "progdir",
1072                                                         CONFIG_TYPE_STRING);
1073                 config_setting_set_string(setting, progs->text().toAscii().data());
1074                 strcpy(progdir, progs->text().toAscii().data());
1075
1076                 setting = config_setting_add(root, "node_number",
1077                                                         CONFIG_TYPE_INT);
1078                 config_setting_set_int(setting, atoi(nn->text().toAscii().data()));
1079
1080                 setting = config_setting_add(root, "homedir",
1081                                                         CONFIG_TYPE_STRING);
1082                 config_setting_set_string(setting, HomeDir);
1083
1084                 setting = config_setting_add(root, "type",
1085                                                         CONFIG_TYPE_STRING);
1086                 if (exp->isChecked()) {
1087                         config_setting_set_string(setting, "explicit");
1088
1089                         config_setting_t *hosts = NULL;
1090                         hosts = config_setting_add(root, "host",
1091                                                         CONFIG_TYPE_ARRAY);
1092                         for(i = 0; i < connections->count(); i++) {
1093                                 setting = config_setting_add(hosts, NULL,
1094                                                         CONFIG_TYPE_STRING);
1095                                 config_setting_set_string(setting,
1096                                                 connections->item(i)->text().toAscii().data());
1097                         }
1098                 } else {
1099                         config_setting_set_string(setting, "register");
1100                 }
1101
1102                 if (!config_write_file(&cfg, "vlp.cfg")) {
1103                         fprintf(stderr, "Error while writing to file: %s.\n", 
1104                                                                 "vlp.cfg");
1105                 }
1106                 config_destroy(&cfg);
1107         }
1108 }
1109
1110 /**
1111  * Locks kernel program.
1112  * Additional window is displayed to enter password and retype it. If both are
1113  * same kernel window is locked.
1114  */
1115 void QKernel::LockConsole()
1116 {
1117         QDialog d(this, Qt::Dialog);
1118         d.setWindowTitle("Lock console");
1119
1120         QPushButton ob("Ok", &d);
1121         ob.setGeometry(30, 60, 80, 30);
1122         ob.setDefault(TRUE);
1123         connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
1124
1125         QLabel lab("Password:", &d);
1126         lab.setGeometry(10, 10, 60, 30);
1127
1128         QLineEdit ed("", &d);
1129         ed.setGeometry(70, 10, 140, 30);
1130         ed.setEchoMode(QLineEdit::Password);
1131
1132         QPushButton cb("Cancel", &d);
1133         cb.setGeometry(130, 60, 80, 30);
1134         connect(&cb, SIGNAL(clicked()), &d, SLOT(reject())); 
1135
1136         d.resize(240, 100);
1137
1138         if (d.exec()) {
1139                 if (strcmp(ed.text().toAscii().data(), "") != 0) {
1140                         strcpy(LockPasswd, ed.text().toAscii().data());
1141                         lab.setText("Retype:");
1142                         ed.setText("");
1143                         if (d.exec()) {
1144                                 if (strcmp(ed.text().toAscii().data(), LockPasswd)==0) {
1145                                         qid->setEnabled(FALSE);
1146                                         prid->setEnabled(FALSE);
1147                                         mid->setEnabled(FALSE);
1148                                         unlockid->setEnabled(TRUE);
1149                                         lockid->setEnabled(FALSE);
1150                                         cwid->setEnabled(FALSE);
1151                                         optid->setEnabled(FALSE);
1152                                         WriteMessage("CONSOLE LOCKED");
1153                                         LOCKED = TRUE;
1154                                 } else {
1155                                         QMessageBox msg(this);
1156                                         msg.setText("Not matching!");
1157                                         msg.setButtonText(0, "Close");
1158                                         msg.show();
1159                                 }
1160                         } else {
1161                                 strcpy(LockPasswd, "");
1162                         }
1163                 }
1164         }
1165 }
1166
1167 /**
1168  * Unlocks kernel program.
1169  * Additional window is displayed to enter password. If it is correct, kernel 
1170  * window is unlocked
1171  */
1172 void QKernel::UnlockConsole()
1173 {
1174         QDialog d(this, Qt::Dialog);
1175         d.setWindowTitle("Enter password");
1176
1177         QLabel lab("Password:", &d);
1178         lab.setGeometry(10, 10, 60, 30);
1179
1180         QLineEdit ed("", &d);
1181         ed.setGeometry(70, 10, 140, 30);
1182         ed.setEchoMode(QLineEdit::Password);
1183
1184         QPushButton ob("Ok", &d);
1185         ob.setGeometry(30, 60, 80, 30);
1186         ob.setDefault(TRUE);
1187         connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
1188
1189         QPushButton cb("Cancel", &d);
1190         cb.setGeometry(130, 60, 80, 30);
1191         connect(&cb, SIGNAL(clicked()), &d, SLOT(reject())); 
1192
1193         d.resize(240, 100);
1194
1195         if (d.exec()) {
1196                 if (strcmp(ed.text().toAscii().data(), LockPasswd) == 0) {
1197                         qid->setEnabled(TRUE);
1198                         prid->setEnabled(TRUE);
1199                         mid->setEnabled(TRUE);
1200                         unlockid->setEnabled(FALSE);
1201                         lockid->setEnabled(TRUE);
1202                         cwid->setEnabled(TRUE);
1203                         optid->setEnabled(TRUE);
1204                         WriteMessage("CONSOLE UNLOCKED");
1205                         LOCKED = FALSE;
1206                 } else {
1207                         QMessageBox msg(this);
1208                         msg.setText("Wrong password!");
1209                         msg.setButtonText(0, "Close");
1210                         msg.show();
1211                 }
1212         }
1213 }
1214
1215 /**
1216  * Writes init message in kernel
1217  */
1218 void QKernel::InitMessage()
1219 {
1220         WriteMessage("\n " PACKAGE_STRING ": READY \n");
1221 }
1222
1223 /**
1224  * Finds Interpreter by its socket
1225  * @param _id ID of the socket
1226  * @return returns pointer to the found interpreter slot. NULL otherwise
1227  */
1228 InterpEntry *QKernel::findINTbySocket(int _id)
1229 {
1230         InterpEntry *pom = NULL;
1231         
1232         for (int i = 0; i < Interpreters.size(); i++) {
1233                 if (Interpreters.at(i)->sock == _id) {
1234                         pom = Interpreters.at(i);
1235                         break;
1236                 }
1237         }
1238
1239         return pom;
1240 }
1241
1242 /**
1243  * Finds Interpreter by its ID.
1244  * @param _id ID of the interpreter
1245  * @return returns pointer to the found interpreter slot. NULL otherwise
1246  */
1247 InterpEntry *QKernel::findINTbyID(int _id)
1248 {
1249         InterpEntry *pom = NULL;
1250         
1251         for (int i = 0; i < Interpreters.size(); i++) {
1252                 if (Interpreters.at(i)->ID == _id) {
1253                         pom = Interpreters.at(i);
1254                         break;
1255                 }
1256         }
1257
1258         return pom;
1259 }
1260
1261
1262 /**
1263  * Connects interpreter
1264  * @param ss full filepath with filename but without extension of the loglan
1265  *           program to run.
1266  * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
1267  *          remote
1268  * @return Returns pointer to newly created interpreter slot, or NULL on error.
1269  */
1270 InterpEntry *QKernel::RunIntModule(char *ss, int r)
1271 {
1272         char a[256], b[255];
1273         struct sockaddr_un svr;
1274         int len, sock, i, on;
1275         int newint=-1;
1276         char cmd[255];
1277         FILE *cf;
1278         MESSAGE msg;
1279         InterpEntry *newINT = NULL;
1280
1281         strcpy(a, ss);
1282         strcat(a, ".ccd");
1283         cf = fopen(a, "r");
1284         if (cf == NULL) {
1285                 WriteMessage("File not found: no .ccd file");
1286                 return NULL;
1287         }
1288         fclose(cf);
1289
1290         strcpy(a, ss);
1291         strcat(a, ".pcd");
1292         cf = fopen(a, "r");
1293         if (cf == NULL) {
1294                 WriteMessage("File not found: no .pcd file");
1295                 return NULL;
1296         }
1297         fclose(cf);
1298
1299         newINT = new InterpEntry;
1300         for(i = 0; i < MAXINSTANCES; i++) 
1301                 newINT->RInstances[i] =- 1;
1302
1303         strcpy(b, rindex(ss, '/'));
1304         for(i = 0; i < strlen(b); i++)
1305                 b[i] = b[i+1];
1306         if (info_messages) {
1307                 sprintf(a, "%s : Start execution", b);
1308                 WriteMessage(a); 
1309         }
1310
1311         newint = freeINTid;
1312         freeINTid++;
1313         newINT->ID = newint;
1314         strcpy(newINT->shortname, b);
1315         strcpy(newINT->fullname, ss);
1316
1317         sprintf(a, "%s%d", IPATH, newint);
1318         sprintf(cmd, "%s/modules/logint %s %s", HomeDir, a, ss);
1319         if (r) 
1320                 strcat(cmd, " r");
1321         sprintf(b, " %s %s %s %s %s", myargs[0], myargs[1], myargs[2],
1322                                                         myargs[3], myargs[4]);
1323         strcat(cmd, b);
1324         strcat(cmd, " &");
1325
1326         sock = socket(AF_UNIX, SOCK_STREAM, 0);
1327         unlink(a);
1328         bzero(&svr, sizeof(svr));
1329         svr.sun_family = AF_UNIX;
1330         strcpy(svr.sun_path, a);
1331         len = strlen(svr.sun_path)+sizeof(svr.sun_family);
1332         bind(sock, (struct sockaddr*)&svr, len);
1333         listen(sock, 5);
1334         system(cmd); 
1335         newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
1336         //::close(sock);
1337
1338         if (newINT->sock > 0) { 
1339                 fcntl(newINT->sock, F_SETFL, 
1340                                 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
1341                 on=1; 
1342                 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
1343                                                                 sizeof(on)); 
1344                 if (r)
1345                         newINT->remote = 1;
1346                 else 
1347                         newINT->remote = 0;
1348
1349                 bzero(&msg, sizeof(MESSAGE));
1350                 msg.msg_type = MSG_VLP;
1351                 msg.param.pword[0] = VLP_REGINT;
1352                 msg.param.pword[1] = newINT->ID;
1353                 sprintf(msg.param.pstr, "logi%d.net", newint);
1354                 write(net_sock, &msg, sizeof(MESSAGE)); 
1355
1356                 Interpreters.append(newINT);
1357                 newINT->notify = new QSocketNotifier(newINT->sock,
1358                                                         QSocketNotifier::Read);
1359                 connect(newINT->notify, SIGNAL(activated(int)), this,
1360                                                         SLOT(IntMessage(int)));
1361                 if (info_messages)
1362                         WriteMessage("INTERPRETER successfully connected");
1363         } else {
1364                 WriteMessage("Cannot connect interpreter");
1365         }
1366
1367         return newINT;
1368 }
1369
1370 /**
1371  * Allocates remote instance of interpreter
1372  * @param interp Interpreter slot 
1373  * @param on Node Number
1374  */
1375 void QKernel::RemoteInstance(InterpEntry *interp, int on)
1376 {
1377         MESSAGE m;
1378         char s[255];
1379
1380         m.msg_type = MSG_NET;
1381         m.param.pword[0] = NET_NODE_EXIST;
1382         m.param.pword[1] = on;
1383         m.param.pword[2] = interp->ID;
1384         write(net_sock, &m, sizeof(MESSAGE));
1385         bzero(&m, sizeof(MESSAGE));
1386         while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
1387                 read(net_sock, &m, sizeof(MESSAGE));
1388
1389          /* means node exists */
1390         if (m.param.pword[1] == 1) {
1391                 m.msg_type = MSG_NET;
1392                 m.param.pword[0] = NET_TRANSMIT_CODE;
1393                 m.param.pword[1] = interp->ID;
1394                 m.param.pword[2] = on;
1395                 strcpy(m.param.pstr, interp->fullname);
1396                 write(net_sock, &m, sizeof(MESSAGE));
1397
1398                 Net_Notify->setEnabled(FALSE);
1399                 while ((m.msg_type != MSG_NET) ||
1400                         (m.param.pword[0] != NET_TRANSMITTED))
1401                         read(net_sock, &m, sizeof(MESSAGE));
1402
1403                 m.msg_type = MSG_NET;
1404                 m.param.pword[0] = NET_PROPAGATE;
1405                 m.param.pword[1] = MSG_VLP;
1406                 m.param.pword[2] = NodeNumber;
1407                 m.param.pword[3] = 0;
1408                 m.param.pword[4] = on;
1409                 m.param.pword[5] = 0;
1410                 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1411                 m.param.pword[7] = interp->ID;
1412                 strcpy(m.param.pstr, interp->shortname);
1413                 write(net_sock, &m, sizeof(MESSAGE));
1414
1415                 read(net_sock, &m, sizeof(MESSAGE));
1416                 while (1) {
1417                         if ((m.param.pword[0] == NET_PROPAGATE) &&
1418                                 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1419                                 interp->RInstances[on] = m.param.pword[7];
1420                                 break;
1421                         }
1422                         read(net_sock, &m, sizeof(MESSAGE));  
1423                 }
1424
1425                 Net_Notify->setEnabled(TRUE);
1426
1427                 /*bzero(&m, sizeof(MESSAGE));*/
1428                 m.msg_type = MSG_VLP;
1429                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1430                 m.param.pword[1] = interp->RInstances[on];
1431                 write(interp->sock, &m, sizeof(MESSAGE));
1432         } else { /* There is no such a node! */
1433                 sprintf(s, "Warning: Node number %d not found!", on); 
1434                 WriteMessage(s);
1435                 WriteMessage("Allocating O-process on the local node");
1436                 bzero(&m, sizeof(MESSAGE));
1437                 m.msg_type = MSG_VLP;
1438                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1439                 m.param.pword[1] = interp->ID;
1440                 write(interp->sock, &m, sizeof(MESSAGE));
1441         }
1442 }
1443
1444 /**
1445  * Closes all remote instances
1446  */
1447 void QKernel::CloseInstances(InterpEntry *e)
1448 {
1449         MESSAGE msg;
1450         int i;
1451
1452         if (info_messages)
1453                 WriteMessage("Closing remote instances");
1454
1455         for(i=0; i < MAXINSTANCES; i++)
1456                 if (e->RInstances[i]>=0) {
1457                         msg.msg_type = MSG_NET;
1458                         msg.param.pword[0] = NET_PROPAGATE;
1459                         msg.param.pword[1] = MSG_VLP;
1460                         msg.param.pword[2] = NodeNumber;
1461                         msg.param.pword[4] = i;
1462                         msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1463                         msg.param.pword[7] = e->RInstances[i];
1464                         write(net_sock, &msg, sizeof(MESSAGE));
1465                 }
1466 }
1467
1468 /**
1469  * Displays information about virtual machine
1470  */
1471 void QKernel::Info()
1472 {
1473         MESSAGE m;
1474
1475         WriteMessage(CharLine);
1476         WriteMessage("### Virtual Machine Information ###");
1477         m.msg_type = MSG_NET;
1478         m.param.pword[0] = NET_GET_INFO;
1479         write(net_sock, &m, sizeof(MESSAGE));
1480         wait_for_info = TRUE;
1481 }
1482
1483 #include "kernel.moc"
1484
1485 /**
1486  * Program main function
1487  * All program arguments but the first one (argv[0]: program name) are saved and
1488  * passed to all dependent programs on their invocation.
1489  * @param argc Number of program arguments
1490  * @param argv Program arguments
1491  */
1492 int main(int argc, char **argv)
1493 {
1494         int i;
1495         for(i = 0; i < 5; i++) {
1496                 strcpy(myargs[i], "");
1497         }
1498         for(i = 1; i < argc; i++) {
1499                 strcpy(myargs[i - 1], argv[i]);
1500         }
1501
1502         app = new QApplication(argc, argv);
1503         QKernel kernel;
1504         kernel.show();
1505         kernel.InitMessage();
1506         
1507         return app->exec();
1508 }