Restore compilation of loggraph, extract code layout of kernel's message dialog into...
[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 #include <QtGui/QApplication>
33 #include <QtGui/QMainWindow>
34 #include <QtGui/QTextEdit>
35 #include <QtGui/QMenuBar>
36 #include <QtGui/QMessageBox>
37 #include <QtGui/QFileDialog>
38 #include <QtGui/QDialog>
39 #include <QtCore/QString>
40 #include <QtGui/QLabel>
41 #include <QtGui/QLineEdit>
42 #include <QtGui/QPushButton>
43 #include <QtGui/QRadioButton>
44 #include <QtGui/QGroupBox>
45 #include <QtGui/QVBoxLayout>
46 #include <QtCore/QList>
47 #include <QtGui/QListWidget>
48 #include <qfile.h>
49 #include <qcursor.h>
50 #include <QtCore/QSocketNotifier>
51 #include <QtGui/QCloseEvent>
52 #include <QtCore/QDir>
53 #include <QtCore/QProcess>
54
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <unistd.h>
58 #include <fcntl.h>
59
60 #include "genint1.h"
61 #include "socu.h"
62 #include <netinet/in.h>
63
64 #include <libconfig.h>
65 #include <X11/Xlib.h>
66
67 #include "kernel.h"
68 #include "ui/KernelWindow.h"
69 #include "ConnectDialog.h"
70 #include "KillDialog.h"
71 #include "LockDialog.h"
72 #include "OptionsDialog.h"
73 #include "MessageDialog.h"
74
75 #include "vlp/config.h"
76
77 #include <sys/prctl.h>
78 /* File resides in top directory (where are Makefiles)*/
79 #include "../../config.h"
80
81
82 namespace loglan {
83 namespace vlp {
84
85 char CharLine[25] = "________________________";
86
87 /**
88  * Event invoked on program close.
89  * Closes application. Displays additional window to confirm exit.
90  */
91 void QKernel::closeEvent(QCloseEvent * e)
92 {
93         e->ignore();
94
95         if (!LOCKED) {
96                 on_actionQuit_triggered();
97         }
98 }
99
100 void QKernel::setLocked(bool locked)
101 {
102         LOCKED = locked;
103
104         actionQuit->setDisabled(locked);
105
106         actionExecute->setDisabled(locked);
107         actionKill->setDisabled(locked);
108         actionMessage->setDisabled(locked);
109         actionConnect->setDisabled(locked);
110         actionDisconnect->setDisabled(locked);
111         actionInfo->setDisabled(locked);
112
113
114         /* Enable only menu entry for unlocking */
115         actionEditor->setDisabled(locked);
116         actionOptions->setDisabled(locked);
117         actionLock_console->setDisabled(locked);
118         actionUnlock_console->setDisabled(!locked);
119 }
120
121 /**
122  * Kernel program constructor.
123  * Prepares everything to work.
124  */
125 QKernel::QKernel(int argc, char **argv)
126 {
127         setupUi(this);
128
129         QString arg0(argv[0]);
130         arg0 += "/";
131         homeDir = QDir(arg0);
132         homeDir.cdUp();
133
134         
135         int i;
136         for(i = 0; (i < 5) && (i < argc-1); i++) {
137                 strcpy(myargs[i], "");
138                 if (i < argc) {
139                         strcpy(myargs[i], argv[i+1]);
140                 }
141         }
142
143         QDir q(getRemoteDir());
144
145         if (!q.exists()) {
146                 q.mkpath(getRemoteDir());
147         }
148
149         info_messages = actionInfo_messages->isChecked();
150         wait_for_info = FALSE;
151
152         setWindowTitle(PACKAGE_NAME);
153
154         LOCKED = FALSE;
155
156         Tasks = 0;
157         freeINTid = 1;
158         ActiveConnections = 0;
159         strcpy(LockPasswd, "");
160
161         loadConfig(getConfigFilePath());
162
163         RunNetModule();
164
165         Net_Notify = new QSocketNotifier(net_sock, QSocketNotifier::Read, this);
166         connect(Net_Notify, SIGNAL(activated(int)), this, SLOT(NetMessage()));
167
168         WriteMessage("\n " PACKAGE_STRING ": READY \n");
169 }
170
171 QString QKernel::getConfigFilePath()
172 {
173         return homeDir.absoluteFilePath("vlp.cfg");
174 }
175
176 const char * QKernel::getHomeDir()
177 {
178         return homeDir.absolutePath().toStdString().c_str();
179 }
180
181 const char * QKernel::getRemoteDir()
182 {
183         return homeDir.absoluteFilePath(REMOTE_PATH).toStdString().c_str();
184 }
185
186 const char * QKernel::getNetModuleSocket()
187 {
188         return homeDir.absoluteFilePath(NPATH).toStdString().c_str();
189 }
190
191 const char * QKernel::getGraphModuleSocket()
192 {
193         return homeDir.absoluteFilePath(GPATH).toStdString().c_str();
194 }
195
196 void QKernel::loadConfig(const QString & fname)
197 {
198         loadConfig(fname.toStdString().c_str());
199 }
200 /**
201  * Loads configuration from the given file.
202  * @param fname Filename of the configuration file.
203  */
204 void QKernel::loadConfig(const char * fname)
205 {
206         loglan::vlp::Config config;
207         if(config.load(fname)) {
208                 NodeNumber = config.getNodeNumber();
209                 ConType = config.getConnectionType();
210
211
212                 std::vector<std::string> hosts = config.getHosts();
213                 for (unsigned int i = 0; i < hosts.size(); i++) {
214                         ConnectList.append(new ConnectEntry(hosts[i].c_str()));
215                 }
216
217                 strncpy(progdir, config.getProgramDir(), 256);
218         }
219 }
220
221 /**
222  * Executes program.
223  * Additional window id displayed to set which code to execute.
224  */
225 void QKernel::on_actionExecute_triggered()
226 {
227         QString s = QFileDialog::getOpenFileName(this, "Execute", progdir, "*.log");
228
229         if (!s.isNull()) {
230                 int i = s.indexOf(".log");
231
232                 if (i > 0)
233                         s.remove(i, 4);
234
235                 // @TODO: if no interpreter is running will result in killing app
236                 RunIntModule((char*)s.toAscii().data(), 0);
237         }
238 }
239
240 /**
241  * Invokes editor program
242  */
243 void QKernel::on_actionEditor_triggered()
244 {
245         QString program = getHomeDir();
246         program += "/modules/logedit";
247
248         fprintf(stderr, "Run EDIT Module: %s, %s\n", program.toStdString().c_str(), getHomeDir());
249         pid_t pid = fork();
250         if (pid == 0) {
251                 if (execl(program.toStdString().c_str(),
252                         getHomeDir(),
253                         myargs[0],
254                         myargs[1],
255                         myargs[2],
256                         myargs[3],
257                         myargs[4],
258                         NULL
259                 ) == -1) {
260                         WriteMessage("Executing logedit failed!");
261                 }
262         }
263         else if (pid < 0) {
264                 WriteMessage("fork(logedit) failed!");
265                 WriteMessage("Exiting...");
266                 sleep(2);
267                 on_actionQuit_triggered();
268                 exit(3);
269         }
270 }
271
272 /**
273  * Invokes help program
274  */
275 void QKernel::on_actionHelp_triggered()
276 {
277         QString program = getHomeDir();
278         program += "/modules/loghelp";
279         
280         QString docDir = getHomeDir();
281         docDir += "/doc";
282
283         fprintf(stderr, "Run HELP Module: %s, %s\n", program.toStdString().c_str(), docDir.toStdString().c_str());
284
285         pid_t pid = fork();
286         if (pid == 0) {
287                 if (execl(program.toStdString().c_str(),
288                         docDir.toStdString().c_str(),
289                         myargs[0],
290                         myargs[1],
291                         myargs[2],
292                         myargs[3],
293                         myargs[4],
294                         NULL
295                 ) == -1) {
296
297                         WriteMessage("Executing loghelp failed!");
298                 }
299         }
300         else if (pid < 0) {
301                 WriteMessage("fork(loghelp) failed!");
302                 WriteMessage("Exiting...");
303                 sleep(2);
304                 on_actionQuit_triggered();
305                 exit(3);
306         }
307 }
308
309 /**
310  * Invokes graphics module
311  */
312 void QKernel::RunGraphModule(char *sk)
313 {
314         QString program = getHomeDir();
315         program += "/modules/loggraph";
316
317         fprintf(stderr, "Run GRAPH Module: %s, %s\n", program.toStdString().c_str(), sk);
318
319         pid_t pid = fork();
320         if (pid == 0) {
321                 if (execl(program.toStdString().c_str(),
322                         program.toStdString().c_str(),
323                         sk,
324                         myargs[0],
325                         myargs[1],
326                         myargs[2],
327                         myargs[3],
328                         myargs[4],
329                         NULL
330                 ) == -1) {
331
332                         WriteMessage("Executing loggraph failed!");
333                         WriteMessage("Exiting...");
334                         sleep(2);
335                         on_actionQuit_triggered();
336                 }
337         }
338         else if (pid < 0) {
339                 WriteMessage("fork(loggraph) failed!");
340                 WriteMessage("Exiting...");
341                 sleep(2);
342                 on_actionQuit_triggered();
343                 exit(3);
344         }
345 }
346
347 /**
348  * Invokes net module
349  */
350 void QKernel::RunNetModule()
351 {
352
353         struct sockaddr_un svr;
354         int len;
355         int on;
356         int sock;
357
358         QString program = getHomeDir();
359         program += "/modules/lognet";
360
361         fprintf(stderr, "Run NET Module: %s, %s %s\n", program.toStdString().c_str(), getNetModuleSocket(), getConfigFilePath().toStdString().c_str());
362         pid_t pid = fork();
363         if (pid == 0) {
364                 if (execl(program.toStdString().c_str(),
365                         program.toStdString().c_str(),
366                         getNetModuleSocket(),
367                         getConfigFilePath().toStdString().c_str(),
368                         myargs[0],
369                         myargs[1],
370                         myargs[2],
371                         myargs[3],
372                         myargs[4],
373                         NULL
374                 ) == -1) {
375
376                         WriteMessage("Executing lognet failed!");
377                         WriteMessage("Exiting...");
378                         sleep(2);
379                         on_actionQuit_triggered();
380                 }
381         }
382         else if (pid < 0) {
383                 WriteMessage("fork(lognet) failed!");
384                 WriteMessage("Exiting...");
385                 sleep(2);
386                 on_actionQuit_triggered();
387                 exit(3);
388         }
389
390         /* -------- socket for NET module -------- */
391         unlink(getNetModuleSocket());
392         sock = socket(AF_UNIX, SOCK_STREAM, 0);
393         bzero(&svr, sizeof(svr));
394         svr.sun_family = AF_UNIX;
395         strcpy(svr.sun_path, getNetModuleSocket());
396         len = strlen(svr.sun_path) + sizeof(svr.sun_family);
397         bind(sock, (struct sockaddr*)&svr, len);
398         listen(sock, 5);
399
400         net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
401         // close(sock); 
402         if (net_sock != 0) {
403                 WriteMessage("NETWORK successfully connected");
404                 fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock, F_GETFL, 0));
405                 on = 1;
406                 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
407         } else {
408                 WriteMessage("Cannot connect NETWORK resources");
409                 WriteMessage("Exiting...");
410                 sleep(2);
411                 on_actionQuit_triggered();
412         }
413 }
414
415 /**
416  * Connects to the specified address
417  * Additional window is displayed to connect to the specified address
418  */
419 void QKernel::on_actionConnect_triggered()
420 {
421         MESSAGE m;
422
423         dialog::ConnectDialog dialog(this);
424         dialog.setWindowTitle("IP Address:");
425
426         if (dialog.exec()) {
427                 m.msg_type = MSG_NET;
428                 m.param.pword[0] = NET_CONNECT_TO;
429                 strcpy(m.param.pstr, dialog.getAddress().toStdString().c_str());
430                 write(net_sock, &m, sizeof(MESSAGE));
431         }
432 }
433
434 /**
435  * Disconnects from virtual machine
436  */
437 void QKernel::on_actionDisconnect_triggered()
438 {
439         MESSAGE msg;
440
441         if (info_messages)
442                 WriteMessage("Disconnecting from virtual machine");
443
444         msg.msg_type = MSG_NET;
445         msg.param.pword[0] = NET_DISCONNECT;
446         write(net_sock, &msg, sizeof(MESSAGE));
447 }
448
449 /**
450  * Quits process. Closes VLP. Shows additional window to confirm exit. 
451  */
452 void QKernel::on_actionQuit_triggered()
453 {
454         MESSAGE msg;
455
456         QMessageBox::StandardButton response = QMessageBox::question(this,
457                 "Close VLP",
458                 "Terminate VLP ?",
459                 QMessageBox::Ok | QMessageBox::Cancel
460         );
461
462
463         if (response == QMessageBox::Cancel) {
464                 return;
465         }
466         /*
467         msg.msg_type = MSG_NET;
468         msg.param.pword[0] = NET_DISCONNECT;
469         write(net_sock, &msg, sizeof(MESSAGE));*/
470         delete Net_Notify;
471
472         msg.msg_type = MSG_NET;
473         msg.param.pword[0] = NET_EXIT;
474         write(net_sock, &msg, sizeof(MESSAGE));
475         /*  ::close(net_sock);*/
476         QApplication::instance()->quit();
477 }
478
479 /**
480  * Sends message to node.
481  * Additional window is displayed to set Node Number of node where send message,
482  * and textfield to enter message.
483  */
484 void QKernel::on_actionMessage_triggered()
485 {
486         dialog::MessageDialog dialog(this);
487         MESSAGE m;
488
489         if (dialog.exec()) {
490                 m.msg_type = MSG_NET;
491                 m.param.pword[0] = NET_PROPAGATE;
492                 m.param.pword[1] = MSG_VLP;
493                 m.param.pword[2] = NodeNumber;
494                 m.param.pword[4] = dialog.getNodeNumber();
495                 m.param.pword[6] = VLP_WRITE;
496                 strcpy(m.param.pstr, dialog.getMessage().toStdString().c_str());
497                 write(net_sock, &m, sizeof(MESSAGE));
498         }
499 }
500
501 /**
502  * Kills interpreter.
503  * Additional window is displayed to get ID of interpreter which should be
504  * killed.
505  */
506 void QKernel::on_actionKill_triggered()
507 {
508         dialog::KillInterpreterDialog dialog(this);
509         dialog.setWindowTitle("Kill interpreter");
510
511         if (dialog.exec()) {
512                 MESSAGE m;
513                 m.msg_type = MSG_INT;
514                 m.param.pword[0] = INT_KILL;
515                 
516                 InterpEntry *interpreter;
517                 interpreter = findINTbyID(dialog.getInterpreterId());
518
519                 if (interpreter != NULL) {
520                         if (!(interpreter->remote)) {
521                                 write(interpreter->sock, &m, sizeof(MESSAGE));
522                         }
523                         else {
524                                 WriteMessage("This is a remote instance of a program!");
525                         }
526                 }
527                 else {
528                         WriteMessage("Interpreter not found");
529                 }
530         }
531 }
532
533 /**
534  * Sends message to the net module.
535  */
536 void QKernel::NetMessage()
537 {
538         
539         /* TODO: It has to be rewritten */
540         MESSAGE msg;
541         int cnt;
542         InterpEntry *pom;
543
544         cnt = read(net_sock, &msg, sizeof(MESSAGE));
545         if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
546                 char ss[255];
547
548                 switch(msg.param.pword[0]) {
549                 case NET_CSWRITELN:
550                         WriteMessage(msg.param.pstr);
551                         break;
552                 case NET_PROPAGATE: 
553                         switch(msg.param.pword[1]) {
554                         case MSG_INT:
555                                 /*  pom = find_link_by_ID(msg.param.pword[5]);
556                                 msg.msg_type = MSG_NET;
557                                 msg.param.pword[0] = NET_PROPAGATE;
558                                 send_int(pom, &msg);*/
559                                 break;
560                         case MSG_VLP:
561                                 switch(msg.param.pword[6]) {
562                                 case VLP_WRITE:
563                                         QApplication::beep();
564                                         WriteMessage(CharLine);
565                                         WriteMessage("### Incoming Messsage ###");
566                                         sprintf(ss,
567                                                 "Mesg from Node %d: %s",
568                                                 msg.param.pword[2],
569                                                 msg.param.pstr
570                                         );
571                                         WriteMessage(ss);
572                                         WriteMessage(CharLine);
573                                         break;
574                                 case VLP_REMOTE_INSTANCE:
575                                         sprintf(ss, "%s/%s", getRemoteDir(), msg.param.pstr);
576
577                                         if (info_messages) { 
578                                                 WriteMessage("Running program:");
579                                                 WriteMessage(ss);
580                                         }
581                                         pom = RunIntModule(ss, 1);
582                                         if (pom != NULL) {
583                                                 pom->p_ctx.node = msg.param.pword[2];
584                                                 pom->p_ctx.program_id = 
585                                                         msg.param.pword[7];
586                                                 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
587                                         }
588                                         break;
589                                 case VLP_CLOSE_INSTANCE:
590                                         msg.msg_type = MSG_INT;
591                                         msg.param.pword[0] = INT_CLOSE_INSTANCE;
592                                         pom = findINTbyID(msg.param.pword[7]);
593                                         if (pom != NULL) {
594                                                 write(pom->sock, &msg,
595                                                         sizeof(MESSAGE));
596                                                 MESSAGE m1;
597                                                 m1.msg_type = MSG_VLP;
598                                                 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
599                                                 m1.param.pword[1] = pom->ID;
600                                                 write(net_sock, &m1,
601                                                         sizeof(MESSAGE));
602                                         } else {
603                                                 WriteMessage("Instance not found"); 
604                                         }
605                                         break; 
606                                 } /* VLP switch */
607                         }/* switch */
608                         break;
609                 case NET_CONNECTIONS:
610                         ActiveConnections = msg.param.pword[1];
611                         WriteMessage(msg.param.pstr);
612                         if (!synchro) 
613                                 synchro = TRUE;
614                         break;
615                 case NET_INFO:
616                         /* TODO: It has to be rewritten */
617                         if (wait_for_info) {
618                                 QString poms, poms1, poms2;
619                                 poms.sprintf("%s", msg.param.pstr);
620                                 while (poms.length() > 0) {
621                                         cnt = poms.indexOf(';');
622                                         if (cnt!=-1) {
623                                                 poms1 = poms.left(cnt);
624                                                 poms = poms.right(poms.length() - cnt - 1);
625                                                 cnt = poms1.indexOf('=');
626                                                 if (cnt != -1) {
627                                                         poms2 = poms1.left(cnt);
628                                                         poms1 = poms1.right(poms1.length() - cnt - 1);
629                                                         sprintf(ss, "Node: %s Addr: %s", poms2.toStdString().c_str(), poms1.toStdString().c_str());
630                                                         WriteMessage(ss); 
631                                                 }
632                                         } 
633                                 }
634                         } 
635                         break;
636                 case NET_INFO_END:
637                         wait_for_info = FALSE;
638                         WriteMessage(CharLine);
639                         break;
640                 } /* switch */
641         }
642 }
643
644 /**
645  * Sends message to the interpreter program.
646  * @param sock Interpreter socket to whom the message will be send.
647  */
648 void QKernel::IntMessage(int sock)
649 {
650         MESSAGE msg;
651         int cnt;
652         InterpEntry *e;
653
654         cnt = read(sock, &msg, sizeof(MESSAGE));
655         e = findINTbySocket(sock);
656         if ((cnt > 0) && (e != NULL)) {
657                 switch (msg.msg_type) { 
658                 case MSG_GRAPH:
659                         if (msg.param.pword[0] == GRAPH_ALLOCATE) {
660                                 fprintf(stderr, "Running graph module with arg: %s\n", msg.param.pstr);
661                                 RunGraphModule(msg.param.pstr);
662                         }
663                         break;
664                 case MSG_NET:
665                         write(net_sock, &msg, sizeof(MESSAGE));
666                         break;
667                 case MSG_VLP:
668                         switch(msg.param.pword[0]) {
669                         case VLP_REMOTE_INSTANCE_PLEASE:
670                                 RemoteInstance(e, msg.param.pword[2]);
671                                 break;
672                         }/* switch */
673                         break;
674                 case MSG_INT:
675                         switch(msg.param.pword[0]) {
676                         case INT_EXITING:
677                                 char ss[255];
678
679                                 MESSAGE m;
680                                 m.msg_type = MSG_VLP;
681                                 m.param.pword[0] = VLP_INTERPRETER_DOWN;
682                                 m.param.pword[1] = e->ID;
683                                 write(net_sock, &m, sizeof(MESSAGE));
684                                 if (e->remote == 0)
685                                         CloseInstances(e);
686                                 delete e->notify;
687                                 ::close(e->sock);
688                                 /* TODO: Check this */
689                                 Interpreters.removeOne(e);
690                                 delete e;
691
692                                 if (info_messages) {
693                                         sprintf(ss, "%s : End of program "
694                                                 "execution", msg.param.pstr);
695                                         WriteMessage(ss);
696                                 }
697                                 break;
698                         case INT_CTX_REQ:
699                                 msg.msg_type = MSG_INT;
700                                 msg.param.pword[0] = INT_CTX;
701                                 msg.param.pword[1] = NodeNumber;
702                                 msg.param.pword[2] = e->ID;
703                                 if (e->remote) {
704                                         msg.param.pword[3] = e->p_ctx.node;
705                                         msg.param.pword[4] = 
706                                                         e->p_ctx.program_id;
707                                 }
708                                 write(sock, &msg, sizeof(MESSAGE)); 
709                                 break;
710                         };
711                         break;
712                 }
713         }
714 }
715
716 /**
717  * Writes message to kernel logger.
718  * @parame msg String with message to log
719  */
720 void QKernel::WriteMessage(const char *msg)
721 {
722         int x;
723 //      int y;
724         x = desktop->textCursor().blockNumber();
725 //      y = desktop->textCursor().columnNumber();
726
727         if (x > 100) {
728                 desktop->clear();
729         }
730         
731         desktop->setReadOnly(FALSE);
732         desktop->append(msg);
733         desktop->setReadOnly(TRUE);
734
735         QTextCursor tmpCursor = desktop->textCursor();
736         tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
737         desktop->setTextCursor(tmpCursor);
738
739         desktop->repaint();
740         
741         if (desktop->document()->blockCount() > 100) {
742                 desktop->clear();
743         }
744 }
745
746 /**
747  * Adds checkbox to menu item. If it is checked additional info messages are
748  * shown.
749  */
750 void QKernel::on_actionInfo_messages_triggered()
751 {
752         if (toolsMenu != NULL) {
753                 info_messages = actionInfo_messages->isChecked();
754                 actionInfo_messages->setChecked(info_messages);
755         }
756 }
757
758 /**
759  * Allows to set options in GUI window.
760  * Additional window is displayed to set kernel options which are saved in 
761  * vlp.cfg file in kernel executable directory.
762  */
763 void QKernel::on_actionOptions_triggered()
764 {
765         dialog::OptionsDialog optionsDialog(getConfigFilePath(), this);
766         if (optionsDialog.exec()) {
767                 optionsDialog.saveConfig(getConfigFilePath());
768
769                 loadConfig(getConfigFilePath());
770         }
771 }
772
773 /**
774  * Locks kernel program.
775  * Additional window is displayed to enter password and retype it. If both are
776  * same kernel window is locked.
777  */
778 void QKernel::on_actionLock_console_triggered()
779 {
780         dialog::LockDialog lockDialog(this);
781
782         if (lockDialog.exec()) {
783                 QString password = lockDialog.getPassword();
784                 if (lockDialog.getPassword().size() > 0) {
785                         strcpy(LockPasswd, password.toStdString().c_str());
786                         lockDialog.retype();
787
788                         if (lockDialog.exec()) {
789                                 password = lockDialog.getPassword();
790                                 if (password == LockPasswd) {
791                                         setLocked(TRUE);
792                                         WriteMessage("CONSOLE LOCKED");
793                                 } else {
794                                         QMessageBox msg(this);
795                                         msg.setText("Not matching!");
796                                         msg.setButtonText(0, "Close");
797                                         msg.show();
798                                         strcpy(LockPasswd, "");
799                                 }
800                         } else {
801                                 strcpy(LockPasswd, "");
802                         }
803                 }
804         }
805 }
806
807 /**
808  * Unlocks kernel program.
809  * Additional window is displayed to enter password. If it is correct, kernel 
810  * window is unlocked
811  */
812 void QKernel::on_actionUnlock_console_triggered()
813 {
814         dialog::LockDialog lockDialog(this);
815
816         if (lockDialog.exec()) {
817                 QString password = lockDialog.getPassword();
818                 if (strcmp(password.toStdString().c_str(), LockPasswd) == 0) {
819                         setLocked(FALSE);
820                         WriteMessage("CONSOLE UNLOCKED");
821                 } else {
822                         QMessageBox msg(this);
823                         msg.setText("Wrong password!");
824                         msg.setButtonText(0, "Close");
825                         msg.show();
826                 }
827         }
828 }
829
830 /**
831  * Finds Interpreter by its socket
832  * @param _id ID of the socket
833  * @return returns pointer to the found interpreter slot. NULL otherwise
834  */
835 InterpEntry *QKernel::findINTbySocket(int _id)
836 {
837         InterpEntry *pom = NULL;
838         
839         for (auto interpreter : Interpreters) {
840                 if (interpreter->sock == _id) {
841                         pom = interpreter;
842                         break;
843                 }
844         }
845
846         return pom;
847 }
848
849 /**
850  * Finds Interpreter by its ID.
851  * @param _id ID of the interpreter
852  * @return returns pointer to the found interpreter slot. NULL otherwise
853  */
854 InterpEntry *QKernel::findINTbyID(int _id)
855 {
856         InterpEntry *pom = NULL;
857         
858         for (auto interpreter : Interpreters) {
859                 if (interpreter->ID == _id) {
860                         pom = interpreter;
861                         break;
862                 }
863         }
864
865         return pom;
866 }
867
868
869 /**
870  * Connects interpreter
871  * @param ss full filepath with filename but without extension of the loglan
872  *           program to run.
873  * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
874  *          remote
875  * @return Returns pointer to newly created interpreter slot, or NULL on error.
876  */
877 InterpEntry *QKernel::RunIntModule(char *ss, int r)
878 {
879         fprintf(stderr, "Run INT Module: %s, %d\n", ss, r);
880         char a[256], b[255];
881         struct sockaddr_un svr;
882         int len, sock, on;
883         unsigned int i;
884         int newint=-1;
885         char cmd[255];
886         FILE *cf;
887         MESSAGE msg;
888         InterpEntry *newINT = NULL;
889
890         strcpy(a, ss);
891         strcat(a, ".ccd");
892         cf = fopen(a, "r");
893         if (cf == NULL) {
894                 WriteMessage("File not found: no .ccd file");
895                 return NULL;
896         }
897         fclose(cf);
898
899         strcpy(a, ss);
900         strcat(a, ".pcd");
901         cf = fopen(a, "r");
902         if (cf == NULL) {
903                 WriteMessage("File not found: no .pcd file");
904                 return NULL;
905         }
906         fclose(cf);
907
908         newINT = new InterpEntry;
909         for(i = 0; i < MAXINSTANCES; i++) 
910                 newINT->RInstances[i] =- 1;
911
912         strcpy(b, rindex(ss, '/'));
913         for(i = 0; i < strlen(b); i++)
914                 b[i] = b[i+1];
915         if (info_messages) {
916                 sprintf(a, "%s : Start execution", b);
917                 WriteMessage(a); 
918         }
919
920         newint = freeINTid;
921         freeINTid++;
922         newINT->ID = newint;
923         strcpy(newINT->shortname, b);
924         strcpy(newINT->fullname, ss);
925
926         sprintf(a, "%s%d", IPATH, newint);
927         sprintf(cmd, "%s/modules/logint %s %s",
928                 getHomeDir(),
929                 a,
930                 ss);
931         if (r) {
932                 strcat(cmd, " r");
933         }
934         sprintf(b, " %s %s %s %s %s",
935                 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
936         strcat(cmd, b);
937         strcat(cmd, " &");
938
939         sock = socket(AF_UNIX, SOCK_STREAM, 0);
940         unlink(a);
941         bzero(&svr, sizeof(svr));
942         svr.sun_family = AF_UNIX;
943         strcpy(svr.sun_path, a);
944         len = strlen(svr.sun_path)+sizeof(svr.sun_family);
945         bind(sock, (struct sockaddr*)&svr, len);
946         listen(sock, 5);
947         system(cmd);
948         newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
949         //::close(sock);
950
951         if (newINT->sock > 0) { 
952                 fcntl(newINT->sock, F_SETFL, 
953                                 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
954                 on=1; 
955                 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
956                                                                 sizeof(on));
957                 if (r)
958                         newINT->remote = 1;
959                 else 
960                         newINT->remote = 0;
961
962                 bzero(&msg, sizeof(MESSAGE));
963                 msg.msg_type = MSG_VLP;
964                 msg.param.pword[0] = VLP_REGINT;
965                 msg.param.pword[1] = newINT->ID;
966                 sprintf(msg.param.pstr, "logi%d.net", newint);
967                 write(net_sock, &msg, sizeof(MESSAGE)); 
968
969                 Interpreters.append(newINT);
970                 newINT->notify = new QSocketNotifier(newINT->sock,
971                                                         QSocketNotifier::Read);
972                 connect(newINT->notify, SIGNAL(activated(int)), this,
973                                                         SLOT(IntMessage(int)));
974                 if (info_messages)
975                         WriteMessage("INTERPRETER successfully connected");
976         } else {
977                 WriteMessage("Cannot connect interpreter");
978         }
979
980         return newINT;
981 }
982
983 /**
984  * Allocates remote instance of interpreter
985  * @param interp Interpreter slot 
986  * @param on Node Number
987  */
988 void QKernel::RemoteInstance(InterpEntry *interp, int on)
989 {
990         MESSAGE m;
991
992         m.msg_type = MSG_NET;
993         m.param.pword[0] = NET_NODE_EXIST;
994         m.param.pword[1] = on;
995         m.param.pword[2] = interp->ID;
996         write(net_sock, &m, sizeof(MESSAGE));
997         bzero(&m, sizeof(MESSAGE));
998         while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
999                 read(net_sock, &m, sizeof(MESSAGE));
1000
1001          /* means node exists */
1002         if (m.param.pword[1] == 1) {
1003                 m.msg_type = MSG_NET;
1004                 m.param.pword[0] = NET_TRANSMIT_CODE;
1005                 m.param.pword[1] = interp->ID;
1006                 m.param.pword[2] = on;
1007                 strcpy(m.param.pstr, interp->fullname);
1008                 write(net_sock, &m, sizeof(MESSAGE));
1009
1010                 Net_Notify->setEnabled(FALSE);
1011                 while ((m.msg_type != MSG_NET) ||
1012                         (m.param.pword[0] != NET_TRANSMITTED))
1013                         read(net_sock, &m, sizeof(MESSAGE));
1014
1015                 m.msg_type = MSG_NET;
1016                 m.param.pword[0] = NET_PROPAGATE;
1017                 m.param.pword[1] = MSG_VLP;
1018                 m.param.pword[2] = NodeNumber;
1019                 m.param.pword[3] = 0;
1020                 m.param.pword[4] = on;
1021                 m.param.pword[5] = 0;
1022                 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1023                 m.param.pword[7] = interp->ID;
1024                 strcpy(m.param.pstr, interp->shortname);
1025                 write(net_sock, &m, sizeof(MESSAGE));
1026
1027                 read(net_sock, &m, sizeof(MESSAGE));
1028                 while (1) {
1029                         if ((m.param.pword[0] == NET_PROPAGATE) &&
1030                                 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1031                                 interp->RInstances[on] = m.param.pword[7];
1032                                 break;
1033                         }
1034                         read(net_sock, &m, sizeof(MESSAGE));
1035                 }
1036
1037                 Net_Notify->setEnabled(TRUE);
1038
1039                 /*bzero(&m, sizeof(MESSAGE));*/
1040                 m.msg_type = MSG_VLP;
1041                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1042                 m.param.pword[1] = interp->RInstances[on];
1043                 write(interp->sock, &m, sizeof(MESSAGE));
1044         } else { /* There is no such a node! */
1045                 char s[255];
1046                 sprintf(s, "Warning: Node number %d not found!", on); 
1047                 WriteMessage(s);
1048                 WriteMessage("Allocating O-process on the local node");
1049                 bzero(&m, sizeof(MESSAGE));
1050                 m.msg_type = MSG_VLP;
1051                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1052                 m.param.pword[1] = interp->ID;
1053                 write(interp->sock, &m, sizeof(MESSAGE));
1054         }
1055 }
1056
1057 /**
1058  * Closes all remote instances
1059  */
1060 void QKernel::CloseInstances(InterpEntry *e)
1061 {
1062         MESSAGE msg;
1063         int i;
1064
1065         if (info_messages)
1066                 WriteMessage("Closing remote instances");
1067
1068         for(i=0; i < MAXINSTANCES; i++)
1069                 if (e->RInstances[i]>=0) {
1070                         msg.msg_type = MSG_NET;
1071                         msg.param.pword[0] = NET_PROPAGATE;
1072                         msg.param.pword[1] = MSG_VLP;
1073                         msg.param.pword[2] = NodeNumber;
1074                         msg.param.pword[4] = i;
1075                         msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1076                         msg.param.pword[7] = e->RInstances[i];
1077                         write(net_sock, &msg, sizeof(MESSAGE));
1078                 }
1079 }
1080
1081 /**
1082  * Displays information about virtual machine
1083  */
1084 void QKernel::on_actionInfo_triggered()
1085 {
1086         MESSAGE m;
1087
1088         WriteMessage(CharLine);
1089         WriteMessage("### Virtual Machine Information ###");
1090         m.msg_type = MSG_NET;
1091         m.param.pword[0] = NET_GET_INFO;
1092         write(net_sock, &m, sizeof(MESSAGE));
1093         wait_for_info = TRUE;
1094 }
1095
1096 }
1097 }
1098
1099 /**
1100  * Program main function
1101  * All program arguments but the first one (argv[0]: program name) are saved and
1102  * passed to all dependent programs on their invocation.
1103  * @param argc Number of program arguments
1104  * @param argv Program arguments
1105  */
1106 int main(int argc, char **argv)
1107 {
1108         XInitThreads();
1109
1110         QApplication * app = new QApplication(argc, argv);
1111         loglan::vlp::QKernel kernel(argc, argv);
1112         kernel.show();
1113         
1114         return app->exec();
1115 }