Added upstream version.
[vlp.git] / int / cint.c
1  
2
3 #include "depend.h"
4 #include "genint.h"
5 #include "int.h"
6 #include "process.h"
7 #include "intproto.h"
8 #include "socu.h"
9 #include <fcntl.h>
10 #include <sys/stat.h>
11 #include <sys/time.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <errno.h>
15 #include <netdb.h>
16
17
18 #ifndef NO_PROTOTYPES
19 static void load(char *);
20 static void initiate(int,char **);
21 int main(int,char **);
22 #else
23 static void load();
24 static void initiate();
25 int main();
26 #endif
27
28
29 int internal_sock,graph_sock,net_sock,connected=0;
30 struct sockaddr_un svr;
31 int GraphRes=-1;
32 char ProgName[255],mygname[80], gname[80],mykname[80], nname[80], mynname[80];
33 fd_set DirSet;
34 int maxDirSet;
35
36 ctx_struct my_ctx;
37 ctx_struct parent_ctx;
38
39 int RInstance[255]; /* IDs of remote instances */
40 int DirConn[255];   /* Direct connection channels */
41
42 /* graphic vars */
43 int fcol, bcol, curx=0, cury=0;
44
45
46
47 /* Macro to decode addressing modes : */
48 #define getargument(a, argnr)                                       \
49     switch (eop->args[ argnr ])                                     \
50     {                                                               \
51         case GLOBAL     : a = M[ ic++ ];             break;         \
52         case LOCAL      : a = c1+M[ ic++ ];          break;         \
53         case TEMPLOCAL  : a = c2+M[ ic++ ];          break;         \
54         case REMOTE     : a = M[ M[ ic+1 ] ]+M[ ic ];  ic+=2; break;\
55         case INDIRECT   : a = M[ M[ ic++ ] ];                 break;\
56         case IMMEDIATE  : a = ic++;                           break;\
57         case CONSTANT  : a = M[ ic++ ];                       break;\
58         case DOTACCESS : a = M[ display+M[ ic+1 ] ]+M[ ic ];  ic += 2; break;\
59         case NOARGUMENT : return;                          \
60     }
61
62
63 static void load(_filename)     /* Load code and prototypes from file */
64    char *_filename;
65 {
66     FILE *fp;
67     char *cp;
68     word n, left;
69     char filename[100]; /* should suffice on all systems */
70
71     strcpy( filename, _filename );
72     M = mallocate(memorysize+1);        /* allocate main memory array */
73     if (M == NULL) abend("Memory size too large (use /m option)\n");
74
75     addext(filename, ".ccd");
76     if ((fp = fopen(filename, BINARYREAD)) == NULL)
77         {
78            fprintf(stderr,"Cannot open .ccd file\n");
79            endrun(10);
80          };
81
82     ic = 0;              /* read static data and code */
83     left = memorysize+1;               /* from .ccd file */
84     do
85     {
86         if (left == 0) abend("Memory size too small (use /m option)\n");
87         n = min(IOBLOCK/sizeof(word), left);
88         n = fread((char *) &M[ ic ], sizeof(word), (int) n, fp);
89         ic += n;
90         left -= n;
91     } while (n != 0);      /* now ic = number of words read */
92
93     fclose(fp);
94     /* Get various addresses passed by GENERATOR */
95     ipradr    = M[ ic-5 ];           /* primitive type desctriptions */
96     temporary = M[ ic-4 ];           /* global temporary variables */
97     strings   = M[ ic-3 ];           /* string constants */
98     lastprot  = M[ ic-2 ];           /* last prototype number */
99     freem     = M[ ic-1 ];           /* first free word in memory */
100
101     /* Read prototypes from .pcd file */
102     addext(filename, ".pcd");
103     if ((fp = fopen(filename, BINARYREAD)) == NULL)
104        {
105          fprintf(stderr,"Cannot open .pcd file\n");
106          endrun(10); 
107         }
108     for (n = MAINBLOCK;  n <= lastprot;  n++ )
109     {
110         cp = ballocate(sizeof(protdescr));
111         if (cp == NULL) abend("Memory size too large (use /m option)\n");
112         prototype[ n ] = (protdescr *) cp;
113         if (fread(cp, sizeof(protdescr), 1, fp) != 1)
114             abend("Cannot read .pcd file\n");
115     }
116     fclose(fp);
117
118     /* Open trace file */
119     if (debug)
120     {
121         addext(filename, ".trd");
122         if ((tracefile = fopen(filename, "w")) == NULL)
123             abend("Cannot open .trd file\n");
124     }
125 } /* end load */
126
127
128 static void initiate(argc, argv)        /* Establish configuration parameters */
129 int argc;
130 char **argv;
131 {
132     long m;
133     int len,i,on;
134     char filename[80];
135     int sock;
136     fd_set rset,wset;
137
138      ournode = 0;
139      network = TRUE;
140     if ( (argc==4) && (strcmp(argv[3],"r") == 0) ) remote = TRUE;else remote=FALSE;
141       for(i=0;i<255;i++)
142       {
143         RInstance[i] = -1;
144         DirConn[i] = -1;
145       }
146       
147     FD_ZERO(&DirSet);    
148     maxDirSet=0;
149  
150     strcpy(filename,argv[2]);
151     strcpy(ProgName,argv[2]);
152
153     strcpy(mynname,argv[1]);
154     strcat(mynname,".net");
155     unlink(mynname);
156     sock = socket(AF_UNIX,SOCK_STREAM,0); 
157     bzero(&svr, sizeof(svr));
158     svr.sun_family = AF_UNIX;
159     strcpy(svr.sun_path,mynname);
160     len = strlen(svr.sun_path)+sizeof(svr.sun_family);
161     bind(sock,(struct sockaddr*)&svr, len);
162     listen(sock,5);
163
164
165    /* socket for graphic requests */ 
166     strcpy(mygname,argv[1]);
167     strcat(mygname,".gr");
168     unlink(mygname);
169    
170
171    /* socket for KERNEL communication */  
172       internal_sock = socket(AF_UNIX,SOCK_STREAM,0);
173       bzero(&svr, sizeof(svr));
174       svr.sun_family = AF_UNIX;
175       strcpy(svr.sun_path,argv[1]);
176       strcpy(mykname,argv[1]);
177       len = strlen(svr.sun_path)+sizeof(svr.sun_family);
178       i=connect(internal_sock,(struct sockaddr*)&svr,len);
179      
180     if (i==0)
181        { 
182         fcntl(internal_sock,F_SETFL, O_NONBLOCK|fcntl(internal_sock,F_GETFL,0));
183         }
184     else
185      while (i!=0)
186     {
187       close(internal_sock);
188       internal_sock = socket(AF_UNIX,SOCK_STREAM,0);
189       fcntl(internal_sock,F_SETFL, O_NONBLOCK|fcntl(internal_sock,F_GETFL,0));
190       i=connect(internal_sock,(struct sockaddr*)&svr,len);     
191     }    
192     on=1;
193     setsockopt(internal_sock,IPPROTO_TCP,TCP_NODELAY,(char*)&on,sizeof(on));
194     
195     /* socket for network requests */
196      FD_ZERO(&rset);FD_ZERO(&wset);
197      FD_SET(sock,&rset);
198      if (select(sock+1,&rset,&wset,0,0))
199       net_sock = accept(sock,(struct sockaddr*)0,(int *)0);
200     if (net_sock>0)
201     {
202      fcntl(net_sock,F_SETFL,O_NONBLOCK|fcntl(net_sock,F_GETFL,0));
203      setsockopt(net_sock,IPPROTO_TCP,TCP_NODELAY,(char*)&on,sizeof(on));
204
205     }
206     close(sock);
207
208     if( filename!=NULL )
209        load(filename);                     /* load code and prototypes */
210     else
211        usage();
212 }
213
214
215 void decode(){
216     extopcode *eop;
217
218     eop = (extopcode *)(M+ic);   /* pointer to extended opcode in M */
219     lastic = ic;                     /* save ic for possible redecoding */
220     ic += APOPCODE;
221     opcode = ((int) eop->opcode ) & 0xFF ;
222     getargument(a1, 0);
223     getargument(a2, 1);
224     getargument(a3, 2);
225 }
226
227 /* -------------------------------------------------------------------- */
228
229
230 void send_to_graph(G_MESSAGE *msg)
231 {
232  write(graph_sock,msg,sizeof(G_MESSAGE));
233 }
234
235 int read_from_graph(G_MESSAGE *msg)
236 {
237  fd_set rset,wset;
238  struct timeval tout={0,0};
239  
240  FD_ZERO(&rset);FD_ZERO(&wset);
241  FD_SET(graph_sock,&rset);
242  
243   
244  if (select(graph_sock+1,&rset,&wset,0,(struct timeval *)&tout)>0)
245  {
246   if (FD_ISSET(graph_sock,&rset))
247    return(read(graph_sock,msg,sizeof(G_MESSAGE)));
248  }
249  return(0);  
250 }
251
252 int read_from_net(MESSAGE *msg)
253 {
254  fd_set rset,wset;
255  struct timeval tout={0,0};
256  
257  FD_ZERO(&rset);FD_ZERO(&wset);
258  FD_SET(net_sock,&rset);
259  
260   
261  if (select(net_sock+1,&rset,&wset,0,(struct timeval *)&tout)>0)
262  {
263   if (FD_ISSET(net_sock,&rset))
264    return(read(net_sock,msg,sizeof(MESSAGE)));
265  }
266  return(0);  
267 }
268
269
270 /* Get graphic resource number */
271 int get_graph_res()
272 {
273  MESSAGE msg;
274  int sock;
275  struct sockaddr_un svr;
276  int len,i,on;
277  fd_set rset,wset;
278
279  unlink(mygname);
280  sock = socket(AF_UNIX,SOCK_STREAM,0);
281  bzero(&svr,sizeof(svr));
282  svr.sun_family = AF_UNIX;
283  strcpy(svr.sun_path,mygname);
284  len = strlen(svr.sun_path)+sizeof(svr.sun_family);
285  bind(sock,(struct sockaddr*)&svr, len);      
286  listen(sock,5);
287
288
289  msg.msg_type = MSG_GRAPH;
290  msg.param.pword[0] = GRAPH_ALLOCATE;
291  strcpy(msg.param.pstr,mygname);
292  write(internal_sock,&msg,sizeof(MESSAGE));
293  bzero(&msg,sizeof(MESSAGE));
294  FD_ZERO(&rset);FD_ZERO(&wset);
295  FD_SET(sock,&rset);
296   if (select(sock+1,&rset,&wset,0,0))
297     graph_sock = accept(sock,(struct sockaddr*)0,(int*)0);
298  
299  if (graph_sock == -1)
300  {
301    graphics=FALSE;return(0);
302  }
303   on=1;
304   close(sock);
305   fcntl(graph_sock,F_SETFL, O_NONBLOCK|fcntl(graph_sock,F_GETFL,0));
306   setsockopt(graph_sock,IPPROTO_TCP,TCP_NODELAY,(char*)&on,sizeof(on));
307
308   return(1);
309    
310 } /* get_graph_res */
311
312
313 /* writeln string */
314 void writeln_str(char *s)
315 {
316  G_MESSAGE msg;
317  msg.msg_type = MSG_GRAPH;
318  msg.param.pword[1] = GraphRes;
319  msg.param.pword[2] = GRAPH_WRITE;
320  strcpy(msg.param.pstr,s);
321  
322  send_to_graph(&msg);
323  strcpy(msg.param.pstr,"\n");
324  send_to_graph(&msg);
325 }
326
327 /* write string */
328 void write_str(char *s)
329 {
330  G_MESSAGE msg;
331  msg.msg_type = MSG_GRAPH;
332  msg.param.pword[1] = GraphRes;
333  msg.param.pword[0] = GRAPH_WRITE;
334  strcpy(msg.param.pstr,s);
335  send_to_graph(&msg);
336 }
337
338 /* write char */
339 void write_char(char a)
340 {
341  G_MESSAGE msg;
342
343  msg.msg_type = MSG_GRAPH;
344  msg.param.pword[1] = GraphRes;
345  msg.param.pword[0] = GRAPH_PUTCHAR;
346  msg.param.pchar = a;
347  send_to_graph(&msg);
348 }
349
350
351 /* read char */
352 char read_char()
353 {
354  char ch;
355  G_MESSAGE msg;
356  int st;
357
358
359   msg.msg_type = MSG_GRAPH;
360   msg.param.pword[1] = GraphRes;
361   msg.param.pword[0] = GRAPH_READCHAR;
362   send_to_graph(&msg);
363   while(TRUE)
364       {
365        st = read_from_graph(&msg);
366        if (st>0)
367          {
368           if ((msg.msg_type == MSG_GRAPH) && 
369               (msg.param.pword[0]==GRAPH_READCHAR_RESPONSE)) 
370             {ch = msg.param.pchar;break;}
371          }
372        }
373  return(ch);
374
375 }
376
377 /* read line */
378 void read_line()
379 {
380  G_MESSAGE msg;
381  int st;
382
383
384   msg.msg_type = MSG_GRAPH;
385   msg.param.pword[1] = GraphRes;
386   msg.param.pword[0] = GRAPH_READLN;
387   send_to_graph(&msg);
388   while(TRUE)
389       {
390        st = read_from_graph(&msg);
391        if (st>0)
392          if ((msg.msg_type == MSG_GRAPH) && (msg.param.pword[0]== GRAPH_READLN_RESPONSE))
393           break;
394        }
395 }
396
397 /* read string */
398 void read_str(char *s)
399 {
400  char ss[255];
401  G_MESSAGE msg;
402  int st;
403
404   msg.msg_type = MSG_GRAPH;
405   msg.param.pword[1] = GraphRes;
406   msg.param.pword[0] = GRAPH_READSTR;
407   send_to_graph(&msg);
408   while(TRUE)
409       {
410        st = read_from_graph(&msg);
411        if (st>0)
412          {
413           if ((msg.msg_type == MSG_GRAPH) && 
414               (msg.param.pword[0]==GRAPH_READSTR_RESPONSE)) 
415             { strcpy(ss,msg.param.pstr);break;}
416          }
417        }
418  strcpy(s,ss);
419
420 }
421
422
423 /* send message to kernel */
424 void send_to_kernel(MESSAGE *msg)
425 {
426  write(internal_sock,msg,sizeof(MESSAGE));
427 }
428
429 /* send message to net */
430 void send_to_net(MESSAGE *msg)
431 {
432  int k,len;
433  MESSAGE m;
434  struct sockaddr_in svr;
435
436
437  k = msg->int_msg.control.receiver.node; 
438  if (RInstance[k]==-1)
439   { 
440    bzero(&m,sizeof(MESSAGE));
441    m.msg_type = MSG_VLP;
442    m.param.pword[0] = VLP_REMOTE_INSTANCE_PLEASE;
443    m.param.pword[1] = my_ctx.program_id;
444    m.param.pword[2] = k;
445    send_to_kernel(&m);
446    bzero(&m,sizeof(MESSAGE));
447    while(1)
448      {
449        read(internal_sock,&m,sizeof(MESSAGE));
450        if ( (m.msg_type == MSG_VLP) && (m.param.pword[0]==VLP_REMOTE_INSTANCE_HERE)) break;
451       }
452      
453    RInstance[k] = m.param.pword[1];
454    /* Make direct connection */
455    DirConn[k] = socket(AF_INET,SOCK_STREAM,0);
456    svr.sin_family = AF_INET;
457    svr.sin_addr.s_addr = inet_addr(m.param.pstr);
458    svr.sin_port = htons(m.param.pword[8]);
459    len = connect(DirConn[k],(struct sockaddr*)&svr,sizeof(svr));
460    if (len!=0) 
461     {
462      RInstance[k]=-1;
463      writeln_str("Cannot connect remote instance!");
464     }
465    else
466      {
467       fcntl(DirConn[k], F_SETFL,O_NONBLOCK | fcntl(DirConn[k], F_GETFL,0));
468
469       } 
470    }
471 if (RInstance[k]!=-1)
472 {
473  write(DirConn[k],&(msg->int_msg),sizeof(message)); 
474
475 }
476
477
478
479 /* -------------------- Check for message on internal socket -------------*/
480
481
482 void get_internal()
483 {
484  MESSAGE m,m1;
485  message mx;
486  
487  int r,max,i;
488  char s[80];
489  fd_set rset,wset;
490  struct timeval tout={0,0};
491  
492  
493  
494  /* ----------- Direct connection messages -----*/
495  FD_ZERO(&DirSet);
496  maxDirSet=0;
497  for(i=0;i<255;i++)
498   if (DirConn[i]!=-1) 
499    {
500     FD_SET(DirConn[i],&DirSet);
501     if (maxDirSet<DirConn[i]) maxDirSet=DirConn[i];
502    }
503  
504  if (select(maxDirSet+1,&DirSet,0,0,(struct timeval *)&tout)>0)
505   {
506    for(i=0;i<255;i++)
507    {
508     if ( (DirConn[i]!=-1) && (FD_ISSET(DirConn[i],&DirSet)) )
509     {
510      r=read(DirConn[i],&mx,sizeof(mx));
511      if (r>0)
512      {
513       memcpy(globmsgqueue+msgtail,&mx,sizeof(message));
514       msgtail = (msgtail+1) % MAXMSGQUEUE;
515       msgready++;
516      } 
517     }
518    }
519    }
520  /*-----------------------------------------*/
521  
522  
523  FD_ZERO(&rset);FD_ZERO(&wset);
524  FD_SET(net_sock,&rset);
525  FD_SET(internal_sock,&rset);
526  
527  if (net_sock>internal_sock) max = net_sock; else max = internal_sock;
528   
529  if (select(max+1,&rset,&wset,0,(struct timeval *)&tout)>0)
530  {
531  
532  if (FD_ISSET(net_sock,&rset))
533  {
534  r = read(net_sock, &m, sizeof(MESSAGE));
535  if (r>0)
536  {
537    switch(m.msg_type)
538    {
539      case MSG_NET:
540                   switch(m.param.pword[0])
541                   {
542                    case NET_PROPAGATE:
543                     memcpy(globmsgqueue+msgtail,&m.int_msg,sizeof(message));
544                     msgtail = (msgtail+1) % MAXMSGQUEUE;
545                     msgready++;
546                    break;
547                   }; break;
548     } /*switch */
549  }
550   } /* FD_ISSET */
551  
552  if (FD_ISSET(internal_sock,&rset))
553  {
554  r = read(internal_sock,&m,sizeof(MESSAGE));
555
556  if (r>0)
557  {
558   switch(m.msg_type)
559   {
560     case MSG_INT:
561                switch(m.param.pword[0])
562                { 
563                 case INT_CLOSE_INSTANCE: endrun(0);
564                 case INT_KILL: endrun(1);                     
565                 default:break;     
566                } /* switch int */
567     case MSG_NET: 
568             if (m.param.pword[0] == NET_PROPAGATE)
569             {
570              memcpy(globmsgqueue+msgtail,&m.int_msg,sizeof(message));
571              msgtail = (msgtail+1) % MAXMSGQUEUE;
572              msgready++;
573             };break;           
574     
575     
576     
577   }/*switch type */
578  }
579  } /* FD_ISSET */
580  } /* select */
581 }
582
583
584 void request_id()
585 {
586  MESSAGE m;
587  G_MESSAGE m1; 
588  
589  m.msg_type = MSG_INT;
590  m.param.pword[0] = INT_CTX_REQ;
591  send_to_kernel(&m);
592  while ( (m.msg_type != MSG_INT) || (m.param.pword[0] != INT_CTX) )
593   read(internal_sock,&m,sizeof(MESSAGE));
594   
595     my_ctx.node = m.param.pword[1];
596     my_ctx.program_id = m.param.pword[2];
597     if (remote)
598             {
599               parent_ctx.node = m.param.pword[3];
600               parent_ctx.program_id = m.param.pword[4];
601               RInstance[parent_ctx.node] = parent_ctx.program_id;
602             }
603               else
604         {
605          parent_ctx.node = my_ctx.node;
606          parent_ctx.program_id = my_ctx.program_id;
607         } 
608   ournode = my_ctx.node;
609 //  strcpy(nname,m.param.pstr);
610 //  net_sock = open(nname,O_WRONLY);
611   m1.msg_type = MSG_GRAPH;
612   m1.param.pword[0] = GRAPH_SET_TITLE;
613   m1.param.pword[1] = GraphRes;
614   sprintf(m1.param.pstr,
615   "%s      ID: %d",ProgName,my_ctx.program_id);       
616   if (remote) strcat(m1.param.pstr,"  REMOTE instance");
617   send_to_graph(&m1);
618 }
619
620
621
622 void send_ready()
623 {
624  int sock,len;
625  struct sockaddr_in svr;
626  char name[255];
627  struct hostent *info;
628  
629
630  MESSAGE msg;
631  msg.msg_type = MSG_NET;
632  msg.param.pword[0] = NET_PROPAGATE;
633  msg.param.pword[1] = MSG_VLP;
634  msg.param.pword[2] = my_ctx.node;
635  msg.param.pword[4] = parent_ctx.node;
636  msg.param.pword[6] = VLP_REMOTE_INSTANCE_OK;
637  msg.param.pword[7] = my_ctx.program_id;
638  
639  sock = socket(AF_INET,SOCK_STREAM,0);
640  bzero(&svr,sizeof(svr));
641  svr.sin_family = AF_INET;
642  svr.sin_addr.s_addr = INADDR_ANY;
643  svr.sin_port = 0;
644  bind(sock, (struct sockaddr*)&svr, sizeof(svr));
645  listen(sock,5);
646  len=sizeof(svr);
647  getsockname(sock,(struct sockaddr*)&svr,&len);
648  msg.param.pword[8] = ntohs(svr.sin_port);
649  gethostname(name,&len);
650  info = (struct hostent*)gethostbyname(name);
651  bcopy((char*)info->h_addr,(char*)&svr.sin_addr,info->h_length);
652  sprintf(msg.param.pstr,"%s",inet_ntoa(svr.sin_addr));
653  send_to_kernel(&msg);
654  
655  bzero(&svr,sizeof(svr));
656  DirConn[parent_ctx.node] = accept(sock,(struct sockaddr*)&svr,&len);
657  fcntl(DirConn[parent_ctx.node], F_SETFL,O_NONBLOCK | 
658  fcntl(DirConn[parent_ctx.node], F_GETFL,0));
659 }
660
661 int main(argc, argv)
662 int argc;
663 char **argv;
664 {
665     initiate(argc, argv);             /* initialize executor */
666     runsys();              /* initialize running system */
667     init_scheduler();
668     GraphRes = get_graph_res();
669     if ( GraphRes < 0 ) exit(12); 
670      
671     request_id();
672     if (remote) send_ready(); 
673
674
675     setjmp(contenv);         /* set label for continue long jump */
676     while (TRUE)                     /* repeat until exit() is called */
677     {
678         get_internal();
679         schedule();         /* reschedule current process */
680     if (ready != 0)
681     {
682         decode();               /* fetch instruction */
683         execute();            /* and execute it */
684     }
685        
686     }
687     return 0;
688 } /* end main */
689