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 ************************************************************/
34 //#include <qwindow.h>
62 #include <qwindowsstyle.h>
72 #include <netinet/in.h>
74 #include <libconfig.h>
79 #define REMOTE_PATH "REMOTE"
81 #define MAXINSTANCES 256
89 char CharLine[25] = "________________________";
97 /** Interpreter identifier */
99 /** Defines if interpreter is remote or not */
107 QSocketNotifier *notify;
108 /* IDs of my remote INT modules */
109 int RInstances[MAXINSTANCES];
110 /* Parent interpreter info */
121 ConnectEntry(char *s) {
131 class QKernel : public QFrame {
134 QMultiLineEdit *desktop;
145 virtual void resizeEvent(QResizeEvent *ev);
147 void WriteMessage(char* msg);
159 void UnlockConsole();
160 void MessageToNode();
163 void IntMessage(int);
164 void KillInterpreter();
171 virtual void closeEvent (QCloseEvent * e);
174 QList<InterpEntry> Interpreters;
175 QList<ConnectEntry> ConnectList;
176 QListBox *connections;
179 * number of working interpreters
184 * number of connected VLPs
186 int ActiveConnections;
204 QSocketNotifier *Net_Notify;
208 void LoadConfig(char *);
209 void RunGraphModule(char*);
211 InterpEntry *findINTbySocket(int);
212 InterpEntry *findINTbyID(int);
213 InterpEntry *RunIntModule(char *ss, int r);
214 void RemoteInstance(InterpEntry*, int);
215 void CloseInstances(InterpEntry*);
219 * Event invoked on program close.
220 * @copydoc QWidget::closeEvent(QCloseEvent*)
222 void QKernel::closeEvent(QCloseEvent * e)
228 * Kernel program constructor.
229 * Prepares everything to work.
233 QFont f("Helvetica", 10, QFont::Bold);
234 QFont f1("Helvetica", 10, QFont::Normal);
235 QFont f2("Times Roman", 10, QFont::Normal);
240 sprintf(ss, "mkdir %s", REMOTE_PATH);
244 info_messages = TRUE;
245 wait_for_info = FALSE;
247 setCaption("Virtual LOGLAN Processor");
248 setBackgroundColor(white);
250 bar = new QMenuBar(this);
252 p = new QPopupMenu();
254 p->insertItem("Execute", this, SLOT(Run_Prog()));
255 p->insertItem("Kill", this, SLOT(KillInterpreter()));
256 prid = bar->insertItem("&Program", p);
257 p1 = new QPopupMenu();
258 p1->insertItem("Message", this, SLOT(MessageToNode()));
259 p1->insertSeparator();
260 p1->insertItem("Connect", this, SLOT(Connect()));
261 p1->insertItem("Disconnect", this, SLOT(Disconnect()));
262 p1->insertItem("Info", this, SLOT(Info()));
264 mid = bar->insertItem("&Machine", p1);
266 p2 = new QPopupMenu();
267 cwid = p2->insertItem("Editor", this, SLOT(Edit()));
268 hid = p2->insertItem("Help", this, SLOT(Help()));
269 p2->insertSeparator();
270 optid = p2->insertItem("Options", this, SLOT(SetOptions()));
271 msgid = p2->insertItem("Info messages", this, SLOT(SetMessages()));
272 p2->setItemChecked(msgid, TRUE);
273 p2->insertSeparator();
274 lockid = p2->insertItem("Lock console", this, SLOT(LockConsole()));
275 unlockid = p2->insertItem("Unlock console", this,
276 SLOT(UnlockConsole()));
277 p2->setItemEnabled(unlockid, FALSE);
280 toolsid = bar->insertItem("&Tools", p2);
282 qid = bar->insertItem("&Quit", this, SLOT(QuitProc()));
285 desktop = new QMultiLineEdit(this, "desktop");
286 desktop->setAutoUpdate(TRUE);
287 desktop->setReadOnly(TRUE);
288 desktop->setFont(f1);
293 ActiveConnections = 0;
294 strcpy(LockPasswd, "");
295 LoadConfig("vlp.cfg");
298 Net_Notify = new QSocketNotifier(net_sock, QSocketNotifier::Read, this);
299 connect(Net_Notify, SIGNAL(activated(int)), this, SLOT(NetMessage()));
303 * Event invoked on resizing kernel application window.
304 * @copydoc QWidget::resizeEvent(QResizeEvent*)
306 void QKernel::resizeEvent(QResizeEvent *ev)
308 QFrame::resizeEvent(ev);
310 desktop->setGeometry(0, bar->height(), width(),
311 height() - bar->height());
315 * Displays window with information about not implemented functionality.
317 void QKernel::n_impl()
319 QMessageBox::information(this, "Function info", "This function is not "
320 "implemented yet...", "Ok");
324 * Loads configuration from the given file.
325 * @param fname Filename of the configuration file.
327 void QKernel::LoadConfig(char * fname)
330 config_setting_t *setting;
333 /* Hack for checking if file exists without using external libs.*/
334 FILE * file = fopen(fname, "rt");
336 fprintf(stderr, "Error: Cannot load configuration file %s!\n",
340 /* File exists, so file has been locked. Release it. */
344 /* Read the file. If there is an error, report it and exit. */
345 if (!config_read(&cfg, file)) {
346 fprintf(stderr, "%s! In file %s, line %d\n",
347 config_error_text(&cfg),
348 config_error_file(&cfg),
349 config_error_line(&cfg));
350 config_destroy(&cfg);
352 exit(3);/* from original code. */
355 setting = config_lookup(&cfg, "node_number");
357 NodeNumber = config_setting_get_int(setting);
359 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
360 "Warning", fname, "node_number");
361 config_destroy(&cfg);
366 setting = config_lookup(&cfg, "type");
368 /* same as strcmp(..) == 0 */
369 if (!strcmp(config_setting_get_string(setting), "explicit")) {
375 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
376 "Warning", fname, "type");
379 setting = config_lookup(&cfg, "host");
381 switch(config_setting_type(setting)) {
382 /* TODO: Deprecated. Made for back compatibility. */
383 case CONFIG_TYPE_STRING:
384 ConnectList.append(new ConnectEntry((char*)
385 config_setting_get_string(setting)));
387 case CONFIG_TYPE_ARRAY: {
388 int size = config_setting_length(setting);
389 for (int i = 0; i < size; i++) {
390 ConnectList.append(new ConnectEntry((char*)
391 config_setting_get_string_elem(setting,
397 fprintf(stderr, "%s! In file %s, bad entry type for %s."
398 " Will not be read.\n",
399 "Error", fname, "host");
402 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
403 "Warning", fname, "host");
406 setting = config_lookup(&cfg, "progdir");
408 strncpy(progdir, config_setting_get_string(setting), 256);
410 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
411 "Warning", fname, "progdir");
414 setting = config_lookup(&cfg, "homedir");
416 strncpy(HomeDir, config_setting_get_string(setting), 255);
418 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
419 "Warning", fname, "homedir");
422 config_destroy(&cfg);
428 * Additional window id displayed to set which code to execute.
430 void QKernel::Run_Prog()
433 QString s(QFileDialog::getOpenFileName(progdir, "*.log", this));
441 RunIntModule((char*)s.ascii(), 0);
446 * Invokes editor program
451 sprintf(cmd, "%s/modules/logedit %s %s %s %s %s %s &", HomeDir, HomeDir,
452 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
457 * Invokes help program
462 sprintf(cmd, "%s/modules/loghelp %s/doc %s %s %s %s %s &", HomeDir,
463 HomeDir, myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
468 * Invokes graphics module
470 void QKernel::RunGraphModule(char *sk)
474 sprintf(cmd, "%s/modules/loggraph %s %s %s %s %s %s", HomeDir, sk,
475 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
478 if (system(cmd) != 0)
479 WriteMessage("Cannot connect GRAPH resources");
485 void QKernel::RunNetModule()
487 struct sockaddr_un svr;
491 sprintf(cmd, "%s/modules/lognet %s %s %s %s %s %s", HomeDir, NPATH,
492 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
495 /* -------- socket for NET module -------- */
497 sock = socket(AF_UNIX, SOCK_STREAM, 0);
498 bzero(&svr, sizeof(svr));
499 svr.sun_family = AF_UNIX;
500 strcpy(svr.sun_path, NPATH);
501 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
502 bind(sock, (struct sockaddr*)&svr, len);
505 if (system(cmd) == 0) {
506 net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
509 WriteMessage("NETWORK successfully connected");
510 fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock,
513 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY,
514 (char*)&on, sizeof(on));
516 WriteMessage("Cannot connect NETWORK resources");
517 WriteMessage("Exiting...");
523 WriteMessage("Cannot connect NETWORK resources");
524 WriteMessage("Exiting...");
531 * Connects to the specified address
532 * Additional window is displayed to connect to the specified address
534 void QKernel::Connect()
536 QDialog d(this, "", TRUE);
537 QLabel lab(&d, "IP Address:");
538 QLineEdit ed(&d, "");
539 QPushButton ob(&d, "");
540 QPushButton cb(&d, "");
543 d.setFont(QFont("Helvetica", 12, QFont::Bold));
544 ob.setGeometry(30, 60, 80, 30);
547 lab.setGeometry(10, 10, 60, 30);
548 lab.setText("Address");
549 ed.setGeometry(70, 10, 140, 30);
550 cb.setGeometry(130, 60, 80, 30);
551 cb.setText("Cancel");
554 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
555 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
557 m.msg_type = MSG_NET;
558 m.param.pword[0] = NET_CONNECT_TO;
559 strcpy(m.param.pstr, ed.text());
560 write(net_sock, &m, sizeof(MESSAGE));
565 * Disconnects from virtual machine
567 void QKernel::Disconnect()
572 WriteMessage("Disconnecting from virtual machine");
574 msg.msg_type = MSG_NET;
575 msg.param.pword[0] = NET_DISCONNECT;
576 write(net_sock, &msg, sizeof(MESSAGE));
580 * Quits process. Closes VLP. Shows additional window to confirm exit.
582 void QKernel::QuitProc()
586 if (QMessageBox::question(this, "Close VLP", "Terminate VLP ?",
587 QMessageBox::Yes, QMessageBox::No, 0) == QMessageBox::No) {
593 msg.msg_type = MSG_NET;
594 msg.param.pword[0] = NET_DISCONNECT;
595 write(net_sock, &msg, sizeof(MESSAGE));*/
598 msg.msg_type = MSG_NET;
599 msg.param.pword[0] = NET_EXIT;
600 write(net_sock, &msg, sizeof(MESSAGE));
601 /* ::close(net_sock);*/
607 * Adds IP address to the configuration.
608 * Additional window is displayed to add address to the list
610 void QKernel::AddAddress()
612 QDialog d(this, "", TRUE);
613 QLabel lab(&d, "IP Address:");
614 QLineEdit ed(&d, "");
615 QPushButton ob(&d, "");
616 QPushButton cb(&d, "");
619 ob.setGeometry(30, 60, 80, 30);
622 lab.setGeometry(10, 10, 60, 30);
623 lab.setText("Address");
624 ed.setGeometry(70, 10, 140, 30);
625 cb.setGeometry(130, 60, 80, 30);
626 cb.setText("Cancel");
628 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
629 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
631 if (strcmp(ed.text(), "") != 0) {
632 connections->insertItem(ed.text());
638 * Deletes current address from available connections.
640 void QKernel::DelAddress()
643 if (connections->currentItem() != -1)
644 connections->removeItem(connections->currentItem());
649 * Sends message to node.
650 * Additional window is displayed to set Node Number of node where send message,
651 * and textfield to enter message.
653 void QKernel::MessageToNode()
659 dlg = new QDialog(this, "Message", TRUE);
661 nodenr = new QLineEdit(dlg, "number");
662 nodenr->setGeometry(90, 10, 50, 30);
666 tmpQLabel = new QLabel(dlg, "Label_1");
667 tmpQLabel->setGeometry(10, 10, 77, 30);
668 tmpQLabel->setText("Node number:");
670 tmpQLabel = new QLabel(dlg, "Label_2");
671 tmpQLabel->setGeometry(10, 50, 70, 30);
672 tmpQLabel->setText("Message:");
675 msg = new QLineEdit(dlg, "LineEdit_1");
676 msg->setGeometry(80, 60, 330, 30);
680 ob = new QPushButton(dlg, "PushButton_1");
681 ob->setGeometry(230, 10, 80, 30);
683 ob->setDefault(TRUE);
686 cb = new QPushButton(dlg, "PushButton_2");
687 cb->setGeometry(330, 10, 80, 30);
688 cb->setText("Cancel");
689 dlg->resize(430, 110);
690 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
691 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
692 dlg->setCaption("Send message to node");
695 m.msg_type = MSG_NET;
696 m.param.pword[0] = NET_PROPAGATE;
697 m.param.pword[1] = MSG_VLP;
698 m.param.pword[2] = NodeNumber;
699 m.param.pword[4] = atoi(nodenr->text());
700 m.param.pword[6] = VLP_WRITE;
701 strcpy(m.param.pstr, msg->text());
702 write(net_sock, &m, sizeof(MESSAGE));
708 * Additional window is displayed to get ID of interpreter which should be
711 void QKernel::KillInterpreter()
718 dlg = new QDialog(this, "Message", TRUE);
720 nodenr = new QLineEdit(dlg, "number");
721 nodenr->setGeometry(90, 10, 50, 30);
725 tmpQLabel = new QLabel(dlg, "Label_1");
726 tmpQLabel->setGeometry(10, 10, 77, 30);
727 tmpQLabel->setText("Interp. ID:");
728 QPushButton* ob, *cb;
729 ob = new QPushButton(dlg, "PushButton_1");
730 ob->setGeometry( 160, 10, 80, 30);
732 ob->setDefault(TRUE);
733 cb = new QPushButton(dlg, "PushButton_2");
734 cb->setGeometry(260, 10, 80, 30);
735 cb->setText("Cancel");
736 dlg->resize(360, 50);
737 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
738 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
739 dlg->setCaption("Kill interpreter");
741 m.msg_type = MSG_INT;
742 m.param.pword[0] = INT_KILL;
743 pom = findINTbyID(atoi(nodenr->text()));
746 write(pom->sock, &m, sizeof(MESSAGE));
748 WriteMessage("This is a remote instance of "
752 WriteMessage("Interpreter not found");
758 * Sends message to the net module.
760 void QKernel::NetMessage()
763 /* TODO: It has to be rewritten */
769 cnt = read(net_sock, &msg, sizeof(MESSAGE));
770 if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
771 switch(msg.param.pword[0]) {
773 WriteMessage(msg.param.pstr);
776 switch(msg.param.pword[1]) {
778 /* pom = find_link_by_ID(msg.param.pword[5]);
779 msg.msg_type = MSG_NET;
780 msg.param.pword[0] = NET_PROPAGATE;
781 send_int(pom, &msg);*/
784 switch(msg.param.pword[6]) {
786 QApplication::beep();
787 WriteMessage(CharLine);
789 "### Incoming Messsage ###");
790 sprintf(ss, "Mesg from Node %d: %s",
794 WriteMessage(CharLine);
796 case VLP_REMOTE_INSTANCE:
797 sprintf(ss, "%s/%s", REMOTE_PATH,
801 WriteMessage("Running program:");
804 pom = RunIntModule(ss, 1);
806 pom->p_ctx.node = msg.param.pword[2];
807 pom->p_ctx.program_id =
809 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
812 case VLP_CLOSE_INSTANCE:
813 msg.msg_type = MSG_INT;
814 msg.param.pword[0] = INT_CLOSE_INSTANCE;
815 pom = findINTbyID(msg.param.pword[7]);
817 write(pom->sock, &msg,
820 m1.msg_type = MSG_VLP;
821 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
822 m1.param.pword[1] = pom->ID;
826 WriteMessage("Instance not found");
832 case NET_CONNECTIONS:
833 ActiveConnections = msg.param.pword[1];
834 WriteMessage(msg.param.pstr);
839 /* TODO: It has to be rewritten */
841 QString poms, poms1, poms2;
842 poms.sprintf("%s", msg.param.pstr);
843 while (poms.length() > 0) {
844 cnt = poms.find(';');
846 poms1 = poms.left(cnt);
847 poms = poms.right(poms.length() - cnt - 1);
848 cnt = poms1.find('=');
850 poms2 = poms1.left(cnt);
854 sprintf(ss, "Node: %s Addr: %s", poms2.data(), poms1.data());
862 wait_for_info = FALSE;
863 WriteMessage(CharLine);
870 * Sends message to the interpreter program.
871 * @param sock Interpreter socket to whom the message will be send.
873 void QKernel::IntMessage(int sock)
879 cnt = read(sock, &msg, sizeof(MESSAGE));
880 e = findINTbySocket(sock);
881 if ((cnt > 0) && (e != NULL)) {
882 switch (msg.msg_type) {
884 if (msg.param.pword[0] == GRAPH_ALLOCATE) {
885 RunGraphModule(msg.param.pstr);
889 write(net_sock, &msg, sizeof(MESSAGE));
892 switch(msg.param.pword[0]) {
893 case VLP_REMOTE_INSTANCE_PLEASE:
894 RemoteInstance(e, msg.param.pword[2]);
899 switch(msg.param.pword[0]) {
904 m.msg_type = MSG_VLP;
905 m.param.pword[0] = VLP_INTERPRETER_DOWN;
906 m.param.pword[1] = e->ID;
907 write(net_sock, &m, sizeof(MESSAGE));
912 Interpreters.remove(e);
916 sprintf(ss, "%s : End of program "
917 "execution", msg.param.pstr);
922 msg.msg_type = MSG_INT;
923 msg.param.pword[0] = INT_CTX;
924 msg.param.pword[1] = NodeNumber;
925 msg.param.pword[2] = e->ID;
927 msg.param.pword[3] = e->p_ctx.node;
931 write(sock, &msg, sizeof(MESSAGE));
940 * Writes message to kernel logger.
941 * @parame msg String with message to log
943 void QKernel::WriteMessage(char *msg)
948 desktop->getCursorPosition(&x, &y);
953 desktop->setReadOnly(FALSE);
954 desktop->append(msg);
955 desktop->setReadOnly(TRUE);
956 desktop->setCursorPosition(desktop->numLines(), 1);
959 if (desktop->numLines() > 100) {
965 * Adds checkbox to menu item. It it is checked additional info messages are
968 void QKernel::SetMessages()
971 if (p2->isItemChecked(msgid)) {
972 p2->setItemChecked(msgid, FALSE);
975 p2->setItemChecked(msgid, TRUE);
979 /* bar->repaint(); */
983 * Allows to set options in GUI window.
984 * Additional window is displayed to set kernel options which are saved in
985 * vlp.cfg file in kernel executable directory.
987 void QKernel::SetOptions()
989 QDialog dlg(this, "Options", TRUE);
994 progs = new QLineEdit(&dlg, "progs");
995 progs->setGeometry(150, 20, 180, 30);
996 progs->setText(progdir);
999 tmpQLabel = new QLabel(&dlg, "Label_1");
1000 tmpQLabel->setGeometry(30, 20, 120, 30);
1001 tmpQLabel->setText("Programs directory");
1004 tmpQFrame = new QFrame(&dlg, "Frame_2");
1005 tmpQFrame->setGeometry(10, 60, 380, 30);
1006 tmpQFrame->setFrameStyle(52);
1008 tmpQLabel = new QLabel(&dlg, "Label_2");
1009 tmpQLabel->setGeometry(10, 80, 340, 30);
1010 tmpQLabel->setText("Virtual Processor properties (activated after "
1011 "restarting VLP):");
1015 nn = new QLineEdit(&dlg, "LineEdit_2");
1016 nn->setGeometry(110, 110, 40, 30);
1017 sprintf(nns, "%d", NodeNumber);
1020 tmpQLabel = new QLabel(&dlg, "Label_3");
1021 tmpQLabel->setGeometry(20, 110, 90, 30);
1022 tmpQLabel->setText("Node number:");
1024 QRadioButton *exp, *reg;
1025 exp = new QRadioButton(&dlg, "RadioButton_3");
1026 exp->setGeometry(30, 170, 100, 30);
1027 exp->setText("Explicit");
1028 exp->setChecked(TRUE);
1030 reg = new QRadioButton(&dlg, "RadioButton_4");
1031 reg->setGeometry(30, 200, 100, 30);
1032 reg->setText("Registration");
1033 reg->setEnabled(FALSE);
1035 connections = new QListBox(&dlg, "ListBox_1");
1036 connections->setGeometry(170, 140, 130, 100);
1037 e = ConnectList.first();
1039 connections->insertItem(e->addr);
1040 e = ConnectList.next();
1043 tmpQLabel = new QLabel(&dlg, "Label_5");
1044 tmpQLabel->setGeometry(170, 110, 100, 30);
1045 tmpQLabel->setText("Connection list:");
1047 QPushButton *addbtn;
1048 QPushButton *delbtn;
1050 QPushButton *cancelbtn;
1051 addbtn = new QPushButton(&dlg, "PushButton_1");
1052 addbtn->setGeometry(310, 150, 60, 30);
1053 addbtn->setText("Add");
1054 delbtn = new QPushButton(&dlg, "PushButton_2");
1055 delbtn->setGeometry(310, 200, 60, 30);
1056 delbtn->setText("Del");
1057 connect(addbtn, SIGNAL(clicked()), this, SLOT(AddAddress()));
1058 connect(delbtn, SIGNAL(clicked()), this, SLOT(DelAddress()));
1059 okbtn = new QPushButton(&dlg, "PushButton_3");
1060 okbtn->setGeometry(80, 260, 100, 30);
1061 okbtn->setText("Ok");
1062 okbtn->setDefault(TRUE);
1063 cancelbtn = new QPushButton(&dlg, "PushButton_4");
1064 cancelbtn->setGeometry(210, 260, 100, 30);
1065 cancelbtn->setText("Cancel");
1066 connect(okbtn, SIGNAL(clicked()), &dlg, SLOT(accept()));
1067 connect(cancelbtn, SIGNAL(clicked()), &dlg, SLOT(reject()));
1068 QButtonGroup* group;
1069 group = new QButtonGroup(&dlg, "ButtonGroup_1");
1070 group->setGeometry(20, 150, 120, 90);
1071 group->setTitle("Connection type");
1072 group->setAlignment(1);
1074 group->insert(exp, 1);
1075 group->insert(reg, 2);
1077 dlg.resize(400, 310);
1080 config_setting_t *root;
1081 config_setting_t *setting;
1084 root = config_root_setting(&cfg);
1086 setting = config_setting_add(root, "progdir",
1087 CONFIG_TYPE_STRING);
1088 config_setting_set_string(setting, progs->text().ascii());
1089 strcpy(progdir, progs->text());
1091 setting = config_setting_add(root, "node_number",
1093 config_setting_set_int(setting, atoi(nn->text()));
1095 setting = config_setting_add(root, "homedir",
1096 CONFIG_TYPE_STRING);
1097 config_setting_set_string(setting, HomeDir);
1099 setting = config_setting_add(root, "type",
1100 CONFIG_TYPE_STRING);
1101 if (exp->isChecked()) {
1102 config_setting_set_string(setting, "explicit");
1104 config_setting_t *hosts = NULL;
1105 hosts = config_setting_add(root, "host",
1107 for(i = 0; i < connections->count(); i++) {
1108 setting = config_setting_add(hosts, NULL,
1109 CONFIG_TYPE_STRING);
1110 config_setting_set_string(setting,
1111 connections->text(i).ascii());
1114 config_setting_set_string(setting, "register");
1117 if (!config_write_file(&cfg, "vlp.cfg")) {
1118 fprintf(stderr, "Error while writing to file: %s.\n",
1121 config_destroy(&cfg);
1126 * Locks kernel program.
1127 * Additional window is displayed to enter password and retype it. If both are
1128 * same kernel window is locked.
1130 void QKernel::LockConsole()
1132 QDialog d(this, "Enter password", TRUE);
1133 QLabel lab(&d, "Password");
1134 QLineEdit ed(&d, "");
1135 QPushButton ob(&d, "");
1136 QPushButton cb(&d, "");
1138 d.setCaption("Lock console");
1139 ob.setGeometry(30, 60, 80, 30);
1141 ob.setDefault(TRUE);
1142 lab.setGeometry(10, 10, 60, 30);
1143 lab.setText("Password:");
1144 ed.setGeometry(70, 10, 140, 30);
1145 ed.setEchoMode(QLineEdit::Password);
1146 cb.setGeometry(130, 60, 80, 30);
1147 cb.setText("Cancel");
1149 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
1150 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
1153 if (strcmp(ed.text(), "") != 0) {
1154 strcpy(LockPasswd, ed.text());
1155 lab.setText("Retype:");
1158 if (strcmp(ed.text(), LockPasswd)==0) {
1159 bar->setItemEnabled(qid, FALSE);
1160 bar->setItemEnabled(prid, FALSE);
1161 bar->setItemEnabled(mid, FALSE);
1162 p2->setItemEnabled(unlockid, TRUE);
1163 p2->setItemEnabled(lockid, FALSE);
1164 p2->setItemEnabled(cwid, FALSE);
1165 p2->setItemEnabled(optid, FALSE);
1167 WriteMessage("CONSOLE LOCKED");
1170 QMessageBox msg(this);
1171 msg.setText("Not matching!");
1172 msg.setButtonText(0, "Close");
1176 strcpy(LockPasswd, "");
1183 * Unlocks kernel program.
1184 * Additional window is displayed to enter password. If it is correct, kernel
1185 * window is unlocked
1187 void QKernel::UnlockConsole()
1189 QDialog d(this, "Enter password", TRUE);
1190 QLabel lab(&d, "Password");
1191 QLineEdit ed(&d, "");
1192 QPushButton ob(&d, "");
1193 QPushButton cb(&d, "");
1195 ob.setGeometry(30, 60, 80, 30);
1197 ob.setDefault(TRUE);
1198 lab.setGeometry(10, 10, 60, 30);
1199 lab.setText("Password:");
1200 ed.setGeometry(70, 10, 140, 30);
1201 ed.setEchoMode(QLineEdit::Password);
1202 cb.setGeometry(130, 60, 80, 30);
1203 cb.setText("Cancel");
1205 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
1206 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
1209 if (strcmp(ed.text(), LockPasswd) == 0) {
1210 bar->setItemEnabled(qid, TRUE);
1211 bar->setItemEnabled(prid, TRUE);
1212 bar->setItemEnabled(mid, TRUE);
1213 p2->setItemEnabled(unlockid, FALSE);
1214 p2->setItemEnabled(lockid, TRUE);
1215 p2->setItemEnabled(cwid, TRUE);
1216 p2->setItemEnabled(optid, TRUE);
1218 WriteMessage("CONSOLE UNLOCKED");
1221 QMessageBox msg(this);
1222 msg.setText("Wrong password!");
1223 msg.setButtonText(0, "Close");
1230 * Writes init message in kernel
1232 void QKernel::InitMessage()
1234 WriteMessage("\n Virtual LOGLAN Processor - ver 1.9: READY \n");
1238 * Finds Interpreter by its socket
1239 * @param _id ID of the socket
1240 * @return returns pointer to the found interpreter slot
1242 InterpEntry *QKernel::findINTbySocket(int _id)
1245 pom = Interpreters.first();
1247 while (pom != NULL) {
1248 if (pom->sock == _id)
1251 pom = Interpreters.next();
1257 * Finds Interpreter by its ID.
1258 * @param _id ID of the interpreter
1259 * @return returns pointer to the found interpreter slot
1261 InterpEntry *QKernel::findINTbyID(int _id)
1264 pom = Interpreters.first();
1265 while (pom != NULL) {
1268 pom = Interpreters.next();
1275 * Connects interpreter
1276 * @param ss full filepath with filename but without extension of the loglan
1278 * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
1280 * @return Returns pointer to newly created interpreter slot, or NULL on error.
1282 InterpEntry *QKernel::RunIntModule(char *ss, int r)
1284 char a[256], b[255];
1285 struct sockaddr_un svr;
1286 int len, sock, i, on;
1291 InterpEntry *newINT = NULL;
1297 WriteMessage("File not found: no .ccd file");
1306 WriteMessage("File not found: no .pcd file");
1311 newINT = new InterpEntry;
1312 for(i = 0; i < MAXINSTANCES; i++)
1313 newINT->RInstances[i] =- 1;
1315 strcpy(b, rindex(ss, '/'));
1316 for(i = 0; i < strlen(b); i++)
1318 if (info_messages) {
1319 sprintf(a, "%s : Start execution", b);
1325 newINT->ID = newint;
1326 strcpy(newINT->shortname, b);
1327 strcpy(newINT->fullname, ss);
1329 sprintf(a, "%s%d", IPATH, newint);
1330 sprintf(cmd, "%s/modules/logint %s %s", HomeDir, a, ss);
1333 sprintf(b, " %s %s %s %s %s", myargs[0], myargs[1], myargs[2],
1334 myargs[3], myargs[4]);
1338 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1340 bzero(&svr, sizeof(svr));
1341 svr.sun_family = AF_UNIX;
1342 strcpy(svr.sun_path, a);
1343 len = strlen(svr.sun_path)+sizeof(svr.sun_family);
1344 bind(sock, (struct sockaddr*)&svr, len);
1347 newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
1350 if (newINT->sock > 0) {
1351 fcntl(newINT->sock, F_SETFL,
1352 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
1354 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
1361 bzero(&msg, sizeof(MESSAGE));
1362 msg.msg_type = MSG_VLP;
1363 msg.param.pword[0] = VLP_REGINT;
1364 msg.param.pword[1] = newINT->ID;
1365 sprintf(msg.param.pstr, "logi%d.net", newint);
1366 write(net_sock, &msg, sizeof(MESSAGE));
1368 Interpreters.append(newINT);
1369 newINT->notify = new QSocketNotifier(newINT->sock,
1370 QSocketNotifier::Read);
1371 connect(newINT->notify, SIGNAL(activated(int)), this,
1372 SLOT(IntMessage(int)));
1374 WriteMessage("INTERPRETER successfully connected");
1376 WriteMessage("Cannot connect interpreter");
1383 * Allocates remote instance of interpreter
1384 * @param interp Interpreter slot
1385 * @param on Node Number
1387 void QKernel::RemoteInstance(InterpEntry *interp, int on)
1392 m.msg_type = MSG_NET;
1393 m.param.pword[0] = NET_NODE_EXIST;
1394 m.param.pword[1] = on;
1395 m.param.pword[2] = interp->ID;
1396 write(net_sock, &m, sizeof(MESSAGE));
1397 bzero(&m, sizeof(MESSAGE));
1398 while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
1399 read(net_sock, &m, sizeof(MESSAGE));
1401 /* means node exists */
1402 if (m.param.pword[1] == 1) {
1403 m.msg_type = MSG_NET;
1404 m.param.pword[0] = NET_TRANSMIT_CODE;
1405 m.param.pword[1] = interp->ID;
1406 m.param.pword[2] = on;
1407 strcpy(m.param.pstr, interp->fullname);
1408 write(net_sock, &m, sizeof(MESSAGE));
1410 Net_Notify->setEnabled(FALSE);
1411 while ((m.msg_type != MSG_NET) ||
1412 (m.param.pword[0] != NET_TRANSMITTED))
1413 read(net_sock, &m, sizeof(MESSAGE));
1415 m.msg_type = MSG_NET;
1416 m.param.pword[0] = NET_PROPAGATE;
1417 m.param.pword[1] = MSG_VLP;
1418 m.param.pword[2] = NodeNumber;
1419 m.param.pword[3] = 0;
1420 m.param.pword[4] = on;
1421 m.param.pword[5] = 0;
1422 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1423 m.param.pword[7] = interp->ID;
1424 strcpy(m.param.pstr, interp->shortname);
1425 write(net_sock, &m, sizeof(MESSAGE));
1427 read(net_sock, &m, sizeof(MESSAGE));
1429 if ((m.param.pword[0] == NET_PROPAGATE) &&
1430 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1431 interp->RInstances[on] = m.param.pword[7];
1434 read(net_sock, &m, sizeof(MESSAGE));
1437 Net_Notify->setEnabled(TRUE);
1439 /*bzero(&m, sizeof(MESSAGE));*/
1440 m.msg_type = MSG_VLP;
1441 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1442 m.param.pword[1] = interp->RInstances[on];
1443 write(interp->sock, &m, sizeof(MESSAGE));
1444 } else { /* There is no such a node! */
1445 sprintf(s, "Warning: Node number %d not found!", on);
1447 WriteMessage("Allocating O-process on the local node");
1448 bzero(&m, sizeof(MESSAGE));
1449 m.msg_type = MSG_VLP;
1450 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1451 m.param.pword[1] = interp->ID;
1452 write(interp->sock, &m, sizeof(MESSAGE));
1457 * Closes all remote instances
1459 void QKernel::CloseInstances(InterpEntry *e)
1465 WriteMessage("Closing remote instances");
1467 for(i=0; i < MAXINSTANCES; i++)
1468 if (e->RInstances[i]>=0) {
1469 msg.msg_type = MSG_NET;
1470 msg.param.pword[0] = NET_PROPAGATE;
1471 msg.param.pword[1] = MSG_VLP;
1472 msg.param.pword[2] = NodeNumber;
1473 msg.param.pword[4] = i;
1474 msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1475 msg.param.pword[7] = e->RInstances[i];
1476 write(net_sock, &msg, sizeof(MESSAGE));
1481 * Displays information about virtual machine
1483 void QKernel::Info()
1487 WriteMessage(CharLine);
1488 WriteMessage("### Virtual Machine Information ###");
1489 m.msg_type = MSG_NET;
1490 m.param.pword[0] = NET_GET_INFO;
1491 write(net_sock, &m, sizeof(MESSAGE));
1492 wait_for_info = TRUE;
1495 #include "kernel.moc"
1498 * Program main function
1499 * All program arguments but the first one (argv[0]: program name) are saved and
1500 * passed to all dependent programs on their invocation.
1501 * @param argc Number of program arguments
1502 * @param argv Program arguments
1504 int main(int argc, char **argv)
1507 for(i = 0; i < 5; i++) {
1508 strcpy(myargs[i], "");
1510 for(i = 1; i < argc; i++) {
1511 strcpy(myargs[i - 1], argv[i]);
1514 app = new QApplication(argc, argv);
1515 app->setStyle(new QWindowsStyle());
1517 app->setMainWidget(&kernel);
1519 kernel.InitMessage();