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