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 "ui/kernelwindow.h"
71 #include "kill_interpreter_dialog.h"
73 /* File resides in top directory (where are Makefiles)*/
74 #include "../../config.h"
77 char CharLine[25] = "________________________";
80 * Event invoked on program close.
81 * Closes application. Displays additional window to confirm exit.
83 void QKernel::closeEvent(QCloseEvent * e)
88 on_actionQuit_triggered();
92 void QKernel::setLocked(bool locked)
96 actionQuit->setDisabled(locked);
98 actionExecute->setDisabled(locked);
99 actionKill->setDisabled(locked);
100 actionMessage->setDisabled(locked);
101 actionConnect->setDisabled(locked);
102 actionDisconnect->setDisabled(locked);
103 actionInfo->setDisabled(locked);
106 /* Enable only menu entry for unlocking */
107 actionEditor->setDisabled(locked);
108 actionOptions->setDisabled(locked);
109 actionLock_console->setDisabled(locked);
110 actionUnlock_console->setDisabled(!locked);
114 * Kernel program constructor.
115 * Prepares everything to work.
117 QKernel::QKernel(int argc, char **argv)
121 QString arg0(argv[0]);
123 homeDir = QDir(arg0);
128 for(i = 0; (i < 5) && (i < argc-1); i++) {
129 strcpy(myargs[i], "");
131 strcpy(myargs[i], argv[i+1]);
135 QDir q(getRemoteDir());
138 q.mkpath(getRemoteDir());
141 info_messages = TRUE;
142 wait_for_info = FALSE;
144 setWindowTitle(PACKAGE_NAME);
150 ActiveConnections = 0;
151 strcpy(LockPasswd, "");
152 loadConfig(getConfigFilePath());
155 Net_Notify = new QSocketNotifier(net_sock, QSocketNotifier::Read, this);
156 connect(Net_Notify, SIGNAL(activated(int)), this, SLOT(NetMessage()));
159 QString QKernel::getConfigFilePath()
161 return homeDir.absoluteFilePath("vlp.cfg");
164 const char * QKernel::getHomeDir()
166 return homeDir.absolutePath().toStdString().c_str();
169 const char * QKernel::getRemoteDir()
171 return homeDir.absoluteFilePath(REMOTE_PATH).toStdString().c_str();
174 const char * QKernel::getNetModuleSocket()
176 return homeDir.absoluteFilePath(NPATH).toStdString().c_str();
179 const char * QKernel::getGraphModuleSocket()
181 return homeDir.absoluteFilePath(GPATH).toStdString().c_str();
184 void QKernel::loadConfig(const QString & fname)
186 loadConfig(fname.toStdString().c_str());
189 * Loads configuration from the given file.
190 * @param fname Filename of the configuration file.
192 void QKernel::loadConfig(const char * fname)
194 fprintf(stderr, "2: %s\n", fname);
196 config_setting_t *setting;
198 /* Hack for checking if file exists without using external libs.*/
200 FILE * file = fopen(fname, "rt");
202 fprintf(stderr, "Error: Cannot load configuration file: %s!\n",
206 /* File exists, so file has been locked. Release it. */
210 /* Read the file. If there is an error, report it and exit. */
211 if (!config_read(&cfg, file)) {
212 fprintf(stderr, "%s! In file %s, line %d\n",
213 config_error_text(&cfg),
214 config_error_file(&cfg),
215 config_error_line(&cfg));
216 config_destroy(&cfg);
221 setting = config_lookup(&cfg, "node_number");
223 NodeNumber = config_setting_get_int(setting);
225 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
226 "Warning", fname, "node_number");
227 config_destroy(&cfg);
232 setting = config_lookup(&cfg, "type");
234 /* same as strcmp(..) == 0 */
235 if (!strcmp(config_setting_get_string(setting), "explicit")) {
241 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
242 "Warning", fname, "type");
245 setting = config_lookup(&cfg, "host");
247 switch(config_setting_type(setting)) {
248 /* TODO: Deprecated. Made for back compatibility. */
249 case CONFIG_TYPE_STRING:
250 ConnectList.append(new ConnectEntry((char*)
251 config_setting_get_string(setting)));
253 case CONFIG_TYPE_ARRAY: {
254 int size = config_setting_length(setting);
255 for (int i = 0; i < size; i++) {
256 ConnectList.append(new ConnectEntry((char*)
257 config_setting_get_string_elem(setting,
263 fprintf(stderr, "%s! In file %s, bad entry type for %s."
264 " Will not be read.\n",
265 "Error", fname, "host");
268 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
269 "Warning", fname, "host");
272 setting = config_lookup(&cfg, "progdir");
274 strncpy(progdir, config_setting_get_string(setting), 256);
276 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
277 "Warning", fname, "progdir");
280 config_destroy(&cfg);
286 * Additional window id displayed to set which code to execute.
288 void QKernel::on_actionExecute_triggered()
291 QString s = QFileDialog::getOpenFileName(this, "Execute", progdir, "*.log");
294 i = s.indexOf(".log");
299 // @TODO: if no interpreter is running will result in killing app
300 RunIntModule((char*)s.toAscii().data(), 0);
305 * Invokes editor program
307 void QKernel::on_actionEditor_triggered()
309 QString program = getHomeDir();
310 program += "/modules/logedit";
314 if (execl(program.toStdString().c_str(),
323 WriteMessage("Executing logedit failed!");
329 * Invokes help program
331 void QKernel::on_actionHelp_triggered()
333 QString program = getHomeDir();
334 program += "/modules/loghelp";
336 QString docDir = getHomeDir();
341 if (execl(program.toStdString().c_str(),
342 docDir.toStdString().c_str(),
351 WriteMessage("Executing loghelp failed!");
357 * Invokes graphics module
359 void QKernel::RunGraphModule(char *sk)
363 QString program = getHomeDir();
364 program += "/modules/loggraph";
367 if (execl(program.toStdString().c_str(),
368 program.toStdString().c_str(),
378 WriteMessage("Executing loggraph failed!");
379 WriteMessage("Exiting...");
381 on_actionQuit_triggered();
385 WriteMessage("fork(loggraph) failed!");
386 WriteMessage("Exiting...");
388 on_actionQuit_triggered();
396 void QKernel::RunNetModule()
398 struct sockaddr_un svr;
403 QString program = getHomeDir();
404 program += "/modules/lognet";
408 if (execl(program.toStdString().c_str(),
409 program.toStdString().c_str(),
410 getNetModuleSocket(),
411 getConfigFilePath().toStdString().c_str(),
420 WriteMessage("Executing lognet failed!");
421 WriteMessage("Exiting...");
423 on_actionQuit_triggered();
427 WriteMessage("fork(lognet) failed!");
428 WriteMessage("Exiting...");
430 on_actionQuit_triggered();
434 /* -------- socket for NET module -------- */
435 unlink(getNetModuleSocket());
436 sock = socket(AF_UNIX, SOCK_STREAM, 0);
437 bzero(&svr, sizeof(svr));
438 svr.sun_family = AF_UNIX;
439 strcpy(svr.sun_path, getNetModuleSocket());
440 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
441 bind(sock, (struct sockaddr*)&svr, len);
444 net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
447 WriteMessage("NETWORK successfully connected");
448 fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock, F_GETFL, 0));
450 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
452 WriteMessage("Cannot connect NETWORK resources");
453 WriteMessage("Exiting...");
455 on_actionQuit_triggered();
460 * Connects to the specified address
461 * Additional window is displayed to connect to the specified address
463 void QKernel::on_actionConnect_triggered()
465 QDialog d(this, Qt::Dialog);
466 QLabel lab("IP Address:", &d);
467 QLineEdit ed("", &d);
468 QPushButton ob("", &d);
469 QPushButton cb("", &d);
472 ob.setGeometry(30, 60, 80, 30);
475 lab.setGeometry(10, 10, 60, 30);
476 lab.setText("Address");
477 ed.setGeometry(70, 10, 140, 30);
478 cb.setGeometry(130, 60, 80, 30);
479 cb.setText("Cancel");
482 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
483 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
485 m.msg_type = MSG_NET;
486 m.param.pword[0] = NET_CONNECT_TO;
487 strcpy(m.param.pstr, ed.text().toAscii().data());
488 write(net_sock, &m, sizeof(MESSAGE));
493 * Disconnects from virtual machine
495 void QKernel::on_actionDisconnect_triggered()
500 WriteMessage("Disconnecting from virtual machine");
502 msg.msg_type = MSG_NET;
503 msg.param.pword[0] = NET_DISCONNECT;
504 write(net_sock, &msg, sizeof(MESSAGE));
508 * Quits process. Closes VLP. Shows additional window to confirm exit.
510 void QKernel::on_actionQuit_triggered()
514 QMessageBox::StandardButton response = QMessageBox::question(this,
517 QMessageBox::Ok | QMessageBox::Cancel
521 if (response == QMessageBox::Cancel) {
525 msg.msg_type = MSG_NET;
526 msg.param.pword[0] = NET_DISCONNECT;
527 write(net_sock, &msg, sizeof(MESSAGE));*/
530 msg.msg_type = MSG_NET;
531 msg.param.pword[0] = NET_EXIT;
532 write(net_sock, &msg, sizeof(MESSAGE));
533 /* ::close(net_sock);*/
534 QApplication::instance()->quit();
538 * Sends message to node.
539 * Additional window is displayed to set Node Number of node where send message,
540 * and textfield to enter message.
542 void QKernel::on_actionMessage_triggered()
548 dlg = new QDialog(this, Qt::Dialog);
549 dlg->setWindowTitle("Send message to node");
551 nodenr = new QLineEdit("number", dlg);
552 nodenr->setGeometry(90, 10, 50, 30);
556 tmpQLabel = new QLabel("Node number:", dlg);
557 tmpQLabel->setGeometry(10, 10, 77, 30);
559 tmpQLabel = new QLabel("Message:", dlg);
560 tmpQLabel->setGeometry(10, 50, 70, 30);
563 msg = new QLineEdit("", dlg);
564 msg->setGeometry(80, 60, 330, 30);
567 ob = new QPushButton("Send", dlg);
568 ob->setGeometry(230, 10, 80, 30);
569 ob->setDefault(TRUE);
572 cb = new QPushButton("Cancel", dlg);
573 cb->setGeometry(330, 10, 80, 30);
574 dlg->resize(430, 110);
575 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
576 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
579 m.msg_type = MSG_NET;
580 m.param.pword[0] = NET_PROPAGATE;
581 m.param.pword[1] = MSG_VLP;
582 m.param.pword[2] = NodeNumber;
583 m.param.pword[4] = atoi(nodenr->text().toAscii().data());
584 m.param.pword[6] = VLP_WRITE;
585 strcpy(m.param.pstr, msg->text().toAscii().data());
586 write(net_sock, &m, sizeof(MESSAGE));
592 * Additional window is displayed to get ID of interpreter which should be
595 void QKernel::on_actionKill_triggered()
597 KillInterpreterDialog dialog(this);
598 dialog.setWindowTitle("Kill interpreter");
601 InterpEntry *interpreter;
604 m.msg_type = MSG_INT;
605 m.param.pword[0] = INT_KILL;
606 interpreter = findINTbyID(dialog.getInterpreterId());
607 if (interpreter != NULL) {
608 if (!(interpreter->remote))
609 write(interpreter->sock, &m, sizeof(MESSAGE));
611 WriteMessage("This is a remote instance of a program!");
614 WriteMessage("Interpreter not found");
620 * Sends message to the net module.
622 void QKernel::NetMessage()
625 /* TODO: It has to be rewritten */
631 cnt = read(net_sock, &msg, sizeof(MESSAGE));
632 if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
633 switch(msg.param.pword[0]) {
635 WriteMessage(msg.param.pstr);
638 switch(msg.param.pword[1]) {
640 /* pom = find_link_by_ID(msg.param.pword[5]);
641 msg.msg_type = MSG_NET;
642 msg.param.pword[0] = NET_PROPAGATE;
643 send_int(pom, &msg);*/
646 switch(msg.param.pword[6]) {
648 QApplication::beep();
649 WriteMessage(CharLine);
651 "### Incoming Messsage ###");
652 sprintf(ss, "Mesg from Node %d: %s",
656 WriteMessage(CharLine);
658 case VLP_REMOTE_INSTANCE:
659 sprintf(ss, "%s/%s", getRemoteDir(),
663 WriteMessage("Running program:");
666 pom = RunIntModule(ss, 1);
668 pom->p_ctx.node = msg.param.pword[2];
669 pom->p_ctx.program_id =
671 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
674 case VLP_CLOSE_INSTANCE:
675 msg.msg_type = MSG_INT;
676 msg.param.pword[0] = INT_CLOSE_INSTANCE;
677 pom = findINTbyID(msg.param.pword[7]);
679 write(pom->sock, &msg,
682 m1.msg_type = MSG_VLP;
683 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
684 m1.param.pword[1] = pom->ID;
688 WriteMessage("Instance not found");
694 case NET_CONNECTIONS:
695 ActiveConnections = msg.param.pword[1];
696 WriteMessage(msg.param.pstr);
701 /* TODO: It has to be rewritten */
703 QString poms, poms1, poms2;
704 poms.sprintf("%s", msg.param.pstr);
705 while (poms.length() > 0) {
706 cnt = poms.indexOf(';');
708 poms1 = poms.left(cnt);
709 poms = poms.right(poms.length() - cnt - 1);
710 cnt = poms1.indexOf('=');
712 poms2 = poms1.left(cnt);
713 poms1 = poms1.right(poms1.length() - cnt - 1);
714 sprintf(ss, "Node: %s Addr: %s", poms2.toStdString().c_str(), poms1.toStdString().c_str());
722 wait_for_info = FALSE;
723 WriteMessage(CharLine);
730 * Sends message to the interpreter program.
731 * @param sock Interpreter socket to whom the message will be send.
733 void QKernel::IntMessage(int sock)
739 cnt = read(sock, &msg, sizeof(MESSAGE));
740 e = findINTbySocket(sock);
741 if ((cnt > 0) && (e != NULL)) {
742 switch (msg.msg_type) {
744 if (msg.param.pword[0] == GRAPH_ALLOCATE) {
745 RunGraphModule(msg.param.pstr);
749 write(net_sock, &msg, sizeof(MESSAGE));
752 switch(msg.param.pword[0]) {
753 case VLP_REMOTE_INSTANCE_PLEASE:
754 RemoteInstance(e, msg.param.pword[2]);
759 switch(msg.param.pword[0]) {
764 m.msg_type = MSG_VLP;
765 m.param.pword[0] = VLP_INTERPRETER_DOWN;
766 m.param.pword[1] = e->ID;
767 write(net_sock, &m, sizeof(MESSAGE));
772 /* TODO: Check this */
773 Interpreters.removeOne(e);
777 sprintf(ss, "%s : End of program "
778 "execution", msg.param.pstr);
783 msg.msg_type = MSG_INT;
784 msg.param.pword[0] = INT_CTX;
785 msg.param.pword[1] = NodeNumber;
786 msg.param.pword[2] = e->ID;
788 msg.param.pword[3] = e->p_ctx.node;
792 write(sock, &msg, sizeof(MESSAGE));
801 * Writes message to kernel logger.
802 * @parame msg String with message to log
804 void QKernel::WriteMessage(char *msg)
808 x = desktop->textCursor().blockNumber();
809 y = desktop->textCursor().columnNumber();
815 desktop->setReadOnly(FALSE);
816 desktop->append(msg);
817 desktop->setReadOnly(TRUE);
819 QTextCursor tmpCursor = desktop->textCursor();
820 tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
821 desktop->setTextCursor(tmpCursor);
825 if (desktop->document()->blockCount() > 100) {
831 * Adds checkbox to menu item. If it is checked additional info messages are
834 void QKernel::on_actionInfo_messages_triggered()
836 if (toolsMenu != NULL) {
837 info_messages = actionInfo_messages->isChecked();
838 actionInfo_messages->setChecked(info_messages);
843 * Allows to set options in GUI window.
844 * Additional window is displayed to set kernel options which are saved in
845 * vlp.cfg file in kernel executable directory.
847 void QKernel::on_actionOptions_triggered()
849 OptionsDialog optionsDialog(getConfigFilePath(), this);
850 if (optionsDialog.exec()) {
851 optionsDialog.saveConfig(getConfigFilePath());
853 loadConfig(getConfigFilePath());
858 * Locks kernel program.
859 * Additional window is displayed to enter password and retype it. If both are
860 * same kernel window is locked.
862 void QKernel::on_actionLock_console_triggered()
864 LockDialog lockDialog(this);
866 if (lockDialog.exec()) {
867 QString password = lockDialog.getPassword();
868 if (lockDialog.getPassword().size() > 0) {
869 strcpy(LockPasswd, password.toStdString().c_str());
872 if (lockDialog.exec()) {
873 password = lockDialog.getPassword();
874 if (password == LockPasswd) {
876 WriteMessage("CONSOLE LOCKED");
878 QMessageBox msg(this);
879 msg.setText("Not matching!");
880 msg.setButtonText(0, "Close");
882 strcpy(LockPasswd, "");
885 strcpy(LockPasswd, "");
892 * Unlocks kernel program.
893 * Additional window is displayed to enter password. If it is correct, kernel
896 void QKernel::on_actionUnlock_console_triggered()
898 LockDialog lockDialog(this);
900 if (lockDialog.exec()) {
901 QString password = lockDialog.getPassword();
902 if (strcmp(password.toStdString().c_str(), LockPasswd) == 0) {
904 WriteMessage("CONSOLE UNLOCKED");
906 QMessageBox msg(this);
907 msg.setText("Wrong password!");
908 msg.setButtonText(0, "Close");
915 * Writes init message in kernel
917 void QKernel::InitMessage()
919 WriteMessage("\n " PACKAGE_STRING ": READY \n");
923 * Finds Interpreter by its socket
924 * @param _id ID of the socket
925 * @return returns pointer to the found interpreter slot. NULL otherwise
927 InterpEntry *QKernel::findINTbySocket(int _id)
929 InterpEntry *pom = NULL;
931 for (int i = 0; i < Interpreters.size(); i++) {
932 if (Interpreters.at(i)->sock == _id) {
933 pom = Interpreters.at(i);
942 * Finds Interpreter by its ID.
943 * @param _id ID of the interpreter
944 * @return returns pointer to the found interpreter slot. NULL otherwise
946 InterpEntry *QKernel::findINTbyID(int _id)
948 InterpEntry *pom = NULL;
950 for (int i = 0; i < Interpreters.size(); i++) {
951 if (Interpreters.at(i)->ID == _id) {
952 pom = Interpreters.at(i);
962 * Connects interpreter
963 * @param ss full filepath with filename but without extension of the loglan
965 * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
967 * @return Returns pointer to newly created interpreter slot, or NULL on error.
969 InterpEntry *QKernel::RunIntModule(char *ss, int r)
972 struct sockaddr_un svr;
979 InterpEntry *newINT = NULL;
985 WriteMessage("File not found: no .ccd file");
994 WriteMessage("File not found: no .pcd file");
999 newINT = new InterpEntry;
1000 for(i = 0; i < MAXINSTANCES; i++)
1001 newINT->RInstances[i] =- 1;
1003 strcpy(b, rindex(ss, '/'));
1004 for(i = 0; i < strlen(b); i++)
1006 if (info_messages) {
1007 sprintf(a, "%s : Start execution", b);
1013 newINT->ID = newint;
1014 strcpy(newINT->shortname, b);
1015 strcpy(newINT->fullname, ss);
1017 sprintf(a, "%s%d", IPATH, newint);
1018 sprintf(cmd, "%s/modules/logint %s %s",
1025 sprintf(b, " %s %s %s %s %s",
1026 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
1030 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1032 bzero(&svr, sizeof(svr));
1033 svr.sun_family = AF_UNIX;
1034 strcpy(svr.sun_path, a);
1035 len = strlen(svr.sun_path)+sizeof(svr.sun_family);
1036 bind(sock, (struct sockaddr*)&svr, len);
1039 newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
1042 if (newINT->sock > 0) {
1043 fcntl(newINT->sock, F_SETFL,
1044 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
1046 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
1053 bzero(&msg, sizeof(MESSAGE));
1054 msg.msg_type = MSG_VLP;
1055 msg.param.pword[0] = VLP_REGINT;
1056 msg.param.pword[1] = newINT->ID;
1057 sprintf(msg.param.pstr, "logi%d.net", newint);
1058 write(net_sock, &msg, sizeof(MESSAGE));
1060 Interpreters.append(newINT);
1061 newINT->notify = new QSocketNotifier(newINT->sock,
1062 QSocketNotifier::Read);
1063 connect(newINT->notify, SIGNAL(activated(int)), this,
1064 SLOT(IntMessage(int)));
1066 WriteMessage("INTERPRETER successfully connected");
1068 WriteMessage("Cannot connect interpreter");
1075 * Allocates remote instance of interpreter
1076 * @param interp Interpreter slot
1077 * @param on Node Number
1079 void QKernel::RemoteInstance(InterpEntry *interp, int on)
1084 m.msg_type = MSG_NET;
1085 m.param.pword[0] = NET_NODE_EXIST;
1086 m.param.pword[1] = on;
1087 m.param.pword[2] = interp->ID;
1088 write(net_sock, &m, sizeof(MESSAGE));
1089 bzero(&m, sizeof(MESSAGE));
1090 while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
1091 read(net_sock, &m, sizeof(MESSAGE));
1093 /* means node exists */
1094 if (m.param.pword[1] == 1) {
1095 m.msg_type = MSG_NET;
1096 m.param.pword[0] = NET_TRANSMIT_CODE;
1097 m.param.pword[1] = interp->ID;
1098 m.param.pword[2] = on;
1099 strcpy(m.param.pstr, interp->fullname);
1100 write(net_sock, &m, sizeof(MESSAGE));
1102 Net_Notify->setEnabled(FALSE);
1103 while ((m.msg_type != MSG_NET) ||
1104 (m.param.pword[0] != NET_TRANSMITTED))
1105 read(net_sock, &m, sizeof(MESSAGE));
1107 m.msg_type = MSG_NET;
1108 m.param.pword[0] = NET_PROPAGATE;
1109 m.param.pword[1] = MSG_VLP;
1110 m.param.pword[2] = NodeNumber;
1111 m.param.pword[3] = 0;
1112 m.param.pword[4] = on;
1113 m.param.pword[5] = 0;
1114 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1115 m.param.pword[7] = interp->ID;
1116 strcpy(m.param.pstr, interp->shortname);
1117 write(net_sock, &m, sizeof(MESSAGE));
1119 read(net_sock, &m, sizeof(MESSAGE));
1121 if ((m.param.pword[0] == NET_PROPAGATE) &&
1122 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1123 interp->RInstances[on] = m.param.pword[7];
1126 read(net_sock, &m, sizeof(MESSAGE));
1129 Net_Notify->setEnabled(TRUE);
1131 /*bzero(&m, sizeof(MESSAGE));*/
1132 m.msg_type = MSG_VLP;
1133 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1134 m.param.pword[1] = interp->RInstances[on];
1135 write(interp->sock, &m, sizeof(MESSAGE));
1136 } else { /* There is no such a node! */
1137 sprintf(s, "Warning: Node number %d not found!", on);
1139 WriteMessage("Allocating O-process on the local node");
1140 bzero(&m, sizeof(MESSAGE));
1141 m.msg_type = MSG_VLP;
1142 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1143 m.param.pword[1] = interp->ID;
1144 write(interp->sock, &m, sizeof(MESSAGE));
1149 * Closes all remote instances
1151 void QKernel::CloseInstances(InterpEntry *e)
1157 WriteMessage("Closing remote instances");
1159 for(i=0; i < MAXINSTANCES; i++)
1160 if (e->RInstances[i]>=0) {
1161 msg.msg_type = MSG_NET;
1162 msg.param.pword[0] = NET_PROPAGATE;
1163 msg.param.pword[1] = MSG_VLP;
1164 msg.param.pword[2] = NodeNumber;
1165 msg.param.pword[4] = i;
1166 msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1167 msg.param.pword[7] = e->RInstances[i];
1168 write(net_sock, &msg, sizeof(MESSAGE));
1173 * Displays information about virtual machine
1175 void QKernel::on_actionInfo_triggered()
1179 WriteMessage(CharLine);
1180 WriteMessage("### Virtual Machine Information ###");
1181 m.msg_type = MSG_NET;
1182 m.param.pword[0] = NET_GET_INFO;
1183 write(net_sock, &m, sizeof(MESSAGE));
1184 wait_for_info = TRUE;
1188 * Program main function
1189 * All program arguments but the first one (argv[0]: program name) are saved and
1190 * passed to all dependent programs on their invocation.
1191 * @param argc Number of program arguments
1192 * @param argv Program arguments
1194 int main(int argc, char **argv)
1198 QApplication * app = new QApplication(argc, argv);
1199 QKernel kernel(argc, argv);
1201 kernel.InitMessage();