1 /**************************************************************
3 Copyright (C) 1997 Oskar Swida
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.
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.
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.
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.
27 To contact the author, write:
28 e-mail: swida@aragorn.pb.bialystok.pl
30 ************************************************************/
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>
50 #include <QtCore/QSocketNotifier>
51 #include <QtGui/QCloseEvent>
52 #include <QtCore/QDir>
53 #include <QtCore/QProcess>
62 #include <netinet/in.h>
64 #include <libconfig.h>
68 #include "kernelwindow.h"
72 /* File resides in top directory (where are Makefiles)*/
73 #include "../../config.h"
76 char CharLine[25] = "________________________";
79 * Event invoked on program close.
80 * Closes application. Displays additional window to confirm exit.
82 void QKernel::closeEvent(QCloseEvent * e)
87 on_actionQuit_triggered();
91 void QKernel::setLocked(bool locked)
95 actionQuit->setDisabled(locked);
97 actionExecute->setDisabled(locked);
98 actionKill->setDisabled(locked);
99 actionMessage->setDisabled(locked);
100 actionConnect->setDisabled(locked);
101 actionDisconnect->setDisabled(locked);
102 actionInfo->setDisabled(locked);
105 /* Enable only menu entry for unlocking */
106 actionEditor->setDisabled(locked);
107 actionOptions->setDisabled(locked);
108 actionLock_console->setDisabled(locked);
109 actionUnlock_console->setDisabled(!locked);
113 * Kernel program constructor.
114 * Prepares everything to work.
116 QKernel::QKernel(int argc, char **argv)
120 QString arg0(argv[0]);
122 homeDir = QDir(arg0);
127 for(i = 0; (i < 5) && (i < argc-1); i++) {
128 strcpy(myargs[i], "");
130 strcpy(myargs[i], argv[i+1]);
134 QDir q(getRemoteDir());
137 q.mkpath(getRemoteDir());
140 info_messages = TRUE;
141 wait_for_info = FALSE;
143 setWindowTitle(PACKAGE_NAME);
149 ActiveConnections = 0;
150 strcpy(LockPasswd, "");
151 loadConfig(getConfigFilePath());
154 Net_Notify = new QSocketNotifier(net_sock, QSocketNotifier::Read, this);
155 connect(Net_Notify, SIGNAL(activated(int)), this, SLOT(NetMessage()));
158 QString QKernel::getConfigFilePath()
160 return homeDir.absoluteFilePath("vlp.cfg");
163 const char * QKernel::getHomeDir()
165 return homeDir.absolutePath().toStdString().c_str();
168 const char * QKernel::getRemoteDir()
170 return homeDir.absoluteFilePath(REMOTE_PATH).toStdString().c_str();
173 const char * QKernel::getNetModuleSocket()
175 return homeDir.absoluteFilePath(NPATH).toStdString().c_str();
178 const char * QKernel::getGraphModuleSocket()
180 return homeDir.absoluteFilePath(GPATH).toStdString().c_str();
183 void QKernel::loadConfig(const QString & fname)
185 loadConfig(fname.toStdString().c_str());
188 * Loads configuration from the given file.
189 * @param fname Filename of the configuration file.
191 void QKernel::loadConfig(const char * fname)
193 fprintf(stderr, "2: %s\n", fname);
195 config_setting_t *setting;
197 /* Hack for checking if file exists without using external libs.*/
199 FILE * file = fopen(fname, "rt");
201 fprintf(stderr, "Error: Cannot load configuration file: %s!\n",
205 /* File exists, so file has been locked. Release it. */
209 /* Read the file. If there is an error, report it and exit. */
210 if (!config_read(&cfg, file)) {
211 fprintf(stderr, "%s! In file %s, line %d\n",
212 config_error_text(&cfg),
213 config_error_file(&cfg),
214 config_error_line(&cfg));
215 config_destroy(&cfg);
220 setting = config_lookup(&cfg, "node_number");
222 NodeNumber = config_setting_get_int(setting);
224 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
225 "Warning", fname, "node_number");
226 config_destroy(&cfg);
231 setting = config_lookup(&cfg, "type");
233 /* same as strcmp(..) == 0 */
234 if (!strcmp(config_setting_get_string(setting), "explicit")) {
240 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
241 "Warning", fname, "type");
244 setting = config_lookup(&cfg, "host");
246 switch(config_setting_type(setting)) {
247 /* TODO: Deprecated. Made for back compatibility. */
248 case CONFIG_TYPE_STRING:
249 ConnectList.append(new ConnectEntry((char*)
250 config_setting_get_string(setting)));
252 case CONFIG_TYPE_ARRAY: {
253 int size = config_setting_length(setting);
254 for (int i = 0; i < size; i++) {
255 ConnectList.append(new ConnectEntry((char*)
256 config_setting_get_string_elem(setting,
262 fprintf(stderr, "%s! In file %s, bad entry type for %s."
263 " Will not be read.\n",
264 "Error", fname, "host");
267 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
268 "Warning", fname, "host");
271 setting = config_lookup(&cfg, "progdir");
273 strncpy(progdir, config_setting_get_string(setting), 256);
275 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
276 "Warning", fname, "progdir");
279 config_destroy(&cfg);
285 * Additional window id displayed to set which code to execute.
287 void QKernel::on_actionExecute_triggered()
290 QString s = QFileDialog::getOpenFileName(this, "Execute", progdir, "*.log");
293 i = s.indexOf(".log");
298 // @TODO: if no interpreter is running will result in killing app
299 RunIntModule((char*)s.toAscii().data(), 0);
304 * Invokes editor program
306 void QKernel::on_actionEditor_triggered()
308 QString program = getHomeDir();
309 program += "/modules/logedit";
313 if (execl(program.toStdString().c_str(),
322 WriteMessage("Executing logedit failed!");
328 * Invokes help program
330 void QKernel::on_actionHelp_triggered()
332 QString program = getHomeDir();
333 program += "/modules/loghelp";
335 QString docDir = getHomeDir();
340 if (execl(program.toStdString().c_str(),
341 docDir.toStdString().c_str(),
350 WriteMessage("Executing loghelp failed!");
356 * Invokes graphics module
358 void QKernel::RunGraphModule(char *sk)
362 QString program = getHomeDir();
363 program += "/modules/loggraph";
366 if (execl(program.toStdString().c_str(),
367 program.toStdString().c_str(),
377 WriteMessage("Executing loggraph failed!");
378 WriteMessage("Exiting...");
380 on_actionQuit_triggered();
384 WriteMessage("fork(loggraph) failed!");
385 WriteMessage("Exiting...");
387 on_actionQuit_triggered();
395 void QKernel::RunNetModule()
397 struct sockaddr_un svr;
402 QString program = getHomeDir();
403 program += "/modules/lognet";
407 if (execl(program.toStdString().c_str(),
408 program.toStdString().c_str(),
409 getNetModuleSocket(),
410 getConfigFilePath().toStdString().c_str(),
419 WriteMessage("Executing lognet failed!");
420 WriteMessage("Exiting...");
422 on_actionQuit_triggered();
426 WriteMessage("fork(lognet) failed!");
427 WriteMessage("Exiting...");
429 on_actionQuit_triggered();
433 /* -------- socket for NET module -------- */
434 unlink(getNetModuleSocket());
435 sock = socket(AF_UNIX, SOCK_STREAM, 0);
436 bzero(&svr, sizeof(svr));
437 svr.sun_family = AF_UNIX;
438 strcpy(svr.sun_path, getNetModuleSocket());
439 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
440 bind(sock, (struct sockaddr*)&svr, len);
443 net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
446 WriteMessage("NETWORK successfully connected");
447 fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock, F_GETFL, 0));
449 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
451 WriteMessage("Cannot connect NETWORK resources");
452 WriteMessage("Exiting...");
454 on_actionQuit_triggered();
459 * Connects to the specified address
460 * Additional window is displayed to connect to the specified address
462 void QKernel::on_actionConnect_triggered()
464 QDialog d(this, Qt::Dialog);
465 QLabel lab("IP Address:", &d);
466 QLineEdit ed("", &d);
467 QPushButton ob("", &d);
468 QPushButton cb("", &d);
471 ob.setGeometry(30, 60, 80, 30);
474 lab.setGeometry(10, 10, 60, 30);
475 lab.setText("Address");
476 ed.setGeometry(70, 10, 140, 30);
477 cb.setGeometry(130, 60, 80, 30);
478 cb.setText("Cancel");
481 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
482 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
484 m.msg_type = MSG_NET;
485 m.param.pword[0] = NET_CONNECT_TO;
486 strcpy(m.param.pstr, ed.text().toAscii().data());
487 write(net_sock, &m, sizeof(MESSAGE));
492 * Disconnects from virtual machine
494 void QKernel::on_actionDisconnect_triggered()
499 WriteMessage("Disconnecting from virtual machine");
501 msg.msg_type = MSG_NET;
502 msg.param.pword[0] = NET_DISCONNECT;
503 write(net_sock, &msg, sizeof(MESSAGE));
507 * Quits process. Closes VLP. Shows additional window to confirm exit.
509 void QKernel::on_actionQuit_triggered()
513 QMessageBox::StandardButton response = QMessageBox::question(this,
516 QMessageBox::Ok | QMessageBox::Cancel
520 if (response == QMessageBox::Cancel) {
524 msg.msg_type = MSG_NET;
525 msg.param.pword[0] = NET_DISCONNECT;
526 write(net_sock, &msg, sizeof(MESSAGE));*/
529 msg.msg_type = MSG_NET;
530 msg.param.pword[0] = NET_EXIT;
531 write(net_sock, &msg, sizeof(MESSAGE));
532 /* ::close(net_sock);*/
533 QApplication::instance()->quit();
537 * Sends message to node.
538 * Additional window is displayed to set Node Number of node where send message,
539 * and textfield to enter message.
541 void QKernel::on_actionMessage_triggered()
547 dlg = new QDialog(this, Qt::Dialog);
548 dlg->setWindowTitle("Send message to node");
550 nodenr = new QLineEdit("number", dlg);
551 nodenr->setGeometry(90, 10, 50, 30);
555 tmpQLabel = new QLabel("Node number:", dlg);
556 tmpQLabel->setGeometry(10, 10, 77, 30);
558 tmpQLabel = new QLabel("Message:", dlg);
559 tmpQLabel->setGeometry(10, 50, 70, 30);
562 msg = new QLineEdit("", dlg);
563 msg->setGeometry(80, 60, 330, 30);
566 ob = new QPushButton("Send", dlg);
567 ob->setGeometry(230, 10, 80, 30);
568 ob->setDefault(TRUE);
571 cb = new QPushButton("Cancel", dlg);
572 cb->setGeometry(330, 10, 80, 30);
573 dlg->resize(430, 110);
574 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
575 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
578 m.msg_type = MSG_NET;
579 m.param.pword[0] = NET_PROPAGATE;
580 m.param.pword[1] = MSG_VLP;
581 m.param.pword[2] = NodeNumber;
582 m.param.pword[4] = atoi(nodenr->text().toAscii().data());
583 m.param.pword[6] = VLP_WRITE;
584 strcpy(m.param.pstr, msg->text().toAscii().data());
585 write(net_sock, &m, sizeof(MESSAGE));
591 * Additional window is displayed to get ID of interpreter which should be
594 void QKernel::on_actionKill_triggered()
601 dlg = new QDialog(this, Qt::Dialog);
602 dlg->setWindowTitle("Kill interpreter");
604 nodenr = new QLineEdit("", dlg);
605 nodenr->setGeometry(90, 10, 50, 30);
607 QLabel * tmpQLabel = new QLabel("Interp. ID:", dlg);
608 tmpQLabel->setGeometry(10, 10, 77, 30);
610 QPushButton * ob = new QPushButton("Kill", dlg);
611 ob->setGeometry( 160, 10, 80, 30);
612 ob->setDefault(TRUE);
614 QPushButton * cb = new QPushButton("Cancel", dlg);
615 cb->setGeometry(260, 10, 80, 30);
616 dlg->resize(360, 50);
618 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
619 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
622 m.msg_type = MSG_INT;
623 m.param.pword[0] = INT_KILL;
624 pom = findINTbyID(atoi(nodenr->text().toAscii().data()));
627 write(pom->sock, &m, sizeof(MESSAGE));
629 WriteMessage("This is a remote instance of "
633 WriteMessage("Interpreter not found");
639 * Sends message to the net module.
641 void QKernel::NetMessage()
644 /* TODO: It has to be rewritten */
650 cnt = read(net_sock, &msg, sizeof(MESSAGE));
651 if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
652 switch(msg.param.pword[0]) {
654 WriteMessage(msg.param.pstr);
657 switch(msg.param.pword[1]) {
659 /* pom = find_link_by_ID(msg.param.pword[5]);
660 msg.msg_type = MSG_NET;
661 msg.param.pword[0] = NET_PROPAGATE;
662 send_int(pom, &msg);*/
665 switch(msg.param.pword[6]) {
667 QApplication::beep();
668 WriteMessage(CharLine);
670 "### Incoming Messsage ###");
671 sprintf(ss, "Mesg from Node %d: %s",
675 WriteMessage(CharLine);
677 case VLP_REMOTE_INSTANCE:
678 sprintf(ss, "%s/%s", getRemoteDir(),
682 WriteMessage("Running program:");
685 pom = RunIntModule(ss, 1);
687 pom->p_ctx.node = msg.param.pword[2];
688 pom->p_ctx.program_id =
690 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
693 case VLP_CLOSE_INSTANCE:
694 msg.msg_type = MSG_INT;
695 msg.param.pword[0] = INT_CLOSE_INSTANCE;
696 pom = findINTbyID(msg.param.pword[7]);
698 write(pom->sock, &msg,
701 m1.msg_type = MSG_VLP;
702 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
703 m1.param.pword[1] = pom->ID;
707 WriteMessage("Instance not found");
713 case NET_CONNECTIONS:
714 ActiveConnections = msg.param.pword[1];
715 WriteMessage(msg.param.pstr);
720 /* TODO: It has to be rewritten */
722 QString poms, poms1, poms2;
723 poms.sprintf("%s", msg.param.pstr);
724 while (poms.length() > 0) {
725 cnt = poms.indexOf(';');
727 poms1 = poms.left(cnt);
728 poms = poms.right(poms.length() - cnt - 1);
729 cnt = poms1.indexOf('=');
731 poms2 = poms1.left(cnt);
732 poms1 = poms1.right(poms1.length() - cnt - 1);
733 sprintf(ss, "Node: %s Addr: %s", poms2.toStdString().c_str(), poms1.toStdString().c_str());
741 wait_for_info = FALSE;
742 WriteMessage(CharLine);
749 * Sends message to the interpreter program.
750 * @param sock Interpreter socket to whom the message will be send.
752 void QKernel::IntMessage(int sock)
758 cnt = read(sock, &msg, sizeof(MESSAGE));
759 e = findINTbySocket(sock);
760 if ((cnt > 0) && (e != NULL)) {
761 switch (msg.msg_type) {
763 if (msg.param.pword[0] == GRAPH_ALLOCATE) {
764 RunGraphModule(msg.param.pstr);
768 write(net_sock, &msg, sizeof(MESSAGE));
771 switch(msg.param.pword[0]) {
772 case VLP_REMOTE_INSTANCE_PLEASE:
773 RemoteInstance(e, msg.param.pword[2]);
778 switch(msg.param.pword[0]) {
783 m.msg_type = MSG_VLP;
784 m.param.pword[0] = VLP_INTERPRETER_DOWN;
785 m.param.pword[1] = e->ID;
786 write(net_sock, &m, sizeof(MESSAGE));
791 /* TODO: Check this */
792 Interpreters.removeOne(e);
796 sprintf(ss, "%s : End of program "
797 "execution", msg.param.pstr);
802 msg.msg_type = MSG_INT;
803 msg.param.pword[0] = INT_CTX;
804 msg.param.pword[1] = NodeNumber;
805 msg.param.pword[2] = e->ID;
807 msg.param.pword[3] = e->p_ctx.node;
811 write(sock, &msg, sizeof(MESSAGE));
820 * Writes message to kernel logger.
821 * @parame msg String with message to log
823 void QKernel::WriteMessage(char *msg)
827 x = desktop->textCursor().blockNumber();
828 y = desktop->textCursor().columnNumber();
834 desktop->setReadOnly(FALSE);
835 desktop->append(msg);
836 desktop->setReadOnly(TRUE);
838 QTextCursor tmpCursor = desktop->textCursor();
839 tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
840 desktop->setTextCursor(tmpCursor);
844 if (desktop->document()->blockCount() > 100) {
850 * Adds checkbox to menu item. If it is checked additional info messages are
853 void QKernel::on_actionInfo_messages_triggered()
855 if (toolsMenu != NULL) {
856 info_messages = !actionInfo_messages->isChecked();
857 actionInfo_messages->setChecked(info_messages);
858 fprintf(stderr, "Info is checked? %s\n", info_messages ? "yes" : "no");
863 * Allows to set options in GUI window.
864 * Additional window is displayed to set kernel options which are saved in
865 * vlp.cfg file in kernel executable directory.
867 void QKernel::on_actionOptions_triggered()
869 OptionsDialog optionsDialog(getConfigFilePath(), this);
870 if (optionsDialog.exec()) {
871 optionsDialog.saveConfig(getConfigFilePath());
873 loadConfig(getConfigFilePath());
878 * Locks kernel program.
879 * Additional window is displayed to enter password and retype it. If both are
880 * same kernel window is locked.
882 void QKernel::on_actionLock_console_triggered()
884 LockDialog lockDialog(this);
886 if (lockDialog.exec()) {
887 QString password = lockDialog.getPassword();
888 if (lockDialog.getPassword().size() > 0) {
889 strcpy(LockPasswd, password.toAscii().data());
892 if (lockDialog.exec()) {
893 password = lockDialog.getPassword();
894 if (password == LockPasswd) {
896 WriteMessage("CONSOLE LOCKED");
898 QMessageBox msg(this);
899 msg.setText("Not matching!");
900 msg.setButtonText(0, "Close");
902 strcpy(LockPasswd, "");
905 strcpy(LockPasswd, "");
912 * Unlocks kernel program.
913 * Additional window is displayed to enter password. If it is correct, kernel
916 void QKernel::on_actionUnlock_console_triggered()
918 QDialog d(this, Qt::Dialog);
919 d.setWindowTitle("Enter password");
921 QLabel lab("Password:", &d);
922 lab.setGeometry(10, 10, 60, 30);
924 QLineEdit ed("", &d);
925 ed.setGeometry(70, 10, 140, 30);
926 ed.setEchoMode(QLineEdit::Password);
928 QPushButton ob("Ok", &d);
929 ob.setGeometry(30, 60, 80, 30);
931 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
933 QPushButton cb("Cancel", &d);
934 cb.setGeometry(130, 60, 80, 30);
935 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
940 if (strcmp(ed.text().toAscii().data(), LockPasswd) == 0) {
942 WriteMessage("CONSOLE UNLOCKED");
944 QMessageBox msg(this);
945 msg.setText("Wrong password!");
946 msg.setButtonText(0, "Close");
953 * Writes init message in kernel
955 void QKernel::InitMessage()
957 WriteMessage("\n " PACKAGE_STRING ": READY \n");
961 * Finds Interpreter by its socket
962 * @param _id ID of the socket
963 * @return returns pointer to the found interpreter slot. NULL otherwise
965 InterpEntry *QKernel::findINTbySocket(int _id)
967 InterpEntry *pom = NULL;
969 for (int i = 0; i < Interpreters.size(); i++) {
970 if (Interpreters.at(i)->sock == _id) {
971 pom = Interpreters.at(i);
980 * Finds Interpreter by its ID.
981 * @param _id ID of the interpreter
982 * @return returns pointer to the found interpreter slot. NULL otherwise
984 InterpEntry *QKernel::findINTbyID(int _id)
986 InterpEntry *pom = NULL;
988 for (int i = 0; i < Interpreters.size(); i++) {
989 if (Interpreters.at(i)->ID == _id) {
990 pom = Interpreters.at(i);
1000 * Connects interpreter
1001 * @param ss full filepath with filename but without extension of the loglan
1003 * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
1005 * @return Returns pointer to newly created interpreter slot, or NULL on error.
1007 InterpEntry *QKernel::RunIntModule(char *ss, int r)
1009 char a[256], b[255];
1010 struct sockaddr_un svr;
1017 InterpEntry *newINT = NULL;
1023 WriteMessage("File not found: no .ccd file");
1032 WriteMessage("File not found: no .pcd file");
1037 newINT = new InterpEntry;
1038 for(i = 0; i < MAXINSTANCES; i++)
1039 newINT->RInstances[i] =- 1;
1041 strcpy(b, rindex(ss, '/'));
1042 for(i = 0; i < strlen(b); i++)
1044 if (info_messages) {
1045 sprintf(a, "%s : Start execution", b);
1051 newINT->ID = newint;
1052 strcpy(newINT->shortname, b);
1053 strcpy(newINT->fullname, ss);
1055 sprintf(a, "%s%d", IPATH, newint);
1056 sprintf(cmd, "%s/modules/logint %s %s",
1063 sprintf(b, " %s %s %s %s %s",
1064 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
1068 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1070 bzero(&svr, sizeof(svr));
1071 svr.sun_family = AF_UNIX;
1072 strcpy(svr.sun_path, a);
1073 len = strlen(svr.sun_path)+sizeof(svr.sun_family);
1074 bind(sock, (struct sockaddr*)&svr, len);
1077 newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
1080 if (newINT->sock > 0) {
1081 fcntl(newINT->sock, F_SETFL,
1082 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
1084 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
1091 bzero(&msg, sizeof(MESSAGE));
1092 msg.msg_type = MSG_VLP;
1093 msg.param.pword[0] = VLP_REGINT;
1094 msg.param.pword[1] = newINT->ID;
1095 sprintf(msg.param.pstr, "logi%d.net", newint);
1096 write(net_sock, &msg, sizeof(MESSAGE));
1098 Interpreters.append(newINT);
1099 newINT->notify = new QSocketNotifier(newINT->sock,
1100 QSocketNotifier::Read);
1101 connect(newINT->notify, SIGNAL(activated(int)), this,
1102 SLOT(IntMessage(int)));
1104 WriteMessage("INTERPRETER successfully connected");
1106 WriteMessage("Cannot connect interpreter");
1113 * Allocates remote instance of interpreter
1114 * @param interp Interpreter slot
1115 * @param on Node Number
1117 void QKernel::RemoteInstance(InterpEntry *interp, int on)
1122 m.msg_type = MSG_NET;
1123 m.param.pword[0] = NET_NODE_EXIST;
1124 m.param.pword[1] = on;
1125 m.param.pword[2] = interp->ID;
1126 write(net_sock, &m, sizeof(MESSAGE));
1127 bzero(&m, sizeof(MESSAGE));
1128 while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
1129 read(net_sock, &m, sizeof(MESSAGE));
1131 /* means node exists */
1132 if (m.param.pword[1] == 1) {
1133 m.msg_type = MSG_NET;
1134 m.param.pword[0] = NET_TRANSMIT_CODE;
1135 m.param.pword[1] = interp->ID;
1136 m.param.pword[2] = on;
1137 strcpy(m.param.pstr, interp->fullname);
1138 write(net_sock, &m, sizeof(MESSAGE));
1140 Net_Notify->setEnabled(FALSE);
1141 while ((m.msg_type != MSG_NET) ||
1142 (m.param.pword[0] != NET_TRANSMITTED))
1143 read(net_sock, &m, sizeof(MESSAGE));
1145 m.msg_type = MSG_NET;
1146 m.param.pword[0] = NET_PROPAGATE;
1147 m.param.pword[1] = MSG_VLP;
1148 m.param.pword[2] = NodeNumber;
1149 m.param.pword[3] = 0;
1150 m.param.pword[4] = on;
1151 m.param.pword[5] = 0;
1152 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1153 m.param.pword[7] = interp->ID;
1154 strcpy(m.param.pstr, interp->shortname);
1155 write(net_sock, &m, sizeof(MESSAGE));
1157 read(net_sock, &m, sizeof(MESSAGE));
1159 if ((m.param.pword[0] == NET_PROPAGATE) &&
1160 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1161 interp->RInstances[on] = m.param.pword[7];
1164 read(net_sock, &m, sizeof(MESSAGE));
1167 Net_Notify->setEnabled(TRUE);
1169 /*bzero(&m, sizeof(MESSAGE));*/
1170 m.msg_type = MSG_VLP;
1171 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1172 m.param.pword[1] = interp->RInstances[on];
1173 write(interp->sock, &m, sizeof(MESSAGE));
1174 } else { /* There is no such a node! */
1175 sprintf(s, "Warning: Node number %d not found!", on);
1177 WriteMessage("Allocating O-process on the local node");
1178 bzero(&m, sizeof(MESSAGE));
1179 m.msg_type = MSG_VLP;
1180 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1181 m.param.pword[1] = interp->ID;
1182 write(interp->sock, &m, sizeof(MESSAGE));
1187 * Closes all remote instances
1189 void QKernel::CloseInstances(InterpEntry *e)
1195 WriteMessage("Closing remote instances");
1197 for(i=0; i < MAXINSTANCES; i++)
1198 if (e->RInstances[i]>=0) {
1199 msg.msg_type = MSG_NET;
1200 msg.param.pword[0] = NET_PROPAGATE;
1201 msg.param.pword[1] = MSG_VLP;
1202 msg.param.pword[2] = NodeNumber;
1203 msg.param.pword[4] = i;
1204 msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1205 msg.param.pword[7] = e->RInstances[i];
1206 write(net_sock, &msg, sizeof(MESSAGE));
1211 * Displays information about virtual machine
1213 void QKernel::on_actionInfo_triggered()
1217 WriteMessage(CharLine);
1218 WriteMessage("### Virtual Machine Information ###");
1219 m.msg_type = MSG_NET;
1220 m.param.pword[0] = NET_GET_INFO;
1221 write(net_sock, &m, sizeof(MESSAGE));
1222 wait_for_info = TRUE;
1226 * Program main function
1227 * All program arguments but the first one (argv[0]: program name) are saved and
1228 * passed to all dependent programs on their invocation.
1229 * @param argc Number of program arguments
1230 * @param argv Program arguments
1232 int main(int argc, char **argv)
1236 QApplication * app = new QApplication(argc, argv);
1237 QKernel kernel(argc, argv);
1239 kernel.InitMessage();