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 ************************************************************/
33 #include <QtGui/QApplication>
34 #include <QtGui/QMainWindow>
35 #include <QtGui/QTextEdit>
36 #include <QtGui/QMenuBar>
37 #include <QtGui/QMessageBox>
38 #include <QtGui/QFileDialog>
39 #include <QtGui/QDialog>
41 #include <QtGui/QLabel>
42 #include <QtGui/QLineEdit>
43 #include <QtGui/QPushButton>
44 #include <QtGui/QRadioButton>
45 #include <QtGui/QGroupBox>
46 #include <QtGui/QVBoxLayout>
47 #include <QtCore/QList>
48 #include <QtGui/QListWidget>
51 #include <QtCore/QSocketNotifier>
52 #include <QtGui/QCloseEvent>
63 #include <netinet/in.h>
65 #include <libconfig.h>
67 /* File resides in top directory (where are Makefiles)*/
68 #include "../../config.h"
73 #define REMOTE_PATH "REMOTE"
75 #define MAXINSTANCES 256
83 char CharLine[25] = "________________________";
91 /** Interpreter identifier */
93 /** Defines if interpreter is remote or not */
101 QSocketNotifier *notify;
102 /* IDs of my remote INT modules */
103 int RInstances[MAXINSTANCES];
104 /* Parent interpreter info */
115 ConnectEntry(char *s) {
125 class QKernel : public QMainWindow {
139 virtual void resizeEvent(QResizeEvent *ev);
141 void WriteMessage(char* msg);
153 void UnlockConsole();
154 void MessageToNode();
157 void IntMessage(int);
158 void KillInterpreter();
165 virtual void closeEvent (QCloseEvent * e);
168 QList<InterpEntry*> Interpreters;
169 QList<ConnectEntry*> ConnectList;
170 QListWidget *connections;
173 * number of working interpreters
174 * @attention Currently not in use
179 * number of connected VLPs
181 int ActiveConnections;
191 QAction * programExecuteAction;
192 QAction * programKillAction;
193 QAction * machineMessageAction;
194 QAction * machineConnectAction;
195 QAction * machineDisconnectAction;
196 QAction * machineInfoAction;
202 QSocketNotifier *Net_Notify;
206 void LoadConfig(char *);
207 void RunGraphModule(char*);
209 InterpEntry *findINTbySocket(int);
210 InterpEntry *findINTbyID(int);
211 InterpEntry *RunIntModule(char *ss, int r);
212 void RemoteInstance(InterpEntry*, int);
213 void CloseInstances(InterpEntry*);
217 * Event invoked on program close.
218 * Closes application. Displays additional window to confirm exit.
220 void QKernel::closeEvent(QCloseEvent * e)
230 * Kernel program constructor.
231 * Prepares everything to work.
239 sprintf(ss, "mkdir %s", REMOTE_PATH);
243 info_messages = TRUE;
244 wait_for_info = FALSE;
246 setWindowTitle(PACKAGE_NAME);
248 QMenu * programMenu = NULL;
249 programMenu = menuBar()->addMenu("&Program");
250 programExecuteAction = programMenu->addAction("Execute", this, SLOT(Run_Prog()));
251 programKillAction = programMenu->addAction("Kill", this, SLOT(KillInterpreter()));
253 machineMenu = menuBar()->addMenu("&Machine");
254 machineMessageAction = machineMenu->addAction("Message", this, SLOT(MessageToNode()));
255 machineMenu->addSeparator();
256 machineConnectAction = machineMenu->addAction("Connect", this, SLOT(Connect()));
257 machineDisconnectAction = machineMenu->addAction("Disconnect", this, SLOT(Disconnect()));
258 machineInfoAction = machineMenu->addAction("Info", this, SLOT(Info()));
260 toolsMenu = menuBar()->addMenu("&Tools");
261 cwid = toolsMenu->addAction("Editor", this, SLOT(Edit()));
262 hid = toolsMenu->addAction("Help", this, SLOT(Help()));
263 toolsMenu->addSeparator();
264 optid = toolsMenu->addAction("Options", this, SLOT(SetOptions()));
265 msgid = toolsMenu->addAction("Info messages", this, SLOT(SetMessages()));
266 msgid->setCheckable(TRUE);
267 msgid->setChecked(TRUE);
268 toolsMenu->addSeparator();
269 lockid = toolsMenu->addAction("Lock console", this, SLOT(LockConsole()));
270 unlockid = toolsMenu->addAction("Unlock console", this,
271 SLOT(UnlockConsole()));
272 unlockid->setDisabled(TRUE);
275 qid = menuBar()->addAction("&Quit", this, SLOT(QuitProc()));
277 desktop = new QTextEdit(this);
278 desktop->setReadOnly(TRUE);
279 QVBoxLayout * layout = new QVBoxLayout();
280 layout->setContentsMargins (3, 0, 3, 0);
281 layout->addWidget(desktop);
282 QWidget *window = new QWidget();
283 window->setLayout(layout);
284 setCentralWidget(window);
289 ActiveConnections = 0;
290 strcpy(LockPasswd, "");
291 LoadConfig("vlp.cfg");
294 Net_Notify = new QSocketNotifier(net_sock, QSocketNotifier::Read, this);
295 connect(Net_Notify, SIGNAL(activated(int)), this, SLOT(NetMessage()));
299 * Event invoked on resizing kernel application window.
300 * @copydoc QWidget::resizeEvent(QResizeEvent*)
302 void QKernel::resizeEvent(QResizeEvent *ev)
304 // QFrame::resizeEvent(ev);
306 // desktop->setGeometry(0, bar->height(), width(),
307 // height() - bar->height());
311 * Displays window with information about not implemented functionality.
313 void QKernel::n_impl()
315 QMessageBox::information(this, "Function info", "This function is not "
316 "implemented yet...", "Ok");
320 * Loads configuration from the given file.
321 * @param fname Filename of the configuration file.
323 void QKernel::LoadConfig(char * fname)
326 config_setting_t *setting;
329 /* Hack for checking if file exists without using external libs.*/
330 FILE * file = fopen(fname, "rt");
332 fprintf(stderr, "Error: Cannot load configuration file %s!\n",
336 /* File exists, so file has been locked. Release it. */
340 /* Read the file. If there is an error, report it and exit. */
341 if (!config_read(&cfg, file)) {
342 fprintf(stderr, "%s! In file %s, line %d\n",
343 config_error_text(&cfg),
344 config_error_file(&cfg),
345 config_error_line(&cfg));
346 config_destroy(&cfg);
348 exit(3);/* from original code. */
351 setting = config_lookup(&cfg, "node_number");
353 NodeNumber = config_setting_get_int(setting);
355 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
356 "Warning", fname, "node_number");
357 config_destroy(&cfg);
362 setting = config_lookup(&cfg, "type");
364 /* same as strcmp(..) == 0 */
365 if (!strcmp(config_setting_get_string(setting), "explicit")) {
371 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
372 "Warning", fname, "type");
375 setting = config_lookup(&cfg, "host");
377 switch(config_setting_type(setting)) {
378 /* TODO: Deprecated. Made for back compatibility. */
379 case CONFIG_TYPE_STRING:
380 ConnectList.append(new ConnectEntry((char*)
381 config_setting_get_string(setting)));
383 case CONFIG_TYPE_ARRAY: {
384 int size = config_setting_length(setting);
385 for (int i = 0; i < size; i++) {
386 ConnectList.append(new ConnectEntry((char*)
387 config_setting_get_string_elem(setting,
393 fprintf(stderr, "%s! In file %s, bad entry type for %s."
394 " Will not be read.\n",
395 "Error", fname, "host");
398 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
399 "Warning", fname, "host");
402 setting = config_lookup(&cfg, "progdir");
404 strncpy(progdir, config_setting_get_string(setting), 256);
406 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
407 "Warning", fname, "progdir");
410 setting = config_lookup(&cfg, "homedir");
412 strncpy(HomeDir, config_setting_get_string(setting), 255);
414 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
415 "Warning", fname, "homedir");
418 config_destroy(&cfg);
424 * Additional window id displayed to set which code to execute.
426 void QKernel::Run_Prog()
429 QString s = QFileDialog::getOpenFileName(this, "Execute", progdir, "*.log");
432 i = s.indexOf(".log");
437 RunIntModule((char*)s.toAscii().data(), 0);
442 * Invokes editor program
447 sprintf(cmd, "%s/modules/logedit %s %s %s %s %s %s &", HomeDir, HomeDir,
448 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
453 * Invokes help program
458 sprintf(cmd, "%s/modules/loghelp %s/doc %s %s %s %s %s &", HomeDir,
459 HomeDir, myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
464 * Invokes graphics module
466 void QKernel::RunGraphModule(char *sk)
470 sprintf(cmd, "%s/modules/loggraph %s %s %s %s %s %s", HomeDir, sk,
471 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
474 if (system(cmd) != 0)
475 WriteMessage("Cannot connect GRAPH resources");
481 void QKernel::RunNetModule()
483 struct sockaddr_un svr;
487 sprintf(cmd, "%s/modules/lognet %s %s %s %s %s %s", HomeDir, NPATH,
488 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
491 /* -------- socket for NET module -------- */
493 sock = socket(AF_UNIX, SOCK_STREAM, 0);
494 bzero(&svr, sizeof(svr));
495 svr.sun_family = AF_UNIX;
496 strcpy(svr.sun_path, NPATH);
497 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
498 bind(sock, (struct sockaddr*)&svr, len);
501 if (system(cmd) == 0) {
502 net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
505 WriteMessage("NETWORK successfully connected");
506 fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock,
509 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY,
510 (char*)&on, sizeof(on));
512 WriteMessage("Cannot connect NETWORK resources");
513 WriteMessage("Exiting...");
519 WriteMessage("Cannot connect NETWORK resources");
520 WriteMessage("Exiting...");
527 * Connects to the specified address
528 * Additional window is displayed to connect to the specified address
530 void QKernel::Connect()
532 QDialog d(this, Qt::Dialog);
533 QLabel lab("IP Address:", &d);
534 QLineEdit ed("", &d);
535 QPushButton ob("", &d);
536 QPushButton cb("", &d);
539 ob.setGeometry(30, 60, 80, 30);
542 lab.setGeometry(10, 10, 60, 30);
543 lab.setText("Address");
544 ed.setGeometry(70, 10, 140, 30);
545 cb.setGeometry(130, 60, 80, 30);
546 cb.setText("Cancel");
549 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
550 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
552 m.msg_type = MSG_NET;
553 m.param.pword[0] = NET_CONNECT_TO;
554 strcpy(m.param.pstr, ed.text().toAscii().data());
555 write(net_sock, &m, sizeof(MESSAGE));
560 * Disconnects from virtual machine
562 void QKernel::Disconnect()
567 WriteMessage("Disconnecting from virtual machine");
569 msg.msg_type = MSG_NET;
570 msg.param.pword[0] = NET_DISCONNECT;
571 write(net_sock, &msg, sizeof(MESSAGE));
575 * Quits process. Closes VLP. Shows additional window to confirm exit.
577 void QKernel::QuitProc()
581 QMessageBox::StandardButton response;
582 response = QMessageBox::question(this, "Close VLP", "Terminate VLP ?",
583 QMessageBox::Ok | QMessageBox::Cancel);
586 if (response == QMessageBox::Cancel) {
590 msg.msg_type = MSG_NET;
591 msg.param.pword[0] = NET_DISCONNECT;
592 write(net_sock, &msg, sizeof(MESSAGE));*/
595 msg.msg_type = MSG_NET;
596 msg.param.pword[0] = NET_EXIT;
597 write(net_sock, &msg, sizeof(MESSAGE));
598 /* ::close(net_sock);*/
603 * Adds IP address to the configuration.
604 * Additional window is displayed to add address to the list
606 void QKernel::AddAddress()
608 QDialog d(this, Qt::Dialog);
609 QLabel lab("IP Address:", &d);
610 QLineEdit ed("", &d);
611 QPushButton ob("", &d);
612 QPushButton cb("", &d);
615 ob.setGeometry(30, 60, 80, 30);
618 lab.setGeometry(10, 10, 60, 30);
619 lab.setText("Address");
620 ed.setGeometry(70, 10, 140, 30);
621 cb.setGeometry(130, 60, 80, 30);
622 cb.setText("Cancel");
624 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
625 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
627 if (strcmp(ed.text().toAscii().data(), "") != 0) {
628 connections->addItem(ed.text());
634 * Deletes current address from available connections.
636 void QKernel::DelAddress()
639 if (connections->currentRow() != -1) {
640 /* TODO: Checki if this work correctly after porting */
641 connections->removeItemWidget(connections->currentItem());
647 * Sends message to node.
648 * Additional window is displayed to set Node Number of node where send message,
649 * and textfield to enter message.
651 void QKernel::MessageToNode()
657 dlg = new QDialog(this, Qt::Dialog);
658 dlg->setWindowTitle("Send message to node");
660 nodenr = new QLineEdit("number", dlg);
661 nodenr->setGeometry(90, 10, 50, 30);
665 tmpQLabel = new QLabel("Node number:", dlg);
666 tmpQLabel->setGeometry(10, 10, 77, 30);
668 tmpQLabel = new QLabel("Message:", dlg);
669 tmpQLabel->setGeometry(10, 50, 70, 30);
672 msg = new QLineEdit("", dlg);
673 msg->setGeometry(80, 60, 330, 30);
676 ob = new QPushButton("Send", dlg);
677 ob->setGeometry(230, 10, 80, 30);
678 ob->setDefault(TRUE);
681 cb = new QPushButton("Cancel", dlg);
682 cb->setGeometry(330, 10, 80, 30);
683 dlg->resize(430, 110);
684 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
685 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
688 m.msg_type = MSG_NET;
689 m.param.pword[0] = NET_PROPAGATE;
690 m.param.pword[1] = MSG_VLP;
691 m.param.pword[2] = NodeNumber;
692 m.param.pword[4] = atoi(nodenr->text().toAscii().data());
693 m.param.pword[6] = VLP_WRITE;
694 strcpy(m.param.pstr, msg->text().toAscii().data());
695 write(net_sock, &m, sizeof(MESSAGE));
701 * Additional window is displayed to get ID of interpreter which should be
704 void QKernel::KillInterpreter()
711 dlg = new QDialog(this, Qt::Dialog);
712 dlg->setWindowTitle("Kill interpreter");
714 nodenr = new QLineEdit("", dlg);
715 nodenr->setGeometry(90, 10, 50, 30);
717 QLabel * tmpQLabel = new QLabel("Interp. ID:", dlg);
718 tmpQLabel->setGeometry(10, 10, 77, 30);
720 QPushButton * ob = new QPushButton("Kill", dlg);
721 ob->setGeometry( 160, 10, 80, 30);
722 ob->setDefault(TRUE);
724 QPushButton * cb = new QPushButton("Cancel", dlg);
725 cb->setGeometry(260, 10, 80, 30);
726 dlg->resize(360, 50);
728 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
729 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
732 m.msg_type = MSG_INT;
733 m.param.pword[0] = INT_KILL;
734 pom = findINTbyID(atoi(nodenr->text().toAscii().data()));
737 write(pom->sock, &m, sizeof(MESSAGE));
739 WriteMessage("This is a remote instance of "
743 WriteMessage("Interpreter not found");
749 * Sends message to the net module.
751 void QKernel::NetMessage()
754 /* TODO: It has to be rewritten */
760 cnt = read(net_sock, &msg, sizeof(MESSAGE));
761 if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
762 switch(msg.param.pword[0]) {
764 WriteMessage(msg.param.pstr);
767 switch(msg.param.pword[1]) {
769 /* pom = find_link_by_ID(msg.param.pword[5]);
770 msg.msg_type = MSG_NET;
771 msg.param.pword[0] = NET_PROPAGATE;
772 send_int(pom, &msg);*/
775 switch(msg.param.pword[6]) {
777 QApplication::beep();
778 WriteMessage(CharLine);
780 "### Incoming Messsage ###");
781 sprintf(ss, "Mesg from Node %d: %s",
785 WriteMessage(CharLine);
787 case VLP_REMOTE_INSTANCE:
788 sprintf(ss, "%s/%s", REMOTE_PATH,
792 WriteMessage("Running program:");
795 pom = RunIntModule(ss, 1);
797 pom->p_ctx.node = msg.param.pword[2];
798 pom->p_ctx.program_id =
800 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
803 case VLP_CLOSE_INSTANCE:
804 msg.msg_type = MSG_INT;
805 msg.param.pword[0] = INT_CLOSE_INSTANCE;
806 pom = findINTbyID(msg.param.pword[7]);
808 write(pom->sock, &msg,
811 m1.msg_type = MSG_VLP;
812 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
813 m1.param.pword[1] = pom->ID;
817 WriteMessage("Instance not found");
823 case NET_CONNECTIONS:
824 ActiveConnections = msg.param.pword[1];
825 WriteMessage(msg.param.pstr);
830 /* TODO: It has to be rewritten */
832 QString poms, poms1, poms2;
833 poms.sprintf("%s", msg.param.pstr);
834 while (poms.length() > 0) {
835 cnt = poms.indexOf(';');
837 poms1 = poms.left(cnt);
838 poms = poms.right(poms.length() - cnt - 1);
839 cnt = poms1.indexOf('=');
841 poms2 = poms1.left(cnt);
845 sprintf(ss, "Node: %s Addr: %s", poms2.data(), poms1.data());
853 wait_for_info = FALSE;
854 WriteMessage(CharLine);
861 * Sends message to the interpreter program.
862 * @param sock Interpreter socket to whom the message will be send.
864 void QKernel::IntMessage(int sock)
870 cnt = read(sock, &msg, sizeof(MESSAGE));
871 e = findINTbySocket(sock);
872 if ((cnt > 0) && (e != NULL)) {
873 switch (msg.msg_type) {
875 if (msg.param.pword[0] == GRAPH_ALLOCATE) {
876 RunGraphModule(msg.param.pstr);
880 write(net_sock, &msg, sizeof(MESSAGE));
883 switch(msg.param.pword[0]) {
884 case VLP_REMOTE_INSTANCE_PLEASE:
885 RemoteInstance(e, msg.param.pword[2]);
890 switch(msg.param.pword[0]) {
895 m.msg_type = MSG_VLP;
896 m.param.pword[0] = VLP_INTERPRETER_DOWN;
897 m.param.pword[1] = e->ID;
898 write(net_sock, &m, sizeof(MESSAGE));
903 /* TODO: Check this */
904 Interpreters.removeOne(e);
908 sprintf(ss, "%s : End of program "
909 "execution", msg.param.pstr);
914 msg.msg_type = MSG_INT;
915 msg.param.pword[0] = INT_CTX;
916 msg.param.pword[1] = NodeNumber;
917 msg.param.pword[2] = e->ID;
919 msg.param.pword[3] = e->p_ctx.node;
923 write(sock, &msg, sizeof(MESSAGE));
932 * Writes message to kernel logger.
933 * @parame msg String with message to log
935 void QKernel::WriteMessage(char *msg)
939 x = desktop->textCursor().blockNumber();
940 y = desktop->textCursor().columnNumber();
946 desktop->setReadOnly(FALSE);
947 desktop->append(msg);
948 desktop->setReadOnly(TRUE);
950 QTextCursor tmpCursor = desktop->textCursor();
951 tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
952 desktop->setTextCursor(tmpCursor);
956 if (desktop->document()->blockCount() > 100) {
962 * Adds checkbox to menu item. If it is checked additional info messages are
965 void QKernel::SetMessages()
967 if (toolsMenu != NULL) {
968 if (msgid->isChecked()) {
969 msgid->setChecked(FALSE);
970 info_messages = FALSE;
972 msgid->setChecked(TRUE);
973 info_messages = TRUE;
976 /* bar->repaint(); */
980 * Allows to set options in GUI window.
981 * Additional window is displayed to set kernel options which are saved in
982 * vlp.cfg file in kernel executable directory.
984 void QKernel::SetOptions()
986 QDialog dlg(this, Qt::Dialog);
987 dlg.setWindowTitle("Options");
992 progs = new QLineEdit(progdir, &dlg);
993 progs->setGeometry(150, 20, 180, 30);
996 tmpQLabel = new QLabel("Programs directory", &dlg);
997 tmpQLabel->setGeometry(30, 20, 120, 30);
1000 tmpQFrame = new QFrame(&dlg);
1001 tmpQFrame->setGeometry(10, 60, 380, 30);
1002 tmpQFrame->setFrameStyle(52);
1004 tmpQLabel = new QLabel("Virtual Processor properties (activated after "
1005 "restarting VLP):", &dlg);
1006 tmpQLabel->setGeometry(10, 80, 340, 30);
1010 sprintf(nns, "%d", NodeNumber);
1011 nn = new QLineEdit(nns, &dlg);
1012 nn->setGeometry(110, 110, 40, 30);
1014 tmpQLabel = new QLabel("Node number:", &dlg);
1015 tmpQLabel->setGeometry(20, 110, 90, 30);
1017 QRadioButton *exp, *reg;
1018 exp = new QRadioButton("Explicit", &dlg);
1019 exp->setGeometry(30, 170, 100, 30);
1020 exp->setChecked(TRUE);
1022 reg = new QRadioButton("Registration", &dlg);
1023 reg->setGeometry(30, 200, 100, 30);
1024 reg->setEnabled(FALSE);
1026 connections = new QListWidget(&dlg);
1027 connections->setGeometry(170, 140, 130, 100);
1029 for (int i = 0; i < ConnectList.size(); i++) {
1030 e = ConnectList.at(i);
1031 connections->addItem(e->addr);
1034 tmpQLabel = new QLabel("Connection list:", &dlg);
1035 tmpQLabel->setGeometry(170, 110, 100, 30);
1037 QPushButton *addbtn;
1038 QPushButton *delbtn;
1040 QPushButton *cancelbtn;
1041 addbtn = new QPushButton("Add", &dlg);
1042 addbtn->setGeometry(310, 150, 60, 30);
1043 connect(addbtn, SIGNAL(clicked()), this, SLOT(AddAddress()));
1045 delbtn = new QPushButton("Del", &dlg);
1046 delbtn->setGeometry(310, 200, 60, 30);
1047 connect(delbtn, SIGNAL(clicked()), this, SLOT(DelAddress()));
1049 okbtn = new QPushButton("Ok", &dlg);
1050 okbtn->setGeometry(80, 260, 100, 30);
1051 okbtn->setDefault(TRUE);
1052 connect(okbtn, SIGNAL(clicked()), &dlg, SLOT(accept()));
1054 cancelbtn = new QPushButton("Cancel", &dlg);
1055 cancelbtn->setGeometry(210, 260, 100, 30);
1056 connect(cancelbtn, SIGNAL(clicked()), &dlg, SLOT(reject()));
1059 group = new QGroupBox("Connection type", &dlg);
1060 group->setGeometry(20, 150, 120, 90);
1061 group->setAlignment(Qt::AlignLeft);
1064 QVBoxLayout *vbox = new QVBoxLayout();
1065 vbox->addWidget(exp);
1066 vbox->addWidget(reg);
1067 vbox->addStretch(1);
1068 group->setLayout(vbox);
1070 dlg.resize(400, 310);
1073 config_setting_t *root;
1074 config_setting_t *setting;
1077 root = config_root_setting(&cfg);
1079 setting = config_setting_add(root, "progdir",
1080 CONFIG_TYPE_STRING);
1081 config_setting_set_string(setting, progs->text().toAscii().data());
1082 strcpy(progdir, progs->text().toAscii().data());
1084 setting = config_setting_add(root, "node_number",
1086 config_setting_set_int(setting, atoi(nn->text().toAscii().data()));
1088 setting = config_setting_add(root, "homedir",
1089 CONFIG_TYPE_STRING);
1090 config_setting_set_string(setting, HomeDir);
1092 setting = config_setting_add(root, "type",
1093 CONFIG_TYPE_STRING);
1094 if (exp->isChecked()) {
1095 config_setting_set_string(setting, "explicit");
1097 config_setting_t *hosts = NULL;
1098 hosts = config_setting_add(root, "host",
1100 for(i = 0; i < connections->count(); i++) {
1101 setting = config_setting_add(hosts, NULL,
1102 CONFIG_TYPE_STRING);
1103 config_setting_set_string(setting,
1104 connections->item(i)->text().toAscii().data());
1107 config_setting_set_string(setting, "register");
1110 if (!config_write_file(&cfg, "vlp.cfg")) {
1111 fprintf(stderr, "Error while writing to file: %s.\n",
1114 config_destroy(&cfg);
1119 * Locks kernel program.
1120 * Additional window is displayed to enter password and retype it. If both are
1121 * same kernel window is locked.
1123 void QKernel::LockConsole()
1125 QDialog d(this, Qt::Dialog);
1126 d.setWindowTitle("Lock console");
1128 QPushButton ob("Ok", &d);
1129 ob.setGeometry(30, 60, 80, 30);
1130 ob.setDefault(TRUE);
1131 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
1133 QLabel lab("Password:", &d);
1134 lab.setGeometry(10, 10, 60, 30);
1136 QLineEdit ed("", &d);
1137 ed.setGeometry(70, 10, 140, 30);
1138 ed.setEchoMode(QLineEdit::Password);
1140 QPushButton cb("Cancel", &d);
1141 cb.setGeometry(130, 60, 80, 30);
1142 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
1147 if (strcmp(ed.text().toAscii().data(), "") != 0) {
1148 strcpy(LockPasswd, ed.text().toAscii().data());
1149 lab.setText("Retype:");
1152 * Following exec(), could produce error:
1153 * X Error: BadWindow (invalid Window parameter) 3
1154 * Major opcode: 3 (X_GetWindowAttributes)
1156 * This is not error in our code. Basing on:
1157 * https://bugreports.qt-project.org/browse/QTBUG-1782
1158 * this happens only on Qt 4.3 - 4.4.
1161 if (strcmp(ed.text().toAscii().data(), LockPasswd) == 0) {
1162 qid->setDisabled(TRUE);
1163 programExecuteAction->setDisabled(TRUE);
1164 programKillAction->setDisabled(TRUE);
1165 machineMessageAction->setDisabled(TRUE);
1166 machineConnectAction->setDisabled(TRUE);
1167 machineDisconnectAction->setDisabled(TRUE);
1168 machineInfoAction->setDisabled(TRUE);
1170 unlockid->setEnabled(TRUE);
1171 lockid->setDisabled(TRUE);
1172 cwid->setDisabled(TRUE);
1173 optid->setDisabled(TRUE);
1174 WriteMessage("CONSOLE LOCKED");
1177 QMessageBox msg(this);
1178 msg.setText("Not matching!");
1179 msg.setButtonText(0, "Close");
1183 strcpy(LockPasswd, "");
1190 * Unlocks kernel program.
1191 * Additional window is displayed to enter password. If it is correct, kernel
1192 * window is unlocked
1194 void QKernel::UnlockConsole()
1196 QDialog d(this, Qt::Dialog);
1197 d.setWindowTitle("Enter password");
1199 QLabel lab("Password:", &d);
1200 lab.setGeometry(10, 10, 60, 30);
1202 QLineEdit ed("", &d);
1203 ed.setGeometry(70, 10, 140, 30);
1204 ed.setEchoMode(QLineEdit::Password);
1206 QPushButton ob("Ok", &d);
1207 ob.setGeometry(30, 60, 80, 30);
1208 ob.setDefault(TRUE);
1209 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
1211 QPushButton cb("Cancel", &d);
1212 cb.setGeometry(130, 60, 80, 30);
1213 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
1218 if (strcmp(ed.text().toAscii().data(), LockPasswd) == 0) {
1219 qid->setEnabled(TRUE);
1220 programExecuteAction->setEnabled(TRUE);
1221 programKillAction->setEnabled(TRUE);
1222 machineMessageAction->setEnabled(TRUE);
1223 machineConnectAction->setEnabled(TRUE);
1224 machineDisconnectAction->setEnabled(TRUE);
1225 machineInfoAction->setEnabled(TRUE);
1226 unlockid->setEnabled(FALSE);
1227 lockid->setEnabled(TRUE);
1228 cwid->setEnabled(TRUE);
1229 optid->setEnabled(TRUE);
1230 WriteMessage("CONSOLE UNLOCKED");
1233 QMessageBox msg(this);
1234 msg.setText("Wrong password!");
1235 msg.setButtonText(0, "Close");
1242 * Writes init message in kernel
1244 void QKernel::InitMessage()
1246 WriteMessage("\n " PACKAGE_STRING ": READY \n");
1250 * Finds Interpreter by its socket
1251 * @param _id ID of the socket
1252 * @return returns pointer to the found interpreter slot. NULL otherwise
1254 InterpEntry *QKernel::findINTbySocket(int _id)
1256 InterpEntry *pom = NULL;
1258 for (int i = 0; i < Interpreters.size(); i++) {
1259 if (Interpreters.at(i)->sock == _id) {
1260 pom = Interpreters.at(i);
1269 * Finds Interpreter by its ID.
1270 * @param _id ID of the interpreter
1271 * @return returns pointer to the found interpreter slot. NULL otherwise
1273 InterpEntry *QKernel::findINTbyID(int _id)
1275 InterpEntry *pom = NULL;
1277 for (int i = 0; i < Interpreters.size(); i++) {
1278 if (Interpreters.at(i)->ID == _id) {
1279 pom = Interpreters.at(i);
1289 * Connects interpreter
1290 * @param ss full filepath with filename but without extension of the loglan
1292 * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
1294 * @return Returns pointer to newly created interpreter slot, or NULL on error.
1296 InterpEntry *QKernel::RunIntModule(char *ss, int r)
1298 char a[256], b[255];
1299 struct sockaddr_un svr;
1300 int len, sock, i, on;
1305 InterpEntry *newINT = NULL;
1311 WriteMessage("File not found: no .ccd file");
1320 WriteMessage("File not found: no .pcd file");
1325 newINT = new InterpEntry;
1326 for(i = 0; i < MAXINSTANCES; i++)
1327 newINT->RInstances[i] =- 1;
1329 strcpy(b, rindex(ss, '/'));
1330 for(i = 0; i < strlen(b); i++)
1332 if (info_messages) {
1333 sprintf(a, "%s : Start execution", b);
1339 newINT->ID = newint;
1340 strcpy(newINT->shortname, b);
1341 strcpy(newINT->fullname, ss);
1343 sprintf(a, "%s%d", IPATH, newint);
1344 sprintf(cmd, "%s/modules/logint %s %s", HomeDir, a, ss);
1347 sprintf(b, " %s %s %s %s %s", myargs[0], myargs[1], myargs[2],
1348 myargs[3], myargs[4]);
1352 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1354 bzero(&svr, sizeof(svr));
1355 svr.sun_family = AF_UNIX;
1356 strcpy(svr.sun_path, a);
1357 len = strlen(svr.sun_path)+sizeof(svr.sun_family);
1358 bind(sock, (struct sockaddr*)&svr, len);
1361 newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
1364 if (newINT->sock > 0) {
1365 fcntl(newINT->sock, F_SETFL,
1366 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
1368 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
1375 bzero(&msg, sizeof(MESSAGE));
1376 msg.msg_type = MSG_VLP;
1377 msg.param.pword[0] = VLP_REGINT;
1378 msg.param.pword[1] = newINT->ID;
1379 sprintf(msg.param.pstr, "logi%d.net", newint);
1380 write(net_sock, &msg, sizeof(MESSAGE));
1382 Interpreters.append(newINT);
1383 newINT->notify = new QSocketNotifier(newINT->sock,
1384 QSocketNotifier::Read);
1385 connect(newINT->notify, SIGNAL(activated(int)), this,
1386 SLOT(IntMessage(int)));
1388 WriteMessage("INTERPRETER successfully connected");
1390 WriteMessage("Cannot connect interpreter");
1397 * Allocates remote instance of interpreter
1398 * @param interp Interpreter slot
1399 * @param on Node Number
1401 void QKernel::RemoteInstance(InterpEntry *interp, int on)
1406 m.msg_type = MSG_NET;
1407 m.param.pword[0] = NET_NODE_EXIST;
1408 m.param.pword[1] = on;
1409 m.param.pword[2] = interp->ID;
1410 write(net_sock, &m, sizeof(MESSAGE));
1411 bzero(&m, sizeof(MESSAGE));
1412 while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
1413 read(net_sock, &m, sizeof(MESSAGE));
1415 /* means node exists */
1416 if (m.param.pword[1] == 1) {
1417 m.msg_type = MSG_NET;
1418 m.param.pword[0] = NET_TRANSMIT_CODE;
1419 m.param.pword[1] = interp->ID;
1420 m.param.pword[2] = on;
1421 strcpy(m.param.pstr, interp->fullname);
1422 write(net_sock, &m, sizeof(MESSAGE));
1424 Net_Notify->setEnabled(FALSE);
1425 while ((m.msg_type != MSG_NET) ||
1426 (m.param.pword[0] != NET_TRANSMITTED))
1427 read(net_sock, &m, sizeof(MESSAGE));
1429 m.msg_type = MSG_NET;
1430 m.param.pword[0] = NET_PROPAGATE;
1431 m.param.pword[1] = MSG_VLP;
1432 m.param.pword[2] = NodeNumber;
1433 m.param.pword[3] = 0;
1434 m.param.pword[4] = on;
1435 m.param.pword[5] = 0;
1436 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1437 m.param.pword[7] = interp->ID;
1438 strcpy(m.param.pstr, interp->shortname);
1439 write(net_sock, &m, sizeof(MESSAGE));
1441 read(net_sock, &m, sizeof(MESSAGE));
1443 if ((m.param.pword[0] == NET_PROPAGATE) &&
1444 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1445 interp->RInstances[on] = m.param.pword[7];
1448 read(net_sock, &m, sizeof(MESSAGE));
1451 Net_Notify->setEnabled(TRUE);
1453 /*bzero(&m, sizeof(MESSAGE));*/
1454 m.msg_type = MSG_VLP;
1455 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1456 m.param.pword[1] = interp->RInstances[on];
1457 write(interp->sock, &m, sizeof(MESSAGE));
1458 } else { /* There is no such a node! */
1459 sprintf(s, "Warning: Node number %d not found!", on);
1461 WriteMessage("Allocating O-process on the local node");
1462 bzero(&m, sizeof(MESSAGE));
1463 m.msg_type = MSG_VLP;
1464 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1465 m.param.pword[1] = interp->ID;
1466 write(interp->sock, &m, sizeof(MESSAGE));
1471 * Closes all remote instances
1473 void QKernel::CloseInstances(InterpEntry *e)
1479 WriteMessage("Closing remote instances");
1481 for(i=0; i < MAXINSTANCES; i++)
1482 if (e->RInstances[i]>=0) {
1483 msg.msg_type = MSG_NET;
1484 msg.param.pword[0] = NET_PROPAGATE;
1485 msg.param.pword[1] = MSG_VLP;
1486 msg.param.pword[2] = NodeNumber;
1487 msg.param.pword[4] = i;
1488 msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1489 msg.param.pword[7] = e->RInstances[i];
1490 write(net_sock, &msg, sizeof(MESSAGE));
1495 * Displays information about virtual machine
1497 void QKernel::Info()
1501 WriteMessage(CharLine);
1502 WriteMessage("### Virtual Machine Information ###");
1503 m.msg_type = MSG_NET;
1504 m.param.pword[0] = NET_GET_INFO;
1505 write(net_sock, &m, sizeof(MESSAGE));
1506 wait_for_info = TRUE;
1509 #include "kernel.moc"
1512 * Program main function
1513 * All program arguments but the first one (argv[0]: program name) are saved and
1514 * passed to all dependent programs on their invocation.
1515 * @param argc Number of program arguments
1516 * @param argv Program arguments
1518 int main(int argc, char **argv)
1521 for(i = 0; i < 5; i++) {
1522 strcpy(myargs[i], "");
1524 for(i = 1; i < argc; i++) {
1525 strcpy(myargs[i - 1], argv[i]);
1528 app = new QApplication(argc, argv);
1531 kernel.InitMessage();