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