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