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