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