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