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