1f7d383ebc8f6500ef184fe7943a5d64d4753574
[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
425         if (dialog.exec()) {
426                 m.msg_type = MSG_NET;
427                 m.param.pword[0] = NET_CONNECT_TO;
428                 strcpy(m.param.pstr, dialog.getAddress().toStdString().c_str());
429                 write(net_sock, &m, sizeof(MESSAGE));
430         }
431 }
432
433 /**
434  * Disconnects from virtual machine
435  */
436 void QKernel::on_actionDisconnect_triggered()
437 {
438         MESSAGE msg;
439
440         if (info_messages)
441                 WriteMessage("Disconnecting from virtual machine");
442
443         msg.msg_type = MSG_NET;
444         msg.param.pword[0] = NET_DISCONNECT;
445         write(net_sock, &msg, sizeof(MESSAGE));
446 }
447
448 /**
449  * Quits process. Closes VLP. Shows additional window to confirm exit. 
450  */
451 void QKernel::on_actionQuit_triggered()
452 {
453         MESSAGE msg;
454
455         QMessageBox::StandardButton response = QMessageBox::question(this,
456                 "Close VLP",
457                 "Terminate VLP ?",
458                 QMessageBox::Ok | QMessageBox::Cancel
459         );
460
461
462         if (response == QMessageBox::Cancel) {
463                 return;
464         }
465         /*
466         msg.msg_type = MSG_NET;
467         msg.param.pword[0] = NET_DISCONNECT;
468         write(net_sock, &msg, sizeof(MESSAGE));*/
469         delete Net_Notify;
470
471         msg.msg_type = MSG_NET;
472         msg.param.pword[0] = NET_EXIT;
473         write(net_sock, &msg, sizeof(MESSAGE));
474         /*  ::close(net_sock);*/
475         QApplication::instance()->quit();
476 }
477
478 /**
479  * Sends message to node.
480  * Additional window is displayed to set Node Number of node where send message,
481  * and textfield to enter message.
482  */
483 void QKernel::on_actionMessage_triggered()
484 {
485         dialog::MessageDialog dialog(this);
486         MESSAGE m;
487
488         if (dialog.exec()) {
489                 m.msg_type = MSG_NET;
490                 m.param.pword[0] = NET_PROPAGATE;
491                 m.param.pword[1] = MSG_VLP;
492                 m.param.pword[2] = NodeNumber;
493                 m.param.pword[4] = dialog.getNodeNumber();
494                 m.param.pword[6] = VLP_WRITE;
495                 strcpy(m.param.pstr, dialog.getMessage().toStdString().c_str());
496                 write(net_sock, &m, sizeof(MESSAGE));
497         }
498 }
499
500 /**
501  * Kills interpreter.
502  * Additional window is displayed to get ID of interpreter which should be
503  * killed.
504  */
505 void QKernel::on_actionKill_triggered()
506 {
507         dialog::KillInterpreterDialog dialog(this);
508
509         if (dialog.exec()) {
510                 MESSAGE m;
511                 m.msg_type = MSG_INT;
512                 m.param.pword[0] = INT_KILL;
513                 
514                 InterpEntry *interpreter;
515                 interpreter = findINTbyID(dialog.getInterpreterId());
516
517                 if (interpreter != NULL) {
518                         if (!(interpreter->remote)) {
519                                 write(interpreter->sock, &m, sizeof(MESSAGE));
520                         }
521                         else {
522                                 WriteMessage("This is a remote instance of a program!");
523                         }
524                 }
525                 else {
526                         WriteMessage("Interpreter not found");
527                 }
528         }
529 }
530
531 /**
532  * Sends message to the net module.
533  *
534  * \todo method needs to be refactored
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                                 MESSAGE m;
678                                 m.msg_type = MSG_VLP;
679                                 m.param.pword[0] = VLP_INTERPRETER_DOWN;
680                                 m.param.pword[1] = e->ID;
681                                 write(net_sock, &m, sizeof(MESSAGE));
682                                 if (e->remote == 0)
683                                         CloseInstances(e);
684                                 delete e->notify;
685                                 ::close(e->sock);
686                                 /* TODO: Check this */
687                                 Interpreters.removeOne(e);
688                                 delete e;
689
690                                 if (info_messages) {
691                                         char ss[255];
692                                         sprintf(ss, "%s : End of program "
693                                                 "execution", msg.param.pstr);
694                                         WriteMessage(ss);
695                                 }
696                                 break;
697                         case INT_CTX_REQ:
698                                 msg.msg_type = MSG_INT;
699                                 msg.param.pword[0] = INT_CTX;
700                                 msg.param.pword[1] = NodeNumber;
701                                 msg.param.pword[2] = e->ID;
702                                 if (e->remote) {
703                                         msg.param.pword[3] = e->p_ctx.node;
704                                         msg.param.pword[4] = 
705                                                         e->p_ctx.program_id;
706                                 }
707                                 write(sock, &msg, sizeof(MESSAGE)); 
708                                 break;
709                         };
710                         break;
711                 }
712         }
713 }
714
715 /**
716  * Writes message to kernel logger.
717  * @parame msg String with message to log
718  */
719 void QKernel::WriteMessage(const char *msg)
720 {
721         int x;
722 //      int y;
723         x = desktop->textCursor().blockNumber();
724 //      y = desktop->textCursor().columnNumber();
725
726         if (x > 100) {
727                 desktop->clear();
728         }
729         
730         desktop->setReadOnly(FALSE);
731         desktop->append(msg);
732         desktop->setReadOnly(TRUE);
733
734         QTextCursor tmpCursor = desktop->textCursor();
735         tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
736         desktop->setTextCursor(tmpCursor);
737
738         desktop->repaint();
739         
740         if (desktop->document()->blockCount() > 100) {
741                 desktop->clear();
742         }
743 }
744
745 /**
746  * Adds checkbox to menu item. If it is checked additional info messages are
747  * shown.
748  */
749 void QKernel::on_actionInfo_messages_triggered()
750 {
751         if (toolsMenu != NULL) {
752                 info_messages = actionInfo_messages->isChecked();
753                 actionInfo_messages->setChecked(info_messages);
754         }
755 }
756
757 /**
758  * Allows to set options in GUI window.
759  * Additional window is displayed to set kernel options which are saved in 
760  * vlp.cfg file in kernel executable directory.
761  */
762 void QKernel::on_actionOptions_triggered()
763 {
764         dialog::OptionsDialog optionsDialog(getConfigFilePath(), this);
765         if (optionsDialog.exec()) {
766                 optionsDialog.saveConfig(getConfigFilePath());
767
768                 loadConfig(getConfigFilePath());
769         }
770 }
771
772 /**
773  * Locks kernel program.
774  * Additional window is displayed to enter password and retype it. If both are
775  * same kernel window is locked.
776  */
777 void QKernel::on_actionLock_console_triggered()
778 {
779         dialog::LockDialog lockDialog(this);
780
781         if (lockDialog.exec()) {
782                 QString password = lockDialog.getPassword();
783                 if (lockDialog.getPassword().size() > 0) {
784                         strcpy(LockPasswd, password.toStdString().c_str());
785                         lockDialog.retype();
786
787                         if (lockDialog.exec()) {
788                                 password = lockDialog.getPassword();
789                                 if (password == LockPasswd) {
790                                         setLocked(TRUE);
791                                         WriteMessage("CONSOLE LOCKED");
792                                 } else {
793                                         QMessageBox msg(this);
794                                         msg.setText("Not matching!");
795                                         msg.setButtonText(0, "Close");
796                                         msg.show();
797                                         strcpy(LockPasswd, "");
798                                 }
799                         } else {
800                                 strcpy(LockPasswd, "");
801                         }
802                 }
803         }
804 }
805
806 /**
807  * Unlocks kernel program.
808  * Additional window is displayed to enter password. If it is correct, kernel 
809  * window is unlocked
810  */
811 void QKernel::on_actionUnlock_console_triggered()
812 {
813         dialog::LockDialog lockDialog(this);
814
815         if (lockDialog.exec()) {
816                 QString password = lockDialog.getPassword();
817                 if (strcmp(password.toStdString().c_str(), LockPasswd) == 0) {
818                         setLocked(FALSE);
819                         WriteMessage("CONSOLE UNLOCKED");
820                 } else {
821                         QMessageBox msg(this);
822                         msg.setText("Wrong password!");
823                         msg.setButtonText(0, "Close");
824                         msg.show();
825                 }
826         }
827 }
828
829 /**
830  * Finds Interpreter by its socket
831  * @param _id ID of the socket
832  * @return returns pointer to the found interpreter slot. NULL otherwise
833  */
834 InterpEntry *QKernel::findINTbySocket(int _id)
835 {
836         InterpEntry *pom = NULL;
837         
838         for (auto interpreter : Interpreters) {
839                 if (interpreter->sock == _id) {
840                         pom = interpreter;
841                         break;
842                 }
843         }
844
845         return pom;
846 }
847
848 /**
849  * Finds Interpreter by its ID.
850  * @param _id ID of the interpreter
851  * @return returns pointer to the found interpreter slot. NULL otherwise
852  */
853 InterpEntry *QKernel::findINTbyID(int _id)
854 {
855         InterpEntry *pom = NULL;
856         
857         for (auto interpreter : Interpreters) {
858                 if (interpreter->ID == _id) {
859                         pom = interpreter;
860                         break;
861                 }
862         }
863
864         return pom;
865 }
866
867
868 /**
869  * Connects interpreter
870  * @param ss full filepath with filename but without extension of the loglan
871  *           program to run.
872  * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
873  *          remote
874  * @return Returns pointer to newly created interpreter slot, or NULL on error.
875  */
876 InterpEntry *QKernel::RunIntModule(char *ss, int r)
877 {
878         fprintf(stderr, "Run INT Module: %s, %d\n", ss, r);
879         char a[256], b[255];
880         struct sockaddr_un svr;
881         int len, sock, on;
882         unsigned int i;
883         int newint=-1;
884         char cmd[255];
885         FILE *cf;
886         MESSAGE msg;
887         InterpEntry *newINT = NULL;
888
889         strcpy(a, ss);
890         strcat(a, ".ccd");
891         cf = fopen(a, "r");
892         if (cf == NULL) {
893                 WriteMessage("File not found: no .ccd file");
894                 return NULL;
895         }
896         fclose(cf);
897
898         strcpy(a, ss);
899         strcat(a, ".pcd");
900         cf = fopen(a, "r");
901         if (cf == NULL) {
902                 WriteMessage("File not found: no .pcd file");
903                 return NULL;
904         }
905         fclose(cf);
906
907         newINT = new InterpEntry;
908         for(i = 0; i < MAXINSTANCES; i++) 
909                 newINT->RInstances[i] =- 1;
910
911         strcpy(b, rindex(ss, '/'));
912         for(i = 0; i < strlen(b); i++)
913                 b[i] = b[i+1];
914         if (info_messages) {
915                 sprintf(a, "%s : Start execution", b);
916                 WriteMessage(a); 
917         }
918
919         newint = freeINTid;
920         freeINTid++;
921         newINT->ID = newint;
922         strcpy(newINT->shortname, b);
923         strcpy(newINT->fullname, ss);
924
925         sprintf(a, "%s%d", IPATH, newint);
926         sprintf(cmd, "%s/modules/logint %s %s",
927                 getHomeDir(),
928                 a,
929                 ss);
930         if (r) {
931                 strcat(cmd, " r");
932         }
933         sprintf(b, " %s %s %s %s %s",
934                 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
935         strcat(cmd, b);
936         strcat(cmd, " &");
937
938         sock = socket(AF_UNIX, SOCK_STREAM, 0);
939         unlink(a);
940         bzero(&svr, sizeof(svr));
941         svr.sun_family = AF_UNIX;
942         strcpy(svr.sun_path, a);
943         len = strlen(svr.sun_path)+sizeof(svr.sun_family);
944         bind(sock, (struct sockaddr*)&svr, len);
945         listen(sock, 5);
946         system(cmd);
947         newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
948         //::close(sock);
949
950         if (newINT->sock > 0) { 
951                 fcntl(newINT->sock, F_SETFL, 
952                                 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
953                 on=1; 
954                 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
955                                                                 sizeof(on));
956                 if (r)
957                         newINT->remote = 1;
958                 else 
959                         newINT->remote = 0;
960
961                 bzero(&msg, sizeof(MESSAGE));
962                 msg.msg_type = MSG_VLP;
963                 msg.param.pword[0] = VLP_REGINT;
964                 msg.param.pword[1] = newINT->ID;
965                 sprintf(msg.param.pstr, "logi%d.net", newint);
966                 write(net_sock, &msg, sizeof(MESSAGE)); 
967
968                 Interpreters.append(newINT);
969                 newINT->notify = new QSocketNotifier(newINT->sock,
970                                                         QSocketNotifier::Read);
971                 connect(newINT->notify, SIGNAL(activated(int)), this,
972                                                         SLOT(IntMessage(int)));
973                 if (info_messages)
974                         WriteMessage("INTERPRETER successfully connected");
975         } else {
976                 WriteMessage("Cannot connect interpreter");
977         }
978
979         return newINT;
980 }
981
982 /**
983  * Allocates remote instance of interpreter
984  * @param interp Interpreter slot 
985  * @param on Node Number
986  */
987 void QKernel::RemoteInstance(InterpEntry *interp, int on)
988 {
989         MESSAGE m;
990
991         m.msg_type = MSG_NET;
992         m.param.pword[0] = NET_NODE_EXIST;
993         m.param.pword[1] = on;
994         m.param.pword[2] = interp->ID;
995         write(net_sock, &m, sizeof(MESSAGE));
996         bzero(&m, sizeof(MESSAGE));
997         while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
998                 read(net_sock, &m, sizeof(MESSAGE));
999
1000          /* means node exists */
1001         if (m.param.pword[1] == 1) {
1002                 m.msg_type = MSG_NET;
1003                 m.param.pword[0] = NET_TRANSMIT_CODE;
1004                 m.param.pword[1] = interp->ID;
1005                 m.param.pword[2] = on;
1006                 strcpy(m.param.pstr, interp->fullname);
1007                 write(net_sock, &m, sizeof(MESSAGE));
1008
1009                 Net_Notify->setEnabled(FALSE);
1010                 while ((m.msg_type != MSG_NET) ||
1011                         (m.param.pword[0] != NET_TRANSMITTED))
1012                         read(net_sock, &m, sizeof(MESSAGE));
1013
1014                 m.msg_type = MSG_NET;
1015                 m.param.pword[0] = NET_PROPAGATE;
1016                 m.param.pword[1] = MSG_VLP;
1017                 m.param.pword[2] = NodeNumber;
1018                 m.param.pword[3] = 0;
1019                 m.param.pword[4] = on;
1020                 m.param.pword[5] = 0;
1021                 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1022                 m.param.pword[7] = interp->ID;
1023                 strcpy(m.param.pstr, interp->shortname);
1024                 write(net_sock, &m, sizeof(MESSAGE));
1025
1026                 read(net_sock, &m, sizeof(MESSAGE));
1027                 while (1) {
1028                         if ((m.param.pword[0] == NET_PROPAGATE) &&
1029                                 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1030                                 interp->RInstances[on] = m.param.pword[7];
1031                                 break;
1032                         }
1033                         read(net_sock, &m, sizeof(MESSAGE));
1034                 }
1035
1036                 Net_Notify->setEnabled(TRUE);
1037
1038                 /*bzero(&m, sizeof(MESSAGE));*/
1039                 m.msg_type = MSG_VLP;
1040                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1041                 m.param.pword[1] = interp->RInstances[on];
1042                 write(interp->sock, &m, sizeof(MESSAGE));
1043         } else { /* There is no such a node! */
1044                 char s[255];
1045                 sprintf(s, "Warning: Node number %d not found!", on); 
1046                 WriteMessage(s);
1047                 WriteMessage("Allocating O-process on the local node");
1048                 bzero(&m, sizeof(MESSAGE));
1049                 m.msg_type = MSG_VLP;
1050                 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1051                 m.param.pword[1] = interp->ID;
1052                 write(interp->sock, &m, sizeof(MESSAGE));
1053         }
1054 }
1055
1056 /**
1057  * Closes all remote instances
1058  */
1059 void QKernel::CloseInstances(InterpEntry *e)
1060 {
1061         MESSAGE msg;
1062         int i;
1063
1064         if (info_messages)
1065                 WriteMessage("Closing remote instances");
1066
1067         for(i=0; i < MAXINSTANCES; i++)
1068                 if (e->RInstances[i]>=0) {
1069                         msg.msg_type = MSG_NET;
1070                         msg.param.pword[0] = NET_PROPAGATE;
1071                         msg.param.pword[1] = MSG_VLP;
1072                         msg.param.pword[2] = NodeNumber;
1073                         msg.param.pword[4] = i;
1074                         msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1075                         msg.param.pword[7] = e->RInstances[i];
1076                         write(net_sock, &msg, sizeof(MESSAGE));
1077                 }
1078 }
1079
1080 /**
1081  * Displays information about virtual machine
1082  */
1083 void QKernel::on_actionInfo_triggered()
1084 {
1085         MESSAGE m;
1086
1087         WriteMessage(CharLine);
1088         WriteMessage("### Virtual Machine Information ###");
1089         m.msg_type = MSG_NET;
1090         m.param.pword[0] = NET_GET_INFO;
1091         write(net_sock, &m, sizeof(MESSAGE));
1092         wait_for_info = TRUE;
1093 }
1094
1095 }
1096 }
1097
1098 /**
1099  * Program main function
1100  * All program arguments but the first one (argv[0]: program name) are saved and
1101  * passed to all dependent programs on their invocation.
1102  * @param argc Number of program arguments
1103  * @param argv Program arguments
1104  */
1105 int main(int argc, char **argv)
1106 {
1107         XInitThreads();
1108
1109         QApplication * app = new QApplication(argc, argv);
1110         loglan::vlp::QKernel kernel(argc, argv);
1111         kernel.show();
1112         
1113         return app->exec();
1114 }