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