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