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>
62 #include <netinet/in.h>
64 #include <libconfig.h>
68 /* File resides in top directory (where are Makefiles)*/
69 #include "../../config.h"
72 char CharLine[25] = "________________________";
78 * Event invoked on program close.
79 * Closes application. Displays additional window to confirm exit.
81 void QKernel::closeEvent(QCloseEvent * e)
90 void QKernel::setLocked(bool locked)
94 quitAction->setDisabled(locked);
95 programExecuteAction->setDisabled(locked);
96 programKillAction->setDisabled(locked);
97 machineMessageAction->setDisabled(locked);
98 machineConnectAction->setDisabled(locked);
99 machineDisconnectAction->setDisabled(locked);
100 machineInfoAction->setDisabled(locked);
102 /* Enable only menu entry for unlocking */
103 toolsEditorAction->setDisabled(locked);
104 toolsOptionsAction->setDisabled(locked);
105 toolsLockAction->setDisabled(locked);
106 toolsUnlockAction->setEnabled(locked);
110 * Kernel program constructor.
111 * Prepares everything to work.
119 sprintf(ss, "mkdir %s", REMOTE_PATH);
123 info_messages = TRUE;
124 wait_for_info = FALSE;
126 setWindowTitle(PACKAGE_NAME);
128 QMenu * programMenu = NULL;
129 programMenu = menuBar()->addMenu("&Program");
130 programExecuteAction = programMenu->addAction("Execute", this, SLOT(Run_Prog()));
131 programKillAction = programMenu->addAction("Kill", this, SLOT(KillInterpreter()));
133 machineMenu = menuBar()->addMenu("&Machine");
134 machineMessageAction = machineMenu->addAction("Message", this, SLOT(MessageToNode()));
135 machineMenu->addSeparator();
136 machineConnectAction = machineMenu->addAction("Connect", this, SLOT(Connect()));
137 machineDisconnectAction = machineMenu->addAction("Disconnect", this, SLOT(Disconnect()));
138 machineInfoAction = machineMenu->addAction("Info", this, SLOT(Info()));
140 toolsMenu = menuBar()->addMenu("&Tools");
141 toolsEditorAction = toolsMenu->addAction("Editor", this, SLOT(Edit()));
142 toolsMenu->addAction("Help", this, SLOT(Help()));
143 toolsMenu->addSeparator();
144 toolsOptionsAction = toolsMenu->addAction("Options", this, SLOT(SetOptions()));
145 toolsInfoAction = toolsMenu->addAction("Info messages", this, SLOT(SetMessages()));
146 toolsInfoAction->setCheckable(TRUE);
147 toolsInfoAction->setChecked(TRUE);
148 toolsMenu->addSeparator();
149 toolsLockAction = toolsMenu->addAction("Lock console", this, SLOT(LockConsole()));
150 toolsUnlockAction = toolsMenu->addAction("Unlock console", this,
151 SLOT(UnlockConsole()));
152 toolsUnlockAction->setDisabled(TRUE);
155 quitAction = menuBar()->addAction("&Quit", this, SLOT(QuitProc()));
157 desktop = new QTextEdit(this);
158 desktop->setReadOnly(TRUE);
159 QVBoxLayout * layout = new QVBoxLayout();
160 layout->setContentsMargins (3, 0, 3, 0);
161 layout->addWidget(desktop);
162 QWidget *window = new QWidget();
163 window->setLayout(layout);
164 setCentralWidget(window);
169 ActiveConnections = 0;
170 strcpy(LockPasswd, "");
171 LoadConfig("vlp.cfg");
174 Net_Notify = new QSocketNotifier(net_sock, QSocketNotifier::Read, this);
175 connect(Net_Notify, SIGNAL(activated(int)), this, SLOT(NetMessage()));
179 * Event invoked on resizing kernel application window.
180 * @copydoc QWidget::resizeEvent(QResizeEvent*)
182 void QKernel::resizeEvent(QResizeEvent *ev)
184 // QFrame::resizeEvent(ev);
186 // desktop->setGeometry(0, bar->height(), width(),
187 // height() - bar->height());
191 * Displays window with information about not implemented functionality.
193 void QKernel::n_impl()
195 QMessageBox::information(this, "Function info", "This function is not "
196 "implemented yet...", "Ok");
200 * Loads configuration from the given file.
201 * @param fname Filename of the configuration file.
203 void QKernel::LoadConfig(char * fname)
206 config_setting_t *setting;
209 /* Hack for checking if file exists without using external libs.*/
210 FILE * file = fopen(fname, "rt");
212 fprintf(stderr, "Error: Cannot load configuration file %s!\n",
216 /* File exists, so file has been locked. Release it. */
220 /* Read the file. If there is an error, report it and exit. */
221 if (!config_read(&cfg, file)) {
222 fprintf(stderr, "%s! In file %s, line %d\n",
223 config_error_text(&cfg),
224 config_error_file(&cfg),
225 config_error_line(&cfg));
226 config_destroy(&cfg);
231 setting = config_lookup(&cfg, "node_number");
233 NodeNumber = config_setting_get_int(setting);
235 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
236 "Warning", fname, "node_number");
237 config_destroy(&cfg);
242 setting = config_lookup(&cfg, "type");
244 /* same as strcmp(..) == 0 */
245 if (!strcmp(config_setting_get_string(setting), "explicit")) {
251 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
252 "Warning", fname, "type");
255 setting = config_lookup(&cfg, "host");
257 switch(config_setting_type(setting)) {
258 /* TODO: Deprecated. Made for back compatibility. */
259 case CONFIG_TYPE_STRING:
260 ConnectList.append(new ConnectEntry((char*)
261 config_setting_get_string(setting)));
263 case CONFIG_TYPE_ARRAY: {
264 int size = config_setting_length(setting);
265 for (int i = 0; i < size; i++) {
266 ConnectList.append(new ConnectEntry((char*)
267 config_setting_get_string_elem(setting,
273 fprintf(stderr, "%s! In file %s, bad entry type for %s."
274 " Will not be read.\n",
275 "Error", fname, "host");
278 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
279 "Warning", fname, "host");
282 setting = config_lookup(&cfg, "progdir");
284 strncpy(progdir, config_setting_get_string(setting), 256);
286 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
287 "Warning", fname, "progdir");
290 setting = config_lookup(&cfg, "homedir");
292 strncpy(HomeDir, config_setting_get_string(setting), 255);
294 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
295 "Warning", fname, "homedir");
298 config_destroy(&cfg);
304 * Additional window id displayed to set which code to execute.
306 void QKernel::Run_Prog()
309 QString s = QFileDialog::getOpenFileName(this, "Execute", progdir, "*.log");
312 i = s.indexOf(".log");
317 RunIntModule((char*)s.toAscii().data(), 0);
322 * Invokes editor program
327 sprintf(cmd, "%s/modules/logedit %s %s %s %s %s %s &", HomeDir, HomeDir,
328 myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
333 * Invokes help program
338 sprintf(cmd, "%s/modules/loghelp %s/doc %s %s %s %s %s &", HomeDir,
339 HomeDir, myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
344 * Invokes graphics module
346 void QKernel::RunGraphModule(char *sk)
350 sprintf(cmd, "%s/modules/loggraph %s %s %s %s %s %s &", HomeDir,
351 sk, myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
353 if (system(cmd) != 0)
354 WriteMessage("Cannot connect GRAPH resources");
360 void QKernel::RunNetModule()
362 struct sockaddr_un svr;
366 sprintf(cmd, "%s/modules/lognet %s %s %s %s %s %s &", HomeDir,
367 NPATH, myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]);
369 /* -------- socket for NET module -------- */
371 sock = socket(AF_UNIX, SOCK_STREAM, 0);
372 bzero(&svr, sizeof(svr));
373 svr.sun_family = AF_UNIX;
374 strcpy(svr.sun_path, NPATH);
375 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
376 bind(sock, (struct sockaddr*)&svr, len);
379 if (system(cmd) == 0) {
380 net_sock = accept(sock, (struct sockaddr*)0, (unsigned int*)0);
383 WriteMessage("NETWORK successfully connected");
384 fcntl(net_sock, F_SETFL, O_NONBLOCK|fcntl(net_sock,
387 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY,
388 (char*)&on, sizeof(on));
390 WriteMessage("Cannot connect NETWORK resources");
391 WriteMessage("Exiting...");
397 WriteMessage("Cannot connect NETWORK resources");
398 WriteMessage("Exiting...");
405 * Connects to the specified address
406 * Additional window is displayed to connect to the specified address
408 void QKernel::Connect()
410 QDialog d(this, Qt::Dialog);
411 QLabel lab("IP Address:", &d);
412 QLineEdit ed("", &d);
413 QPushButton ob("", &d);
414 QPushButton cb("", &d);
417 ob.setGeometry(30, 60, 80, 30);
420 lab.setGeometry(10, 10, 60, 30);
421 lab.setText("Address");
422 ed.setGeometry(70, 10, 140, 30);
423 cb.setGeometry(130, 60, 80, 30);
424 cb.setText("Cancel");
427 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
428 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
430 m.msg_type = MSG_NET;
431 m.param.pword[0] = NET_CONNECT_TO;
432 strcpy(m.param.pstr, ed.text().toAscii().data());
433 write(net_sock, &m, sizeof(MESSAGE));
438 * Disconnects from virtual machine
440 void QKernel::Disconnect()
445 WriteMessage("Disconnecting from virtual machine");
447 msg.msg_type = MSG_NET;
448 msg.param.pword[0] = NET_DISCONNECT;
449 write(net_sock, &msg, sizeof(MESSAGE));
453 * Quits process. Closes VLP. Shows additional window to confirm exit.
455 void QKernel::QuitProc()
459 QMessageBox::StandardButton response;
460 response = QMessageBox::question(this, "Close VLP", "Terminate VLP ?",
461 QMessageBox::Ok | QMessageBox::Cancel);
464 if (response == QMessageBox::Cancel) {
468 msg.msg_type = MSG_NET;
469 msg.param.pword[0] = NET_DISCONNECT;
470 write(net_sock, &msg, sizeof(MESSAGE));*/
473 msg.msg_type = MSG_NET;
474 msg.param.pword[0] = NET_EXIT;
475 write(net_sock, &msg, sizeof(MESSAGE));
476 /* ::close(net_sock);*/
477 QApplication::instance()->quit();
481 * Adds IP address to the configuration.
482 * Additional window is displayed to add address to the list
484 void QKernel::AddAddress()
486 QDialog d(this, Qt::Dialog);
487 QLabel lab("IP Address:", &d);
488 QLineEdit ed("", &d);
489 QPushButton ob("", &d);
490 QPushButton cb("", &d);
493 ob.setGeometry(30, 60, 80, 30);
496 lab.setGeometry(10, 10, 60, 30);
497 lab.setText("Address");
498 ed.setGeometry(70, 10, 140, 30);
499 cb.setGeometry(130, 60, 80, 30);
500 cb.setText("Cancel");
502 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
503 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
505 if (strcmp(ed.text().toAscii().data(), "") != 0) {
506 connections->addItem(ed.text());
512 * Deletes current address from available connections.
514 void QKernel::DelAddress()
517 if (connections->currentRow() != -1) {
518 /* TODO: Checki if this work correctly after porting */
519 connections->removeItemWidget(connections->currentItem());
525 * Sends message to node.
526 * Additional window is displayed to set Node Number of node where send message,
527 * and textfield to enter message.
529 void QKernel::MessageToNode()
535 dlg = new QDialog(this, Qt::Dialog);
536 dlg->setWindowTitle("Send message to node");
538 nodenr = new QLineEdit("number", dlg);
539 nodenr->setGeometry(90, 10, 50, 30);
543 tmpQLabel = new QLabel("Node number:", dlg);
544 tmpQLabel->setGeometry(10, 10, 77, 30);
546 tmpQLabel = new QLabel("Message:", dlg);
547 tmpQLabel->setGeometry(10, 50, 70, 30);
550 msg = new QLineEdit("", dlg);
551 msg->setGeometry(80, 60, 330, 30);
554 ob = new QPushButton("Send", dlg);
555 ob->setGeometry(230, 10, 80, 30);
556 ob->setDefault(TRUE);
559 cb = new QPushButton("Cancel", dlg);
560 cb->setGeometry(330, 10, 80, 30);
561 dlg->resize(430, 110);
562 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
563 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
566 m.msg_type = MSG_NET;
567 m.param.pword[0] = NET_PROPAGATE;
568 m.param.pword[1] = MSG_VLP;
569 m.param.pword[2] = NodeNumber;
570 m.param.pword[4] = atoi(nodenr->text().toAscii().data());
571 m.param.pword[6] = VLP_WRITE;
572 strcpy(m.param.pstr, msg->text().toAscii().data());
573 write(net_sock, &m, sizeof(MESSAGE));
579 * Additional window is displayed to get ID of interpreter which should be
582 void QKernel::KillInterpreter()
589 dlg = new QDialog(this, Qt::Dialog);
590 dlg->setWindowTitle("Kill interpreter");
592 nodenr = new QLineEdit("", dlg);
593 nodenr->setGeometry(90, 10, 50, 30);
595 QLabel * tmpQLabel = new QLabel("Interp. ID:", dlg);
596 tmpQLabel->setGeometry(10, 10, 77, 30);
598 QPushButton * ob = new QPushButton("Kill", dlg);
599 ob->setGeometry( 160, 10, 80, 30);
600 ob->setDefault(TRUE);
602 QPushButton * cb = new QPushButton("Cancel", dlg);
603 cb->setGeometry(260, 10, 80, 30);
604 dlg->resize(360, 50);
606 connect(ob, SIGNAL(clicked()), dlg, SLOT(accept()));
607 connect(cb, SIGNAL(clicked()), dlg, SLOT(reject()));
610 m.msg_type = MSG_INT;
611 m.param.pword[0] = INT_KILL;
612 pom = findINTbyID(atoi(nodenr->text().toAscii().data()));
615 write(pom->sock, &m, sizeof(MESSAGE));
617 WriteMessage("This is a remote instance of "
621 WriteMessage("Interpreter not found");
627 * Sends message to the net module.
629 void QKernel::NetMessage()
632 /* TODO: It has to be rewritten */
638 cnt = read(net_sock, &msg, sizeof(MESSAGE));
639 if ((cnt > 0) && (msg.msg_type == MSG_NET)) {
640 switch(msg.param.pword[0]) {
642 WriteMessage(msg.param.pstr);
645 switch(msg.param.pword[1]) {
647 /* pom = find_link_by_ID(msg.param.pword[5]);
648 msg.msg_type = MSG_NET;
649 msg.param.pword[0] = NET_PROPAGATE;
650 send_int(pom, &msg);*/
653 switch(msg.param.pword[6]) {
655 QApplication::beep();
656 WriteMessage(CharLine);
658 "### Incoming Messsage ###");
659 sprintf(ss, "Mesg from Node %d: %s",
663 WriteMessage(CharLine);
665 case VLP_REMOTE_INSTANCE:
666 sprintf(ss, "%s/%s", REMOTE_PATH,
670 WriteMessage("Running program:");
673 pom = RunIntModule(ss, 1);
675 pom->p_ctx.node = msg.param.pword[2];
676 pom->p_ctx.program_id =
678 pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
681 case VLP_CLOSE_INSTANCE:
682 msg.msg_type = MSG_INT;
683 msg.param.pword[0] = INT_CLOSE_INSTANCE;
684 pom = findINTbyID(msg.param.pword[7]);
686 write(pom->sock, &msg,
689 m1.msg_type = MSG_VLP;
690 m1.param.pword[0] = VLP_INTERPRETER_DOWN;
691 m1.param.pword[1] = pom->ID;
695 WriteMessage("Instance not found");
701 case NET_CONNECTIONS:
702 ActiveConnections = msg.param.pword[1];
703 WriteMessage(msg.param.pstr);
708 /* TODO: It has to be rewritten */
710 QString poms, poms1, poms2;
711 poms.sprintf("%s", msg.param.pstr);
712 while (poms.length() > 0) {
713 cnt = poms.indexOf(';');
715 poms1 = poms.left(cnt);
716 poms = poms.right(poms.length() - cnt - 1);
717 cnt = poms1.indexOf('=');
719 poms2 = poms1.left(cnt);
723 sprintf(ss, "Node: %s Addr: %s", poms2.data(), poms1.data());
731 wait_for_info = FALSE;
732 WriteMessage(CharLine);
739 * Sends message to the interpreter program.
740 * @param sock Interpreter socket to whom the message will be send.
742 void QKernel::IntMessage(int sock)
748 cnt = read(sock, &msg, sizeof(MESSAGE));
749 e = findINTbySocket(sock);
750 if ((cnt > 0) && (e != NULL)) {
751 switch (msg.msg_type) {
753 if (msg.param.pword[0] == GRAPH_ALLOCATE) {
754 RunGraphModule(msg.param.pstr);
758 write(net_sock, &msg, sizeof(MESSAGE));
761 switch(msg.param.pword[0]) {
762 case VLP_REMOTE_INSTANCE_PLEASE:
763 RemoteInstance(e, msg.param.pword[2]);
768 switch(msg.param.pword[0]) {
773 m.msg_type = MSG_VLP;
774 m.param.pword[0] = VLP_INTERPRETER_DOWN;
775 m.param.pword[1] = e->ID;
776 write(net_sock, &m, sizeof(MESSAGE));
781 /* TODO: Check this */
782 Interpreters.removeOne(e);
786 sprintf(ss, "%s : End of program "
787 "execution", msg.param.pstr);
792 msg.msg_type = MSG_INT;
793 msg.param.pword[0] = INT_CTX;
794 msg.param.pword[1] = NodeNumber;
795 msg.param.pword[2] = e->ID;
797 msg.param.pword[3] = e->p_ctx.node;
801 write(sock, &msg, sizeof(MESSAGE));
810 * Writes message to kernel logger.
811 * @parame msg String with message to log
813 void QKernel::WriteMessage(char *msg)
817 x = desktop->textCursor().blockNumber();
818 y = desktop->textCursor().columnNumber();
824 desktop->setReadOnly(FALSE);
825 desktop->append(msg);
826 desktop->setReadOnly(TRUE);
828 QTextCursor tmpCursor = desktop->textCursor();
829 tmpCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
830 desktop->setTextCursor(tmpCursor);
834 if (desktop->document()->blockCount() > 100) {
840 * Adds checkbox to menu item. If it is checked additional info messages are
843 void QKernel::SetMessages()
845 if (toolsMenu != NULL) {
846 toolsInfoAction->setChecked(!toolsInfoAction->isChecked());
847 // toolsInfoAction->toggle();
848 info_messages = toolsInfoAction->isChecked();
849 fprintf(stderr, "Info is checked? %s\n", toolsInfoAction->isChecked() ? "yes" : "no");
851 // menuBar()->repaint();
855 * Allows to set options in GUI window.
856 * Additional window is displayed to set kernel options which are saved in
857 * vlp.cfg file in kernel executable directory.
859 void QKernel::SetOptions()
861 QDialog dlg(this, Qt::Dialog);
862 dlg.setWindowTitle("Options");
867 progs = new QLineEdit(progdir, &dlg);
868 progs->setGeometry(150, 20, 180, 30);
871 tmpQLabel = new QLabel("Programs directory", &dlg);
872 tmpQLabel->setGeometry(30, 20, 120, 30);
875 tmpQFrame = new QFrame(&dlg);
876 tmpQFrame->setGeometry(10, 60, 380, 30);
877 tmpQFrame->setFrameStyle(52);
879 tmpQLabel = new QLabel("Virtual Processor properties (activated after "
880 "restarting VLP):", &dlg);
881 tmpQLabel->setGeometry(10, 80, 340, 30);
885 sprintf(nns, "%d", NodeNumber);
886 nn = new QLineEdit(nns, &dlg);
887 nn->setGeometry(110, 110, 40, 30);
889 tmpQLabel = new QLabel("Node number:", &dlg);
890 tmpQLabel->setGeometry(20, 110, 90, 30);
892 QRadioButton *exp, *reg;
893 exp = new QRadioButton("Explicit", &dlg);
894 exp->setGeometry(30, 170, 100, 30);
895 exp->setChecked(TRUE);
897 reg = new QRadioButton("Registration", &dlg);
898 reg->setGeometry(30, 200, 100, 30);
899 reg->setEnabled(FALSE);
901 connections = new QListWidget(&dlg);
902 connections->setGeometry(170, 140, 130, 100);
904 for (int i = 0; i < ConnectList.size(); i++) {
905 e = ConnectList.at(i);
906 connections->addItem(e->addr);
909 tmpQLabel = new QLabel("Connection list:", &dlg);
910 tmpQLabel->setGeometry(170, 110, 100, 30);
915 QPushButton *cancelbtn;
916 addbtn = new QPushButton("Add", &dlg);
917 addbtn->setGeometry(310, 150, 60, 30);
918 connect(addbtn, SIGNAL(clicked()), this, SLOT(AddAddress()));
920 delbtn = new QPushButton("Del", &dlg);
921 delbtn->setGeometry(310, 200, 60, 30);
922 connect(delbtn, SIGNAL(clicked()), this, SLOT(DelAddress()));
924 okbtn = new QPushButton("Ok", &dlg);
925 okbtn->setGeometry(80, 260, 100, 30);
926 okbtn->setDefault(TRUE);
927 connect(okbtn, SIGNAL(clicked()), &dlg, SLOT(accept()));
929 cancelbtn = new QPushButton("Cancel", &dlg);
930 cancelbtn->setGeometry(210, 260, 100, 30);
931 connect(cancelbtn, SIGNAL(clicked()), &dlg, SLOT(reject()));
934 group = new QGroupBox("Connection type", &dlg);
935 group->setGeometry(20, 150, 120, 90);
936 group->setAlignment(Qt::AlignLeft);
939 QVBoxLayout *vbox = new QVBoxLayout();
940 vbox->addWidget(exp);
941 vbox->addWidget(reg);
943 group->setLayout(vbox);
945 dlg.resize(400, 310);
948 config_setting_t *root;
949 config_setting_t *setting;
952 root = config_root_setting(&cfg);
954 setting = config_setting_add(root, "progdir",
956 config_setting_set_string(setting, progs->text().toAscii().data());
957 strcpy(progdir, progs->text().toAscii().data());
959 setting = config_setting_add(root, "node_number",
961 config_setting_set_int(setting, atoi(nn->text().toAscii().data()));
963 setting = config_setting_add(root, "homedir",
965 config_setting_set_string(setting, HomeDir);
967 setting = config_setting_add(root, "type",
969 if (exp->isChecked()) {
970 config_setting_set_string(setting, "explicit");
972 config_setting_t *hosts = NULL;
973 hosts = config_setting_add(root, "host",
975 for(i = 0; i < connections->count(); i++) {
976 setting = config_setting_add(hosts, NULL,
978 config_setting_set_string(setting,
979 connections->item(i)->text().toAscii().data());
982 config_setting_set_string(setting, "register");
985 if (!config_write_file(&cfg, "vlp.cfg")) {
986 fprintf(stderr, "Error while writing to file: %s.\n",
989 config_destroy(&cfg);
994 * Locks kernel program.
995 * Additional window is displayed to enter password and retype it. If both are
996 * same kernel window is locked.
998 void QKernel::LockConsole()
1000 QDialog d(this, Qt::Dialog);
1001 d.setWindowTitle("Lock console");
1003 QPushButton ob("Ok", &d);
1004 ob.setGeometry(30, 60, 80, 30);
1005 ob.setDefault(TRUE);
1006 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
1008 QLabel lab("Password:", &d);
1009 lab.setGeometry(10, 10, 60, 30);
1011 QLineEdit ed("", &d);
1012 ed.setGeometry(70, 10, 140, 30);
1013 ed.setEchoMode(QLineEdit::Password);
1015 QPushButton cb("Cancel", &d);
1016 cb.setGeometry(130, 60, 80, 30);
1017 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
1022 if (strcmp(ed.text().toAscii().data(), "") != 0) {
1023 strcpy(LockPasswd, ed.text().toAscii().data());
1024 lab.setText("Retype:");
1027 * Following exec(), could produce error:
1028 * X Error: BadWindow (invalid Window parameter) 3
1029 * Major opcode: 3 (X_GetWindowAttributes)
1031 * This is not error in our code. Basing on:
1032 * https://bugreports.qt-project.org/browse/QTBUG-1782
1033 * this happens only on Qt 4.3 - 4.4.
1036 if (strcmp(ed.text().toAscii().data(), LockPasswd) == 0) {
1038 WriteMessage("CONSOLE LOCKED");
1040 QMessageBox msg(this);
1041 msg.setText("Not matching!");
1042 msg.setButtonText(0, "Close");
1046 strcpy(LockPasswd, "");
1053 * Unlocks kernel program.
1054 * Additional window is displayed to enter password. If it is correct, kernel
1055 * window is unlocked
1057 void QKernel::UnlockConsole()
1059 QDialog d(this, Qt::Dialog);
1060 d.setWindowTitle("Enter password");
1062 QLabel lab("Password:", &d);
1063 lab.setGeometry(10, 10, 60, 30);
1065 QLineEdit ed("", &d);
1066 ed.setGeometry(70, 10, 140, 30);
1067 ed.setEchoMode(QLineEdit::Password);
1069 QPushButton ob("Ok", &d);
1070 ob.setGeometry(30, 60, 80, 30);
1071 ob.setDefault(TRUE);
1072 connect(&ob, SIGNAL(clicked()), &d, SLOT(accept()));
1074 QPushButton cb("Cancel", &d);
1075 cb.setGeometry(130, 60, 80, 30);
1076 connect(&cb, SIGNAL(clicked()), &d, SLOT(reject()));
1081 if (strcmp(ed.text().toAscii().data(), LockPasswd) == 0) {
1083 WriteMessage("CONSOLE UNLOCKED");
1085 QMessageBox msg(this);
1086 msg.setText("Wrong password!");
1087 msg.setButtonText(0, "Close");
1094 * Writes init message in kernel
1096 void QKernel::InitMessage()
1098 WriteMessage("\n " PACKAGE_STRING ": READY \n");
1102 * Finds Interpreter by its socket
1103 * @param _id ID of the socket
1104 * @return returns pointer to the found interpreter slot. NULL otherwise
1106 InterpEntry *QKernel::findINTbySocket(int _id)
1108 InterpEntry *pom = NULL;
1110 for (int i = 0; i < Interpreters.size(); i++) {
1111 if (Interpreters.at(i)->sock == _id) {
1112 pom = Interpreters.at(i);
1121 * Finds Interpreter by its ID.
1122 * @param _id ID of the interpreter
1123 * @return returns pointer to the found interpreter slot. NULL otherwise
1125 InterpEntry *QKernel::findINTbyID(int _id)
1127 InterpEntry *pom = NULL;
1129 for (int i = 0; i < Interpreters.size(); i++) {
1130 if (Interpreters.at(i)->ID == _id) {
1131 pom = Interpreters.at(i);
1141 * Connects interpreter
1142 * @param ss full filepath with filename but without extension of the loglan
1144 * @param r Interpreter execution mode. 0 if it will be local instance, 1 if
1146 * @return Returns pointer to newly created interpreter slot, or NULL on error.
1148 InterpEntry *QKernel::RunIntModule(char *ss, int r)
1150 char a[256], b[255];
1151 struct sockaddr_un svr;
1152 int len, sock, i, on;
1157 InterpEntry *newINT = NULL;
1163 WriteMessage("File not found: no .ccd file");
1172 WriteMessage("File not found: no .pcd file");
1177 newINT = new InterpEntry;
1178 for(i = 0; i < MAXINSTANCES; i++)
1179 newINT->RInstances[i] =- 1;
1181 strcpy(b, rindex(ss, '/'));
1182 for(i = 0; i < strlen(b); i++)
1184 if (info_messages) {
1185 sprintf(a, "%s : Start execution", b);
1191 newINT->ID = newint;
1192 strcpy(newINT->shortname, b);
1193 strcpy(newINT->fullname, ss);
1195 sprintf(a, "%s%d", IPATH, newint);
1196 sprintf(cmd, "%s/modules/logint %s %s", HomeDir, a, ss);
1199 sprintf(b, " %s %s %s %s %s", myargs[0], myargs[1], myargs[2],
1200 myargs[3], myargs[4]);
1204 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1206 bzero(&svr, sizeof(svr));
1207 svr.sun_family = AF_UNIX;
1208 strcpy(svr.sun_path, a);
1209 len = strlen(svr.sun_path)+sizeof(svr.sun_family);
1210 bind(sock, (struct sockaddr*)&svr, len);
1213 newINT->sock = accept(sock, (struct sockaddr*)0, (unsigned int *)0);
1216 if (newINT->sock > 0) {
1217 fcntl(newINT->sock, F_SETFL,
1218 O_NONBLOCK|fcntl(newINT->sock, F_GETFL, 0));
1220 setsockopt(newINT->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
1227 bzero(&msg, sizeof(MESSAGE));
1228 msg.msg_type = MSG_VLP;
1229 msg.param.pword[0] = VLP_REGINT;
1230 msg.param.pword[1] = newINT->ID;
1231 sprintf(msg.param.pstr, "logi%d.net", newint);
1232 write(net_sock, &msg, sizeof(MESSAGE));
1234 Interpreters.append(newINT);
1235 newINT->notify = new QSocketNotifier(newINT->sock,
1236 QSocketNotifier::Read);
1237 connect(newINT->notify, SIGNAL(activated(int)), this,
1238 SLOT(IntMessage(int)));
1240 WriteMessage("INTERPRETER successfully connected");
1242 WriteMessage("Cannot connect interpreter");
1249 * Allocates remote instance of interpreter
1250 * @param interp Interpreter slot
1251 * @param on Node Number
1253 void QKernel::RemoteInstance(InterpEntry *interp, int on)
1258 m.msg_type = MSG_NET;
1259 m.param.pword[0] = NET_NODE_EXIST;
1260 m.param.pword[1] = on;
1261 m.param.pword[2] = interp->ID;
1262 write(net_sock, &m, sizeof(MESSAGE));
1263 bzero(&m, sizeof(MESSAGE));
1264 while((m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST))
1265 read(net_sock, &m, sizeof(MESSAGE));
1267 /* means node exists */
1268 if (m.param.pword[1] == 1) {
1269 m.msg_type = MSG_NET;
1270 m.param.pword[0] = NET_TRANSMIT_CODE;
1271 m.param.pword[1] = interp->ID;
1272 m.param.pword[2] = on;
1273 strcpy(m.param.pstr, interp->fullname);
1274 write(net_sock, &m, sizeof(MESSAGE));
1276 Net_Notify->setEnabled(FALSE);
1277 while ((m.msg_type != MSG_NET) ||
1278 (m.param.pword[0] != NET_TRANSMITTED))
1279 read(net_sock, &m, sizeof(MESSAGE));
1281 m.msg_type = MSG_NET;
1282 m.param.pword[0] = NET_PROPAGATE;
1283 m.param.pword[1] = MSG_VLP;
1284 m.param.pword[2] = NodeNumber;
1285 m.param.pword[3] = 0;
1286 m.param.pword[4] = on;
1287 m.param.pword[5] = 0;
1288 m.param.pword[6] = VLP_REMOTE_INSTANCE;
1289 m.param.pword[7] = interp->ID;
1290 strcpy(m.param.pstr, interp->shortname);
1291 write(net_sock, &m, sizeof(MESSAGE));
1293 read(net_sock, &m, sizeof(MESSAGE));
1295 if ((m.param.pword[0] == NET_PROPAGATE) &&
1296 (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK)) {
1297 interp->RInstances[on] = m.param.pword[7];
1300 read(net_sock, &m, sizeof(MESSAGE));
1303 Net_Notify->setEnabled(TRUE);
1305 /*bzero(&m, sizeof(MESSAGE));*/
1306 m.msg_type = MSG_VLP;
1307 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1308 m.param.pword[1] = interp->RInstances[on];
1309 write(interp->sock, &m, sizeof(MESSAGE));
1310 } else { /* There is no such a node! */
1311 sprintf(s, "Warning: Node number %d not found!", on);
1313 WriteMessage("Allocating O-process on the local node");
1314 bzero(&m, sizeof(MESSAGE));
1315 m.msg_type = MSG_VLP;
1316 m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1317 m.param.pword[1] = interp->ID;
1318 write(interp->sock, &m, sizeof(MESSAGE));
1323 * Closes all remote instances
1325 void QKernel::CloseInstances(InterpEntry *e)
1331 WriteMessage("Closing remote instances");
1333 for(i=0; i < MAXINSTANCES; i++)
1334 if (e->RInstances[i]>=0) {
1335 msg.msg_type = MSG_NET;
1336 msg.param.pword[0] = NET_PROPAGATE;
1337 msg.param.pword[1] = MSG_VLP;
1338 msg.param.pword[2] = NodeNumber;
1339 msg.param.pword[4] = i;
1340 msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1341 msg.param.pword[7] = e->RInstances[i];
1342 write(net_sock, &msg, sizeof(MESSAGE));
1347 * Displays information about virtual machine
1349 void QKernel::Info()
1353 WriteMessage(CharLine);
1354 WriteMessage("### Virtual Machine Information ###");
1355 m.msg_type = MSG_NET;
1356 m.param.pword[0] = NET_GET_INFO;
1357 write(net_sock, &m, sizeof(MESSAGE));
1358 wait_for_info = TRUE;
1362 * Program main function
1363 * All program arguments but the first one (argv[0]: program name) are saved and
1364 * passed to all dependent programs on their invocation.
1365 * @param argc Number of program arguments
1366 * @param argv Program arguments
1368 int main(int argc, char **argv)
1371 for(i = 0; i < 5; i++) {
1372 strcpy(myargs[i], "");
1374 for(i = 1; i < argc; i++) {
1375 strcpy(myargs[i - 1], argv[i]);
1378 QApplication * app = new QApplication(argc, argv);
1381 kernel.InitMessage();