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