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