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