home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rximc175.zip / rxque.c < prev    next >
Text File  |  2002-08-06  |  9KB  |  237 lines

  1. /* The stack server of REXX/imc                    (C) Ian Collier 1992 */
  2.  
  3. #include<stdio.h>
  4. #include<stdlib.h>
  5. #include<errno.h>
  6. #include<signal.h>
  7. #include<fcntl.h>
  8. #include<sys/time.h>
  9. #include<sys/types.h>
  10. #include<unistd.h>
  11. #include<sys/wait.h>
  12. #include<sys/socket.h>
  13. #include<sys/stat.h>
  14.  
  15. int io();                            /* function which does the work */
  16. void term();                         /* cleanup function */
  17.  
  18. struct {u_short af;char name[100];}  /* a mimic of struct sockaddr, but */
  19.        sock={AF_UNIX};               /* with a longer name field. */
  20. int socklen;                         /* The length of the socket name */
  21. fd_set sockfds;                      /* Collection of fds in use */
  22. int maxfd;                           /* maximum fd in use */
  23. int s;                               /* Socket fd */
  24. char inbuf[20];                      /* for reading into */
  25. char *sname;                         /* Socket file name */
  26. static char uname[100];              /* for storing the socket file name */
  27. char dname[100];                     /* for storing the socket directory */
  28. char **stack;                        /* Pointer to the stack structure */
  29. int first,last;                      /* First and last elements in circle */
  30. int empty;                           /* Is stack empty when first==last? */
  31. unsigned max;                        /* Number of stack elements allocated */
  32.  
  33. main(argc,argv)           /* Specify "-csh" and/or a filename */
  34. int argc;
  35. char **argv;
  36. {
  37.    int t;
  38.    int csh=0;
  39.    int parent=getppid();
  40.    if(argc>1&&!strcmp(argv[1],"-csh"))argv++,argc--,csh++;
  41.    if(argc>2)fputs("Usage: rxque [-csh] [socketname]\n",stderr),exit(1);
  42.    umask(077);
  43.    if(argc==2)sname=argv[1];  /* must be the supplied file name */
  44.    else{                      /* make one up */
  45.       sprintf(dname,"/tmp/rxsock%d",getuid()),
  46.       sprintf(uname,"%s/rxstack.%d",dname,getpid());
  47.       if(mkdir(dname,0700)&&errno!=EEXIST)
  48.          perror("Cannot create socket directory"),
  49.          exit(1);
  50.       sname=uname;
  51.    }
  52.    unlink(sname);             /* just in case it was there already */
  53.    strcpy(sock.name,sname);
  54.    socklen=sizeof(u_short)+strlen(sname);
  55.    s=socket(AF_UNIX,SOCK_STREAM,0);
  56.    if(s<0)perror("Cannot create socket"),exit(1);
  57.    if(s==2){ /* 2 is needed for error output */
  58.       t=dup(s);
  59.       if(t<0)perror("Cannot dup socket descriptor"),exit(1);
  60.       close(s);
  61.       s=t;
  62.    }
  63.    if(bind(s,(struct sockaddr *)&sock,socklen)<0)perror("Error in bind call"),exit(1);
  64.    if(listen(s,1)<0)perror("Error in listen call"),exit(1);
  65.    setpgid(0,getpid());       /* Prevent signals from keyboard */
  66.    if((t=fork())<0)perror("fork"),exit(1);
  67.    if(t){                     /* Parent: output data and exit */
  68.       if(argc==2)printf("%d\n",t);
  69.       else
  70.          if(csh)printf("setenv RXSTACK %s;setenv RXSTACKPROC %d",sname,t);
  71.          else printf("RXSTACK=%s RXSTACKPROC=%d",sname,t);
  72.       fflush(stdout),
  73.       exit(0);
  74.    }
  75.    /* Child: now in background, so start serving */
  76.    if(!(stack=(char**)malloc((max=128)*sizeof(char*))))
  77.       perror("malloc"),exit(1);
  78.    if (s!=1) fclose(stdout);
  79.    if (s!=0) fclose(stdin),
  80.    freopen("/dev/tty","w",stderr); /* In case of error messages */
  81.    signal(SIGTERM,term);           /* enable cleanup when killed */
  82.    first=0;last=0;empty=1;
  83.    FD_ZERO(&sockfds);
  84.    maxfd=s;
  85.    while(1)
  86.       if(!io()){                   /* returns 0 if inactive for 5 minutes */
  87.          if(kill(parent,0)&&errno==ESRCH)
  88.             fputs("RX Stack: Exiting since parent no longer exists\n",stderr),
  89.             fflush(stderr),
  90.             term();
  91.       }
  92. }
  93.  
  94. int io() /* Wait for connections; return 0 if timed out, 1 otherwise */
  95. {
  96.    fd_set readfds, exceptfds; /* for select call */
  97.    int nfds;
  98.    int t;
  99.    int rc;
  100.    int len;
  101.    int rdlen;
  102.    int i;
  103.    char c;
  104.    char *mem;
  105.    struct timeval timeout;
  106.    timeout.tv_sec=300;timeout.tv_usec=0;  /* 5 minute timeout */
  107.    readfds=sockfds;     /* for select(): */
  108.    FD_SET(s,&readfds);  /* read fds: all fds plus the socket */
  109.    FD_ZERO(&exceptfds); /* except fds: just the socket */
  110.    FD_SET(s,&exceptfds);
  111.    if(!(nfds=select(maxfd+1,&readfds,NULL,&exceptfds,&timeout))) return 0;
  112.    if (nfds<0) return 1; /* Error (what to do?) */
  113.    if(FD_ISSET(s,&readfds) || FD_ISSET(s,&exceptfds)){ /* The socket is ready */
  114.       if((t=accept(s,(struct sockaddr *)&sock,&socklen))<0); /* Error (what to do?) */
  115.       else {
  116.          if (t>maxfd) maxfd=t;
  117.          FD_SET(t,&sockfds);
  118.       }
  119.    }
  120.    for (t=0; t<=maxfd; t++) { /* Process all fds which are available for read */
  121.       if(FD_ISSET(t,&readfds) && t!=s){ /* Test each one in turn */
  122.          rc=read(t,inbuf,1);            /* Get the command character */
  123.          if(rc>0)switch(inbuf[0]){      /* and select appropriate action */
  124.             case 'N':len=last-first;    /* Num: output last-first (mod max) */
  125.                if(len<=0&&!empty)len+=max;
  126.                sprintf(inbuf,"%06X\n",len);
  127.                if(write(t,inbuf,7)<7)rc=-1;
  128.                break;
  129.             case 'S':                   /* Stack */
  130.             case 'Q':                   /* Queue */
  131.                   if(read(t,inbuf+1,7)<7){ /* Get the data length */
  132.                   rc=-1;
  133.                   break;
  134.                }
  135.                for(len=0,i=1;i<7;i++){       /* Interpret the hex value */
  136.                   len<<=4;
  137.                   if((c=inbuf[i])>='0'&&c<='9')len+=c-'0';
  138.                   else if(c>='A'&&c<='F')len+=c-'A'+10;
  139.                   else if(c>='a'&&c<='f')len+=c-'a'+10;
  140.                   else rc=-1;
  141.                }
  142.                if(rc<0)break;
  143.                if(first==last&&!empty){     /* Extend the full stack */
  144.                   if(!(stack=(char**)realloc((char *)stack,(max<<=1)*sizeof(char *))))
  145.                      perror("RX Stack server: Unable to allocate memory"),
  146.                      exit(1);
  147.                   memcpy((char *)(stack+first+max/2),(char *)(stack+first),(max/2-first)*sizeof(char*));
  148.                   first+=max/2;
  149.                }              /* next allocate memory for a stack entry */
  150.                if(!(mem=malloc((unsigned)len+sizeof(int)))){
  151.                   rc=-1;
  152.                   perror("RX Stack server: Unable to stack data");
  153.                   break;
  154.                }
  155.                rdlen=0;
  156.                while(rdlen<len&&rc>0)       /* Read the data to be stacked */
  157.                   if((i=read(t,mem+sizeof(int)+rdlen,len-rdlen))<1)rc=-1;
  158.                   else rdlen+=i;
  159.                if(rc>0) {
  160.                   *(int *)mem=len;          /* Store its length */
  161.                   empty=0;
  162.                   if(inbuf[0]=='Q'){        /* Put its address in the array */
  163.                      stack[last++]=mem;
  164.                      if(last==max)last=0;
  165.                   }
  166.                   else{
  167.                      if(--first<0)first+=max;
  168.                      stack[first]=mem;
  169.                   }
  170.                }
  171.                break;
  172.             case 'G':                   /* Get */
  173.             case 'P':if(empty){         /* Peek */
  174.                   if(write(t,"FFFFFF\n",7)<7)rc=-1;
  175.                   break;
  176.                }
  177.                sprintf(inbuf+1,"%06X\n",len=*(int *)stack[first]);
  178.                if(write(t,inbuf+1,7)<7)rc=-1;  /* Write the data */
  179.                else if(write(t,stack[first]+sizeof(int),len)<len)rc=-1;
  180.                if(inbuf[0]=='P')break;           /* Continue if it was "Get" */
  181.             case 'D':if(empty)break;    /* Drop */
  182.                free(stack[first]);
  183.                if(++first==max)first=0;
  184.                if(first==last)empty=1;
  185.             break;
  186.             case 'K':                   /* Kill me */
  187.                   if(read(t,inbuf+1,8)<8){ /* Get the pid and signal */
  188.                   rc=-1;
  189.                   break;
  190.                }
  191.                for(len=0,i=1;i<7;i++){       /* Interpret the hex value */
  192.                   len<<=4;
  193.                   if((c=inbuf[i])>='0'&&c<='9')len+=c-'0';
  194.                   else if(c>='A'&&c<='F')len+=c-'A'+10;
  195.                   else if(c>='a'&&c<='f')len+=c-'a'+10;
  196.                   else rc=-1;
  197.                }
  198.                if(rc<0)break;
  199.                kill(len,inbuf[8]);
  200.                break;
  201.             default:rc=-1;             /* Unrecognised */
  202.          }
  203.          if(rc<=0){ /* Error: close connection */
  204.             close(t);
  205.             FD_CLR(t,&sockfds); 
  206.          }
  207.       }
  208.    }
  209.    return 1;
  210. }
  211.  
  212. void term(){
  213.    int n;
  214.    int l;
  215.    char *p,*q;
  216.    close(s);      /* Close and remove the socket */
  217.    unlink(sname);
  218.    if(!empty){    /* Print and free all stacked items */
  219.       n=last-first;
  220.       if(n<0)n+=max;
  221.       fprintf(stderr,"RX Stack: %d item%s still stacked\n",n,n==1?"":"s");
  222.       while(n-->0){
  223.          fputc('>',stderr);
  224.          q=p=stack[first++];
  225.          if(first==max)first=0;
  226.          l=*(int *)p;
  227.          p+=sizeof(int);
  228.          while(l--)fputc(*p>=' '&&*p<=0x7e?*p:'?',stderr),p++;
  229.          fputc('\n',stderr);
  230.          free(q);
  231.       }
  232.       fflush(stderr);
  233.    }
  234.    free((char *)stack);
  235.    exit(0);
  236. }
  237.