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