Fixes: vlp-17.
[vlp.git] / src / kernel / kernel.cpp
1 /**************************************************************
2
3   Copyright (C) 1997  Oskar Swida
4
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.
9
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.
14
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.
18
19
20
21
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.
25
26  
27   To contact the author, write:
28      e-mail: swida@aragorn.pb.bialystok.pl
29
30 ************************************************************/
31
32
33 #include <qpixmap.h>
34 //#include <qwindow.h>
35 #include <qapp.h>
36 #include <qframe.h>
37 #include <qmlined.h>
38 #include <qpainter.h>
39 #include <qcolor.h>
40 #include <qbrush.h>
41 #include <qmenubar.h>
42 #include <qpopmenu.h>
43 #include <qfont.h>
44 #include <qmsgbox.h>
45 #include <qfiledlg.h>
46 #include <qtabdlg.h>
47 #include <qstring.h>
48 #include <qrect.h>
49 #include <qdialog.h>
50 #include <qbttngrp.h>
51 #include <qlabel.h>
52 #include <qlined.h>
53 #include <qlistbox.h>
54 #include <qpushbt.h>
55 #include <qradiobt.h>
56 #include <qlist.h>
57 #include <qfile.h>
58 #include <qcursor.h>
59 #include <qcombo.h>
60 #include <qsocknot.h>
61 #include <qdir.h>
62 #include <qwindowsstyle.h>
63
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <unistd.h>
67 #include <fcntl.h>
68
69 #include "genint1.h"
70 #include "comm.h"
71 #include "socu.h"
72 #include <netinet/in.h>
73
74 #include <libconfig.h>
75
76 #define GPATH "loggr"
77 #define IPATH "logi"
78 #define NPATH "logn"
79 #define REMOTE_PATH "REMOTE"
80 #define MAXINTERP 20
81 #define MAXINSTANCES 256 
82
83
84 #define MESG_COL        0
85 #define WARN_COL        1
86 #define NORM_COL        2
87
88
89 char CharLine[25]="________________________";
90 char myargs[5][255];
91
92
93 /* --------------- interpreter slot -----------------*/
94 class InterpEntry
95 {
96 public:
97  int ID;                                // INT identifier
98  bool remote;                           // Am I remote ?
99  char fullname[255],shortname[255];     // Program name
100  int sock;                              // Socket 
101  QSocketNotifier *notify;             
102  int RInstances[MAXINSTANCES];          // IDs of my remote INT modules
103  ctx_struct p_ctx;                      // parent INT info
104 };
105 /*++++++++++++++++++++++++++++++++++++++++++*/
106
107 /*----------------- connection slot -------------*/
108 class ConnectEntry
109 {
110 public:
111  char addr[256];
112  ConnectEntry(char *s) {strcpy(addr,s);};
113 };
114
115 /* ++++++++++++++++++++++++++++++++++++++++++  */
116
117 QApplication *app;
118
119
120 /* ---------------------------------------------------------- */
121 /*                 KERNEL CLASS DEFINITION                    */
122 /* ---------------------------------------------------------- */
123
124 class QKernel : public QFrame
125 {
126  Q_OBJECT
127 public:
128
129   QMultiLineEdit *desktop;                        
130   QMenuBar *bar;  
131   QPopupMenu *p,*p1,*p2;
132   char progdir[256];                              
133   int NodeNumber,ConType;
134   
135
136   QKernel();
137
138
139   virtual void resizeEvent( QResizeEvent *ev );
140
141   void WriteMessage(char* msg);
142   void InitMessage();
143
144
145 public slots:
146
147   void n_impl();
148   void Run_Prog();
149   void Edit();
150   void Help();
151   void SetOptions();
152   void AddAddress();
153   void DelAddress();
154   void LockConsole();
155   void UnlockConsole();
156   void MessageToNode();
157   void QuitProc();
158   void NetMessage();
159   void IntMessage(int);
160   void KillInterpreter();
161   void Disconnect();
162   void SetMessages();
163   void Connect();
164   void Info();
165
166 protected:
167   virtual void closeEvent ( QCloseEvent * e );
168
169 private:
170   QList<InterpEntry> Interpreters;         
171   QList<ConnectEntry> ConnectList;
172   QListBox *connections;
173   int Tasks;                            // number of working interpreters
174   int ActiveConnections;                // number of connected VLPs
175   bool LOCKED,synchro,wait_for_info;
176   char LockPasswd[25];
177   int lockid,unlockid,qid,cwid,
178   optid,prid,mid,msgid,toolsid,hid;
179   int net_sock;
180   int freeINTid;
181   QSocketNotifier *Net_Notify;
182   char HomeDir[255];
183   bool info_messages;
184   
185
186   void LoadConfig(char *);
187   void RunGraphModule(char*);
188   void RunNetModule();
189   InterpEntry *findINTbySocket(int);
190   InterpEntry *findINTbyID(int);
191   InterpEntry *RunIntModule(char *ss,int r);
192   void RemoteInstance(InterpEntry*,int);
193   void CloseInstances(InterpEntry*);
194   
195
196 };
197 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
198
199 void QKernel::closeEvent ( QCloseEvent * e ) {
200   e->ignore();
201 }
202
203 QKernel::QKernel()
204 {
205  QFont f("Helvetica",10,QFont::Bold);
206  QFont f1("Helvetica",10,QFont::Normal);
207  QFont f2("Times Roman",10,QFont::Normal);
208  QDir q(REMOTE_PATH);
209  char ss[255];
210
211  if (!q.exists())
212    {
213     sprintf(ss,"mkdir %s",REMOTE_PATH);
214     system(ss);
215     } 
216
217  info_messages=TRUE;
218  wait_for_info=FALSE;
219
220  setCaption("Virtual LOGLAN Processor");
221  setBackgroundColor(white);
222
223  bar = new QMenuBar(this);
224  bar->setFont(f); 
225  p = new QPopupMenu();
226  p->setFont(f2);
227  p->insertItem("Execute",this,SLOT(Run_Prog()));
228  p->insertItem("Kill",this,SLOT(KillInterpreter()));
229  prid = bar->insertItem("&Program",p);
230  p1 = new QPopupMenu();
231  p1->insertItem("Message",this,SLOT(MessageToNode()));
232  p1->insertSeparator();
233  p1->insertItem("Connect",this,SLOT(Connect()));
234  p1->insertItem("Disconnect",this,SLOT(Disconnect()));
235  p1->insertItem("Info",this,SLOT(Info()));
236  p1->setFont(f);
237  mid = bar->insertItem("&Machine",p1);
238
239  p2 = new QPopupMenu();
240  cwid = p2->insertItem("Editor",this,SLOT(Edit()));
241  hid = p2->insertItem("Help",this,SLOT(Help()));
242  p2->insertSeparator(); 
243  optid = p2->insertItem("Options",this,SLOT(SetOptions()));
244  msgid = p2->insertItem("Info messages",this,SLOT(SetMessages()));
245  p2->setItemChecked(msgid,TRUE);
246  p2->insertSeparator(); 
247  lockid = p2->insertItem("Lock console",this,SLOT(LockConsole()));
248  unlockid = p2->insertItem("Unlock console",this,SLOT(UnlockConsole()));
249  p2->setItemEnabled(unlockid,FALSE);
250  LOCKED = FALSE;
251  p2->setFont(f);
252  toolsid = bar->insertItem("&Tools",p2);
253
254  qid = bar->insertItem("&Quit",this,SLOT(QuitProc()));
255  p->setFont(f);
256
257  desktop = new QMultiLineEdit(this,"desktop");
258  desktop->setAutoUpdate(TRUE);
259  desktop->setReadOnly(TRUE);
260  desktop->setFont(f1);
261
262  resize(400,200);
263  Tasks = 0;
264  freeINTid = 1;
265  ActiveConnections = 0;
266  strcpy(LockPasswd,"");
267  LoadConfig("vlp.cfg");
268  RunNetModule();
269
270  Net_Notify = new QSocketNotifier(net_sock,QSocketNotifier::Read,this);
271  connect(Net_Notify,SIGNAL(activated(int)),this,SLOT(NetMessage()));
272
273 }
274
275
276 void QKernel::resizeEvent( QResizeEvent *ev )
277 {
278     QFrame::resizeEvent(ev);
279     if ( desktop )
280         desktop->setGeometry( 0,bar->height(), width(),  height() - bar->height() );
281 }
282
283
284
285
286 void QKernel::n_impl()
287 {
288  QMessageBox::information(this,"Function info","This function is not implemented yet...","Ok");
289 }
290
291
292 /* ###########     load configuration from file  ############# */
293
294 void QKernel::LoadConfig(char * fname)
295 {
296   config_t cfg;
297   config_setting_t *setting;
298   const char *str;
299
300   /* Hack for checking if file exists without using external libs.*/
301   FILE * file = fopen(fname, "rt");
302   if (!file) {
303     fprintf(stderr, "Error: Cannot load configuration file %s!\n", fname);
304     exit(3);
305   }
306   /* File exists, so file has been locked. Release it. */
307   
308   config_init(&cfg);
309   
310   /* Read the file. If there is an error, report it and exit. */
311   if(!config_read(&cfg, file))
312   {
313     fprintf(stderr, "%s! In file %s, line %d\n",
314         config_error_text(&cfg),
315         config_error_file(&cfg),
316         config_error_line(&cfg));
317     config_destroy(&cfg);
318     fclose(file);
319     exit(3);/* from original code. */
320   }
321
322   setting = config_lookup(&cfg, "node_number");
323   if(setting) {
324     NodeNumber = config_setting_get_int(setting);
325   }
326   else {
327     fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
328         "Warning",
329         fname,
330         "node_number");
331     config_destroy(&cfg);
332     fclose(file);
333     exit(3);
334   }
335   
336   setting = config_lookup(&cfg, "type");
337   if(setting) {
338     ConType = (strcmp(config_setting_get_string(setting), "explicit") == 0) ? 1 : 2;
339   }
340   else {
341     fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
342         "Warning",
343         fname,
344         "type");
345   }
346   
347   setting = config_lookup(&cfg, "host");
348   if(setting) {
349     switch(config_setting_type(setting)) {
350       case CONFIG_TYPE_STRING:/* TODO: Deprecated. Made for back compatibility. */
351         ConnectList.append(new ConnectEntry((char*)config_setting_get_string(setting)));
352         break;
353       case CONFIG_TYPE_ARRAY:
354         for (int i = 0; i < config_setting_length(setting); i++) {
355           ConnectList.append(new ConnectEntry((char*)config_setting_get_string_elem(setting, i)));
356         }
357         break;
358       default:
359         fprintf(stderr, "%s! In file %s, bad entry type for %s. Will not be read.\n",
360         "Error",
361         fname,
362         "host");
363     }
364   }
365   else {
366     fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
367         "Warning",
368         fname,
369         "host");
370   }
371   
372   setting = config_lookup(&cfg, "progdir");
373   if(setting){
374     strncpy(progdir, config_setting_get_string(setting), 256);
375   }
376   else {
377     fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
378         "Warning",
379         fname,
380         "progdir");
381   }
382   
383   setting = config_lookup(&cfg, "homedir");
384   if(setting) {
385     strncpy(HomeDir, config_setting_get_string(setting), 255);
386   }
387   else {
388     fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
389         "Warning",
390         fname,
391         "homedir");
392   }
393   
394   config_destroy(&cfg);
395   fclose(file);
396 }
397 /* +++++++++++++++++++++++++++++++++++++++++++++++ */
398
399
400 void QKernel::Run_Prog()
401 {
402  int i;
403  QString s(QFileDialog::getOpenFileName(progdir,"*.log",this));
404  if ( !s.isNull())
405  {
406     i = s.find(".log");
407     if (i>0)  s.remove(i,4);
408     RunIntModule((char*)s.ascii(),0);
409  }
410 }
411
412
413 void QKernel::Edit()
414 {
415  char cmd[255];
416  sprintf(cmd,"%s/modules/logedit %s %s %s %s %s %s &",HomeDir,HomeDir,
417  myargs[0],myargs[1],myargs[2],myargs[3],myargs[4]);
418  system(cmd);
419 }
420
421 void QKernel::Help()
422 {
423  char cmd[255];
424  sprintf(cmd,"%s/modules/loghelp %s/doc %s %s %s %s %s &",HomeDir,HomeDir,
425   myargs[0],myargs[1],myargs[2],myargs[3],myargs[4]);
426  system(cmd);
427 }
428
429
430 void QKernel::RunGraphModule(char *sk)
431 {
432  char cmd[255];
433
434      
435      sprintf(cmd,"%s/modules/loggraph %s %s %s %s %s %s",HomeDir,sk,
436       myargs[0],myargs[1],myargs[2],myargs[3],myargs[4]);
437      strcat(cmd," &");
438
439    if (system(cmd)!=0)
440       WriteMessage("Cannot connect GRAPH resources");
441    
442 }
443
444
445
446 void QKernel::RunNetModule()
447 {
448   struct sockaddr_un svr;
449  int len,on;
450  int sock;
451  char cmd[255];
452
453      
454       sprintf(cmd,"%s/modules/lognet %s %s %s %s %s %s",HomeDir,NPATH,
455        myargs[0],myargs[1],myargs[2],myargs[3],myargs[4]);
456       strcat(cmd," &");
457       
458       /* -------- socket for NET module -------- */
459       unlink(NPATH);
460       sock = socket(AF_UNIX,SOCK_STREAM,0);
461       bzero(&svr,sizeof(svr));
462       svr.sun_family = AF_UNIX;
463       strcpy(svr.sun_path,NPATH);
464       len = strlen(svr.sun_path)+sizeof(svr.sun_family);
465       bind(sock,(struct sockaddr*)&svr, len);      
466       listen(sock,5);
467
468      if ( system(cmd) == 0)
469      {
470       net_sock = accept(sock,(struct sockaddr*)0,(unsigned int*)0);
471       // close(sock); 
472       if (net_sock != 0)
473       {
474         WriteMessage("NETWORK successfully connected");
475         fcntl(net_sock,F_SETFL, O_NONBLOCK|fcntl(net_sock,F_GETFL,0));
476         on=1;
477         setsockopt(net_sock,IPPROTO_TCP,TCP_NODELAY,(char*)&on,sizeof(on)); 
478        }
479       else 
480       {
481       WriteMessage("Cannot connect NETWORK resources");
482       WriteMessage("Exiting...");
483       sleep(2);
484       QuitProc(); 
485       }
486    }/* system OK */
487       else 
488       {
489       WriteMessage("Cannot connect NETWORK resources");
490       WriteMessage("Exiting...");
491       sleep(2);
492       QuitProc(); 
493       }
494
495 }
496
497
498 void QKernel::Connect()
499 {
500  QDialog d(this,"",TRUE);
501  QLabel lab(&d,"IP Address:");
502  QLineEdit ed(&d,"");
503  QPushButton ob(&d,""),cb(&d,"");
504  MESSAGE m;
505         
506         d.setFont(QFont("Helvetica",12,QFont::Bold)); 
507         ob.setGeometry( 30, 60, 80, 30 );
508         ob.setText( "Ok" );
509         ob.setDefault(TRUE);
510         lab.setGeometry( 10, 10, 60, 30 );
511         lab.setText( "Address" );
512         ed.setGeometry( 70, 10, 140, 30 );
513         cb.setGeometry( 130, 60, 80, 30 );
514         cb.setText( "Cancel" );
515         d.resize( 240, 100 );
516         
517         connect(&ob,SIGNAL(clicked()),&d,SLOT(accept()));
518         connect(&cb,SIGNAL(clicked()),&d,SLOT(reject())); 
519   if (d.exec())
520   {
521     m.msg_type = MSG_NET;
522     m.param.pword[0] = NET_CONNECT_TO;
523     strcpy(m.param.pstr,ed.text());
524     write(net_sock,&m,sizeof(MESSAGE)); 
525    }
526     
527 }
528
529 void QKernel::Disconnect()
530 {
531  MESSAGE msg;
532
533  if (info_messages) WriteMessage("Disconnecting from virtual machine");
534  msg.msg_type = MSG_NET;
535  msg.param.pword[0] = NET_DISCONNECT;
536  write(net_sock,&msg,sizeof(MESSAGE));
537 }
538
539 void QKernel::QuitProc()
540 {
541  MESSAGE msg;
542
543 if ( QMessageBox::question(this,"Close VLP","Terminate VLP ?",QMessageBox::Yes,QMessageBox::No,0) == QMessageBox::No ) return;
544 if (!LOCKED)
545 {
546   /* 
547    msg.msg_type = MSG_NET;
548    msg.param.pword[0] = NET_DISCONNECT;
549    write(net_sock,&msg,sizeof(MESSAGE));*/
550  
551     
552     delete Net_Notify;
553   
554     msg.msg_type = MSG_NET;
555     msg.param.pword[0] = NET_EXIT;
556     write(net_sock,&msg,sizeof(MESSAGE));
557   //  ::close(net_sock);
558
559  app->quit();
560 }
561 }
562
563
564
565
566 void QKernel::AddAddress()
567 {
568  QDialog d(this,"",TRUE);
569  QLabel lab(&d,"IP Address:");
570  QLineEdit ed(&d,"");
571  QPushButton ob(&d,""),cb(&d,"");
572         
573  if (connections)
574  {
575         ob.setGeometry( 30, 60, 80, 30 );
576         ob.setText( "Ok" );
577         ob.setDefault(TRUE);
578         lab.setGeometry( 10, 10, 60, 30 );
579         lab.setText( "Address" );
580         ed.setGeometry( 70, 10, 140, 30 );
581         cb.setGeometry( 130, 60, 80, 30 );
582         cb.setText( "Cancel" );
583         d.resize( 240, 100 );
584         connect(&ob,SIGNAL(clicked()),&d,SLOT(accept()));
585         connect(&cb,SIGNAL(clicked()),&d,SLOT(reject())); 
586   if (d.exec())
587     if (strcmp(ed.text(),"")!=0)
588     {
589       connections->insertItem(ed.text());
590      }
591  }
592 }
593
594 void QKernel::DelAddress()
595 {
596  if (connections)
597  {
598   if (connections->currentItem()!=-1)
599    connections->removeItem(connections->currentItem());
600  }
601 }
602
603
604
605 void QKernel::MessageToNode()
606 {
607   QDialog *dlg;
608   QLineEdit *nodenr;
609   MESSAGE m;
610         
611
612         dlg = new QDialog(this,"Message",TRUE);
613
614         nodenr = new QLineEdit(dlg,"number"); 
615         nodenr->setGeometry( 90, 10, 50, 30 );
616         nodenr->setText("");
617
618         QLabel* tmpQLabel;
619         tmpQLabel = new QLabel( dlg, "Label_1" );
620         tmpQLabel->setGeometry( 10, 10, 77, 30 );
621         tmpQLabel->setText( "Node number:" );
622
623         tmpQLabel = new QLabel( dlg, "Label_2" );
624         tmpQLabel->setGeometry( 10, 50, 70, 30 );
625         tmpQLabel->setText( "Message:" );
626
627         QLineEdit* msg;
628         msg = new QLineEdit( dlg, "LineEdit_1" );
629         msg->setGeometry( 80, 60, 330, 30 );
630         msg->setText( "" );
631
632         QPushButton* ob,*cb;
633         ob = new QPushButton( dlg, "PushButton_1" );
634         ob->setGeometry(  230, 10, 80, 30 );
635         ob->setText( "Send" );
636         ob->setDefault(TRUE);
637         cb = new QPushButton( dlg, "PushButton_2" );
638         cb->setGeometry( 330, 10, 80, 30 );
639         cb->setText( "Cancel" );
640         dlg->resize( 430, 110 );
641         connect(ob,SIGNAL(clicked()),dlg,SLOT(accept()));
642         connect(cb,SIGNAL(clicked()),dlg,SLOT(reject())); 
643         dlg->setCaption("Send message to node");
644
645    if (dlg->exec())
646    {
647      m.msg_type = MSG_NET;
648      m.param.pword[0] = NET_PROPAGATE;
649      m.param.pword[1] = MSG_VLP;
650      m.param.pword[2] = NodeNumber;
651      m.param.pword[4] = atoi(nodenr->text());
652      m.param.pword[6] = VLP_WRITE;
653      strcpy(m.param.pstr,msg->text());
654      write(net_sock,&m,sizeof(MESSAGE));
655   }
656 }
657
658 void QKernel::KillInterpreter()
659 {
660   QDialog *dlg;
661   QLineEdit *nodenr;
662   MESSAGE m;
663   InterpEntry *pom;
664         
665  dlg = new QDialog(this,"Message",TRUE);
666
667  nodenr = new QLineEdit(dlg,"number"); 
668  nodenr->setGeometry( 90, 10, 50, 30 );
669  nodenr->setText("");
670
671  QLabel* tmpQLabel;
672  tmpQLabel = new QLabel( dlg, "Label_1" );
673  tmpQLabel->setGeometry( 10, 10, 77, 30 );
674  tmpQLabel->setText( "Interp. ID:" );
675  QPushButton* ob,*cb;
676         ob = new QPushButton( dlg, "PushButton_1" );
677         ob->setGeometry(  160, 10, 80, 30 );
678         ob->setText( "Kill" );
679         ob->setDefault(TRUE);
680         cb = new QPushButton( dlg, "PushButton_2" );
681         cb->setGeometry( 260, 10, 80, 30 );
682         cb->setText( "Cancel" );
683         dlg->resize( 360, 50 );
684         connect(ob,SIGNAL(clicked()),dlg,SLOT(accept()));
685         connect(cb,SIGNAL(clicked()),dlg,SLOT(reject())); 
686         dlg->setCaption("Kill interpreter");
687  if (dlg->exec())
688  {
689
690    m.msg_type = MSG_INT;
691    m.param.pword[0] = INT_KILL;
692    pom = findINTbyID(atoi(nodenr->text()));
693    if  (pom!=NULL)
694    {
695     if (!(pom->remote))
696     write(pom->sock,&m,sizeof(MESSAGE));
697     else WriteMessage("This is a remote instance of a program!");
698    }
699     else WriteMessage("Interpreter not found");
700   
701  }
702
703 }
704
705
706
707 void QKernel::NetMessage()
708 {
709  MESSAGE msg;
710  int cnt;
711  char ss[255];
712  InterpEntry *pom;
713
714  cnt = read(net_sock,&msg,sizeof(MESSAGE));
715  if ( (cnt>0) && (msg.msg_type==MSG_NET))
716  {
717    switch(msg.param.pword[0])
718    {
719    case NET_CSWRITELN: WriteMessage(msg.param.pstr);break;
720    case NET_PROPAGATE: 
721                   switch(msg.param.pword[1])
722                     {
723                      case MSG_INT:
724                     /*  pom = find_link_by_ID(msg.param.pword[5]);
725                      msg.msg_type = MSG_NET;
726                      msg.param.pword[0] = NET_PROPAGATE;   
727                      send_int(pom,&msg);*/
728                      break;
729                      case MSG_VLP:
730                           switch(msg.param.pword[6])
731                           {
732                            case VLP_WRITE:
733                                    QApplication::beep();
734                                    WriteMessage(CharLine);
735                                    WriteMessage("### Incoming Messsage ###");  
736                                    sprintf(ss,"Mesg from Node %d: %s",msg.param.pword[2],msg.param.pstr);
737                                    WriteMessage(ss);
738                                    WriteMessage(CharLine);
739                                    break;
740                            case VLP_REMOTE_INSTANCE:
741                             sprintf(ss,"%s/%s",REMOTE_PATH,msg.param.pstr); 
742                             if (info_messages)
743                             { 
744                             WriteMessage("Running program:");
745                             WriteMessage(ss);  
746                             }
747                             pom = RunIntModule(ss,1);
748                             if (pom!=NULL)
749                             {
750                             pom->p_ctx.node = msg.param.pword[2];
751                             pom->p_ctx.program_id = msg.param.pword[7];
752                             pom->RInstances[msg.param.pword[2]] = msg.param.pword[7];
753                             }
754                            break;
755                           case VLP_CLOSE_INSTANCE:
756                              msg.msg_type = MSG_INT;
757                              msg.param.pword[0] = INT_CLOSE_INSTANCE;
758                              pom = findINTbyID(msg.param.pword[7]);
759                              if (pom!=NULL)
760                              {
761                                write(pom->sock,&msg,sizeof(MESSAGE));
762                                MESSAGE m1;
763                                m1.msg_type = MSG_VLP;
764                                m1.param.pword[0] = VLP_INTERPRETER_DOWN;
765                                m1.param.pword[1] = pom->ID;
766                                write(net_sock,&m1,sizeof(MESSAGE));
767                                } else WriteMessage("Instance not found"); 
768                            break; 
769                           } /* VLP switch */        
770                                       
771                           }/* switch */
772                        break;
773    case NET_CONNECTIONS: ActiveConnections = msg.param.pword[1];
774                          WriteMessage(msg.param.pstr);
775                          if (!synchro) synchro=TRUE;
776                          break;
777    case NET_INFO:
778                 if (wait_for_info) 
779                 {
780                  QString poms,poms1,poms2;
781                  poms.sprintf("%s",msg.param.pstr);
782                  while (poms.length()>0)
783                  {
784                   cnt=poms.find(';');
785                   if (cnt!=-1)
786                   { poms1=poms.left(cnt);
787                     poms=poms.right(poms.length()-cnt-1);
788                     cnt=poms1.find('=');
789                     if (cnt!=-1)
790                      {
791                        poms2=poms1.left(cnt);
792                        poms1=poms1.right(poms1.length()-cnt-1);
793                        sprintf(ss,"Node: %s Addr: %s",poms2.data(),poms1.data());
794                        WriteMessage(ss); 
795                       }
796                    } 
797                  }
798                 } 
799                 break; 
800    case NET_INFO_END:wait_for_info=FALSE;
801                      WriteMessage(CharLine);
802                      break;
803    } /* switch */
804   }
805  
806 }
807
808
809
810
811 void QKernel::IntMessage(int sock)
812 {
813  MESSAGE msg;
814  int cnt;
815  InterpEntry *e;
816
817  cnt = read(sock,&msg,sizeof(MESSAGE));
818  e = findINTbySocket(sock);
819  if ( (cnt>0) && (e!=NULL))
820  {
821  switch (msg.msg_type)
822  { 
823    case MSG_GRAPH:
824                   if (msg.param.pword[0]==GRAPH_ALLOCATE)
825                   {
826                     RunGraphModule(msg.param.pstr);
827                     }  
828                   break;
829    case MSG_NET:
830      write(net_sock,&msg,sizeof(MESSAGE));break;    
831    case MSG_VLP:
832       switch(msg.param.pword[0])
833        {
834          case VLP_REMOTE_INSTANCE_PLEASE:
835            RemoteInstance(e,msg.param.pword[2]);
836          break;
837         }/* switch */
838        break;  
839    case MSG_INT:
840        switch(msg.param.pword[0]){
841            case INT_EXITING:
842              {
843                char ss[255];
844                
845                MESSAGE m;
846                m.msg_type = MSG_VLP;
847                m.param.pword[0] = VLP_INTERPRETER_DOWN;
848                m.param.pword[1] = e->ID;
849                write(net_sock,&m,sizeof(MESSAGE));
850                if (e->remote==0) CloseInstances(e);
851                delete e->notify;
852                ::close(e->sock);   
853                Interpreters.remove(e);
854                delete e;
855                if (info_messages)
856                {
857                sprintf(ss,"%s : End of program execution",msg.param.pstr);
858                WriteMessage(ss);
859                }
860               };break;
861             case INT_CTX_REQ:
862                 
863                  msg.msg_type = MSG_INT;
864                  msg.param.pword[0] = INT_CTX;
865                  msg.param.pword[1] = NodeNumber;
866                  msg.param.pword[2] = e->ID;
867                 if (e->remote)
868                  {
869                    msg.param.pword[3] = e->p_ctx.node;
870                    msg.param.pword[4] = e->p_ctx.program_id;
871                   }
872                  write(sock,&msg,sizeof(MESSAGE)); 
873                  break;
874              };break; /* switch param.pword[0] */
875  } /* switch type */
876  } /* if */
877 }
878
879
880 void QKernel::WriteMessage(char *msg)
881 {
882  int x,y;
883  
884  desktop->getCursorPosition(&x,&y);
885  if (x>100) desktop->clear();
886  desktop->setReadOnly(FALSE);
887  desktop->append(msg);
888  desktop->setReadOnly(TRUE);
889  desktop->setCursorPosition(desktop->numLines(),1);
890  desktop->repaint();
891  if (desktop->numLines()>100) desktop->clear();
892 }
893
894 void QKernel::SetMessages()
895 {
896
897  if (p2!=NULL)
898  {
899  if ( p2->isItemChecked(msgid))
900  {
901   p2->setItemChecked(msgid,FALSE);
902   info_messages=FALSE;
903  }
904  else
905  {
906   p2->setItemChecked(msgid,TRUE);  
907   info_messages=TRUE;
908  }
909 } // !=NULL 
910 // bar->repaint();
911 }
912
913 void QKernel::SetOptions()
914 {
915   QDialog dlg(this,"Options",TRUE);
916   ConnectEntry *e;
917   unsigned int i;
918
919
920         QLineEdit* progs;
921         progs = new QLineEdit( &dlg, "progs" );
922         progs->setGeometry( 150, 20, 180, 30 );
923         progs->setText(progdir);
924
925         QLabel* tmpQLabel;
926         tmpQLabel = new QLabel( &dlg, "Label_1" );
927         tmpQLabel->setGeometry( 30, 20, 120, 30 );
928         tmpQLabel->setText( "Programs directory" );
929
930         QFrame* tmpQFrame;
931         tmpQFrame = new QFrame( &dlg, "Frame_2" );
932         tmpQFrame->setGeometry( 10, 60, 380, 30 );
933         tmpQFrame->setFrameStyle( 52 );
934
935         tmpQLabel = new QLabel( &dlg, "Label_2" );
936         tmpQLabel->setGeometry( 10, 80, 340, 30 );
937         tmpQLabel->setText( "Virtual Processor properties (activated after restarting VLP):" );
938
939         QLineEdit *nn;
940         char nns[256];
941         nn = new QLineEdit( &dlg, "LineEdit_2" );
942         nn->setGeometry( 110, 110, 40, 30 );
943         sprintf(nns,"%d",NodeNumber);
944         nn->setText(nns);
945
946         tmpQLabel = new QLabel( &dlg, "Label_3" );
947         tmpQLabel->setGeometry( 20, 110, 90, 30 );
948         tmpQLabel->setText( "Node number:" );
949
950         QRadioButton *exp,*reg;
951         exp = new QRadioButton( &dlg, "RadioButton_3" );
952         exp->setGeometry( 30, 170, 100, 30 );
953         exp->setText( "Explicit" );
954         exp->setChecked( TRUE );
955
956         reg = new QRadioButton( &dlg, "RadioButton_4" );
957         reg->setGeometry( 30, 200, 100, 30 );
958         reg->setText( "Registration" );
959         reg->setEnabled(FALSE);
960
961         connections = new QListBox( &dlg, "ListBox_1" );
962         connections->setGeometry( 170, 140, 130, 100 );
963         e = ConnectList.first();
964         while (e!=NULL)
965         {
966          connections->insertItem(e->addr);
967          e = ConnectList.next();
968          }
969
970         tmpQLabel = new QLabel( &dlg, "Label_5" );
971         tmpQLabel->setGeometry( 170, 110, 100, 30 );
972         tmpQLabel->setText( "Connection list:" );
973
974         QPushButton* addbtn,*delbtn,*okbtn,*cancelbtn;
975         addbtn = new QPushButton( &dlg, "PushButton_1" );
976         addbtn->setGeometry( 310, 150, 60, 30 );
977         addbtn->setText( "Add" );
978         delbtn = new QPushButton( &dlg, "PushButton_2" );
979         delbtn->setGeometry( 310, 200, 60, 30 );
980         delbtn->setText( "Del" );
981         connect(addbtn,SIGNAL(clicked()),this,SLOT(AddAddress()));
982         connect(delbtn,SIGNAL(clicked()),this,SLOT(DelAddress()));
983         okbtn = new QPushButton( &dlg, "PushButton_3" );
984         okbtn->setGeometry( 80, 260, 100, 30 );
985         okbtn->setText( "Ok" );
986         okbtn->setDefault(TRUE);
987         cancelbtn = new QPushButton( &dlg, "PushButton_4" );
988         cancelbtn->setGeometry( 210, 260, 100, 30 );
989         cancelbtn->setText( "Cancel" );
990         connect(okbtn,SIGNAL(clicked()),&dlg,SLOT(accept()));
991         connect(cancelbtn,SIGNAL(clicked()),&dlg,SLOT(reject()));        
992         QButtonGroup* group;
993         group = new QButtonGroup( &dlg, "ButtonGroup_1" );
994         group->setGeometry( 20, 150, 120, 90 );
995         group->setTitle( "Connection type" );
996         group->setAlignment( 1 );
997         group->lower();
998         group->insert(exp,1);
999         group->insert(reg,2);  
1000
1001         dlg.resize( 400, 310 );
1002         if (dlg.exec())
1003    {
1004
1005     config_t cfg;
1006     config_setting_t *root, *setting;
1007     config_init(&cfg);
1008
1009     root = config_root_setting(&cfg);
1010     
1011     setting = config_setting_add(root, "progdir", CONFIG_TYPE_STRING);
1012     config_setting_set_string(setting, progs->text().ascii());
1013     strcpy(progdir,progs->text());
1014
1015     setting = config_setting_add(root, "node_number", CONFIG_TYPE_INT);
1016     config_setting_set_int(setting, atoi(nn->text()));
1017     
1018     setting = config_setting_add(root, "homedir", CONFIG_TYPE_STRING);
1019     config_setting_set_string(setting, HomeDir);
1020     
1021     setting = config_setting_add(root, "type", CONFIG_TYPE_STRING);
1022     if ( exp->isChecked())
1023     {
1024       config_setting_set_string(setting, "explicit");
1025       
1026       config_setting_t *hosts = NULL;
1027       hosts = config_setting_add(root, "host", CONFIG_TYPE_ARRAY);
1028       for(i=0;i<connections->count();i++) {
1029         setting = config_setting_add(hosts, NULL, CONFIG_TYPE_STRING);
1030         config_setting_set_string(setting, connections->text(i).ascii());
1031       }
1032     }
1033     else {
1034       config_setting_set_string(setting, "register");
1035     }
1036     
1037     if(!config_write_file(&cfg, "vlp.cfg")) {
1038       fprintf(stderr, "Error while writing to file: %s.\n", "vlp.cfg");
1039     }
1040     config_destroy(&cfg);
1041     };
1042 }
1043
1044
1045 void QKernel::LockConsole()
1046 {
1047  QDialog d(this,"Enter password",TRUE);
1048  QLabel lab(&d,"Password");
1049  QLineEdit ed(&d,"");
1050  QPushButton ob(&d,""),cb(&d,"");
1051         
1052         d.setCaption("Lock console"); 
1053         ob.setGeometry( 30, 60, 80, 30 );
1054         ob.setText( "Ok" );
1055         ob.setDefault(TRUE);
1056         lab.setGeometry( 10, 10, 60, 30 );
1057         lab.setText( "Password:" );
1058         ed.setGeometry( 70, 10, 140, 30 );
1059         ed.setEchoMode(QLineEdit::Password);
1060         cb.setGeometry( 130, 60, 80, 30 );
1061         cb.setText( "Cancel" );
1062         d.resize( 240, 100 );
1063         connect(&ob,SIGNAL(clicked()),&d,SLOT(accept()));
1064         connect(&cb,SIGNAL(clicked()),&d,SLOT(reject())); 
1065  
1066    if (d.exec())
1067      if (strcmp(ed.text(),"")!=0)
1068     {
1069       strcpy(LockPasswd,ed.text());
1070       lab.setText("Retype:");
1071       ed.setText("");
1072       if (d.exec())
1073       {
1074         if (strcmp(ed.text(),LockPasswd)==0)
1075         {
1076           bar->setItemEnabled(qid,FALSE);
1077           bar->setItemEnabled(prid,FALSE);
1078           bar->setItemEnabled(mid,FALSE);
1079           p2->setItemEnabled(unlockid,TRUE);
1080           p2->setItemEnabled(lockid,FALSE);
1081           p2->setItemEnabled(cwid,FALSE);
1082           p2->setItemEnabled(optid,FALSE);
1083           bar->repaint();
1084           WriteMessage("CONSOLE LOCKED");
1085           LOCKED = TRUE;
1086         }
1087          else
1088              {
1089                 QMessageBox msg(this);
1090                 msg.setText("Not matching!");
1091                 msg.setButtonText(0,"Close");
1092                 msg.show();
1093
1094              }   
1095        }
1096        else strcpy(LockPasswd,"");
1097     }
1098 }
1099
1100 void QKernel::UnlockConsole()
1101 {
1102  QDialog d(this,"Enter password",TRUE);
1103  QLabel lab(&d,"Password");
1104  QLineEdit ed(&d,"");
1105  QPushButton ob(&d,""),cb(&d,"");
1106
1107         ob.setGeometry( 30, 60, 80, 30 );
1108         ob.setText( "Ok" );
1109         ob.setDefault(TRUE);
1110         lab.setGeometry( 10, 10, 60, 30 );
1111         lab.setText( "Password:" );
1112         ed.setGeometry( 70, 10, 140, 30 );
1113         ed.setEchoMode(QLineEdit::Password);
1114         cb.setGeometry( 130, 60, 80, 30 );
1115         cb.setText( "Cancel" );
1116         d.resize( 240, 100 );
1117         connect(&ob,SIGNAL(clicked()),&d,SLOT(accept()));
1118         connect(&cb,SIGNAL(clicked()),&d,SLOT(reject())); 
1119
1120  if (d.exec())
1121  {
1122    if (strcmp(ed.text(),LockPasswd)==0)
1123    {
1124           bar->setItemEnabled(qid,TRUE);
1125           bar->setItemEnabled(prid,TRUE);
1126           bar->setItemEnabled(mid,TRUE);
1127           p2->setItemEnabled(unlockid,FALSE);
1128           p2->setItemEnabled(lockid,TRUE);
1129           p2->setItemEnabled(cwid,TRUE);
1130           p2->setItemEnabled(optid,TRUE);
1131           bar->repaint();
1132           WriteMessage("CONSOLE UNLOCKED");
1133           LOCKED = FALSE;         
1134    }
1135    else
1136           {
1137                 QMessageBox msg(this);
1138                 msg.setText("Wrong password!");
1139                 msg.setButtonText(0,"Close");
1140                 msg.show();
1141
1142              }      
1143  }
1144 }
1145
1146 void QKernel::InitMessage()
1147 {
1148  WriteMessage("\n Virtual LOGLAN Processor - ver 1.9: READY \n");
1149 }
1150
1151
1152
1153 InterpEntry *QKernel::findINTbySocket(int _id)
1154 {
1155  InterpEntry *pom;
1156  pom = Interpreters.first();
1157  while (pom!=NULL)
1158  {
1159   if (pom->sock == _id) break;
1160   pom = Interpreters.next();
1161  }
1162  return(pom);
1163 }
1164
1165 InterpEntry *QKernel::findINTbyID(int _id)
1166 {
1167  InterpEntry *pom;
1168  pom = Interpreters.first();
1169  while (pom!=NULL)
1170  {
1171   if (pom->ID == _id) break;
1172   pom = Interpreters.next();
1173  }
1174  return(pom);
1175 }
1176
1177
1178 /* ------------------ Connect INT module -----------------*/
1179
1180 InterpEntry *QKernel::RunIntModule(char *ss, int r)
1181 {
1182  char a[256],b[255];
1183  struct sockaddr_un svr;
1184  int len,sock,i,on;
1185  int newint=-1;
1186  char cmd[255];
1187  FILE *cf;
1188  MESSAGE msg;
1189  InterpEntry *newINT;
1190  
1191
1192
1193  newINT = NULL;
1194  
1195  strcpy(a,ss);
1196  strcat(a,".ccd");
1197  cf = fopen(a,"r");
1198  if (cf == NULL) {WriteMessage("File not found: no .ccd file");return(NULL);}
1199  fclose(cf);
1200  
1201  strcpy(a,ss);
1202  strcat(a,".pcd");
1203  cf = fopen(a,"r");
1204  if (cf == NULL) {WriteMessage("File not found: no .pcd file");return(NULL);}
1205  fclose(cf);
1206  
1207  newINT = new InterpEntry;
1208  for(i=0;i<MAXINSTANCES;i++) newINT->RInstances[i]=-1;
1209
1210  strcpy(b,rindex(ss,'/'));
1211  for(i=0;i<strlen(b);i++) 
1212       b[i] = b[i+1];
1213  if (info_messages)
1214  {
1215  sprintf(a,"%s : Start execution",b);
1216  WriteMessage(a); 
1217  }
1218
1219  newint = freeINTid; freeINTid++;
1220  newINT->ID = newint;
1221  strcpy(newINT->shortname,b);
1222  strcpy(newINT->fullname,ss);
1223     
1224  sprintf(a,"%s%d",IPATH,newint);
1225  sprintf(cmd,"%s/modules/logint %s %s",HomeDir,a,ss);
1226  if (r) strcat(cmd," r");
1227  sprintf(b," %s %s %s %s %s",myargs[0],myargs[1],myargs[2],myargs[3],myargs[4]);
1228  strcat(cmd,b);
1229  strcat(cmd," &");
1230   
1231
1232     sock = socket(AF_UNIX,SOCK_STREAM,0);
1233     unlink(a);
1234     bzero(&svr, sizeof(svr));
1235     svr.sun_family = AF_UNIX;
1236     strcpy(svr.sun_path,a);
1237     len = strlen(svr.sun_path)+sizeof(svr.sun_family);
1238     bind(sock,(struct sockaddr*)&svr, len);
1239     listen(sock,5);
1240     system(cmd); 
1241     newINT->sock = accept(sock,(struct sockaddr*)0,(unsigned int *)0);
1242     //::close(sock);
1243
1244          
1245  if (newINT->sock>0) 
1246 {
1247
1248    fcntl(newINT->sock,F_SETFL,
1249       O_NONBLOCK|fcntl(newINT->sock,F_GETFL,0));
1250    on=1; 
1251    setsockopt(newINT->sock,IPPROTO_TCP,TCP_NODELAY,(char*)&on,sizeof(on)); 
1252    if (r) newINT->remote = 1;else newINT->remote=0; 
1253   
1254    bzero(&msg,sizeof(MESSAGE));
1255    msg.msg_type = MSG_VLP;
1256    msg.param.pword[0] = VLP_REGINT;
1257    msg.param.pword[1] = newINT->ID;
1258    sprintf(msg.param.pstr,"logi%d.net",newint);
1259    write(net_sock,&msg,sizeof(MESSAGE)); 
1260  
1261    Interpreters.append(newINT);
1262    newINT->notify = new QSocketNotifier(newINT->sock,QSocketNotifier::Read);
1263    connect(newINT->notify,SIGNAL(activated(int)),this,SLOT(IntMessage(int)));
1264    if (info_messages) WriteMessage("INTERPRETER successfully connected");  
1265    
1266 }
1267  else WriteMessage("Cannot connect interpreter");
1268  
1269  return(newINT);    
1270
1271 }
1272
1273 /* ---------------------------------------------------------*/
1274 /*            Allocate remote instance                      */
1275
1276 void QKernel::RemoteInstance(InterpEntry *interp, int on)
1277 {
1278  MESSAGE m;
1279  char s[255];
1280  
1281  
1282  m.msg_type = MSG_NET;
1283  m.param.pword[0] = NET_NODE_EXIST;
1284  m.param.pword[1] = on;
1285  m.param.pword[2] = interp->ID;
1286  write(net_sock,&m,sizeof(MESSAGE));
1287  bzero(&m,sizeof(MESSAGE));
1288  while( (m.msg_type!=MSG_NET) && (m.param.pword[0]!=NET_NODE_EXIST) )
1289   read(net_sock,&m,sizeof(MESSAGE));
1290  
1291 if (m.param.pword[1]==1) /* means node exists */
1292 {
1293  m.msg_type = MSG_NET;
1294  m.param.pword[0] = NET_TRANSMIT_CODE;
1295  m.param.pword[1] = interp->ID;
1296  m.param.pword[2] = on;
1297  strcpy(m.param.pstr,interp->fullname);
1298  write(net_sock,&m,sizeof(MESSAGE));
1299  
1300  Net_Notify->setEnabled(FALSE);
1301  while ( (m.msg_type != MSG_NET) || (m.param.pword[0]!=NET_TRANSMITTED) )
1302  read(net_sock,&m,sizeof(MESSAGE));
1303
1304
1305  m.msg_type = MSG_NET;
1306  m.param.pword[0] = NET_PROPAGATE;
1307  m.param.pword[1] = MSG_VLP;
1308  m.param.pword[2] = NodeNumber;
1309  m.param.pword[3] = 0;
1310  m.param.pword[4] = on;
1311  m.param.pword[5] = 0;
1312  m.param.pword[6] = VLP_REMOTE_INSTANCE;
1313  m.param.pword[7] = interp->ID;
1314  strcpy(m.param.pstr,interp->shortname);
1315  write(net_sock,&m,sizeof(MESSAGE));
1316  
1317  read(net_sock,&m,sizeof(MESSAGE));
1318  while (1)
1319  {
1320    if ( (m.param.pword[0]==NET_PROPAGATE) && (m.param.pword[6] == VLP_REMOTE_INSTANCE_OK))
1321    {
1322     interp->RInstances[on] = m.param.pword[7];
1323     break;
1324    }  
1325   read(net_sock,&m,sizeof(MESSAGE));  
1326  }
1327
1328  Net_Notify->setEnabled(TRUE);
1329
1330  /*bzero(&m,sizeof(MESSAGE));*/
1331  m.msg_type = MSG_VLP;
1332  m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1333  m.param.pword[1] = interp->RInstances[on];
1334  write(interp->sock,&m,sizeof(MESSAGE));
1335 }
1336  else /* There is no such a node! */
1337 {
1338  sprintf(s,"Warning: Node number %d not found!",on); 
1339  WriteMessage(s);
1340  WriteMessage("Allocating O-process on the local node");
1341  bzero(&m,sizeof(MESSAGE));
1342  m.msg_type = MSG_VLP;
1343  m.param.pword[0] = VLP_REMOTE_INSTANCE_HERE;
1344  m.param.pword[1] = interp->ID;
1345  write(interp->sock,&m,sizeof(MESSAGE));
1346 }
1347 }
1348
1349
1350 /*-----------------------------------------------*/
1351 /*           Close all remote instances         */
1352
1353 void QKernel::CloseInstances(InterpEntry *e)
1354 {
1355  MESSAGE msg;
1356  int i;
1357
1358  if (info_messages)  WriteMessage("Closing remote instances");
1359  for(i=0;i<MAXINSTANCES;i++)
1360   if (e->RInstances[i]>=0)
1361  {
1362   msg.msg_type = MSG_NET;
1363   msg.param.pword[0] = NET_PROPAGATE;
1364   msg.param.pword[1] = MSG_VLP;
1365   msg.param.pword[2] = NodeNumber;
1366   msg.param.pword[4] = i;
1367   msg.param.pword[6] = VLP_CLOSE_INSTANCE;
1368   msg.param.pword[7] = e->RInstances[i];
1369   write(net_sock,&msg,sizeof(MESSAGE));
1370   }
1371 }
1372
1373
1374 void QKernel::Info()
1375 {
1376  MESSAGE m;
1377
1378  WriteMessage(CharLine);
1379  WriteMessage("### Virtual Machine Information ###");
1380  m.msg_type = MSG_NET;
1381  m.param.pword[0]=NET_GET_INFO;
1382  write(net_sock,&m,sizeof(MESSAGE));
1383  wait_for_info = TRUE;
1384 }
1385
1386 #include "kernel.moc"
1387
1388 int main( int argc, char **argv )
1389 {
1390     int i;
1391     for(i=0;i<5;i++) strcpy(myargs[i],"");
1392     for(i=1;i<argc;i++) strcpy(myargs[i-1],argv[i]);
1393     
1394     app = new QApplication(argc,argv);
1395     app->setStyle(new QWindowsStyle());
1396     QKernel   draw;
1397     app->setMainWidget( &draw);
1398     draw.show();
1399     draw.InitMessage();
1400     return app->exec();
1401 }