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

  1. /* Utility to access the REXX/imc stack server     (C) Ian Collier 1992 */
  2.  
  3. #include<stdio.h>
  4. #include<stdlib.h>
  5. #include<string.h>
  6. #include<signal.h>
  7. #include<sys/types.h>
  8. #include<sys/socket.h>
  9.  
  10. void ex1t();
  11.  
  12. struct {u_short af;char name[100];}  /* a mimic of struct sockaddr, but */
  13.        sock={AF_UNIX};               /* with a longer name field. */
  14. int socklen;                         /* The length of the socket name */
  15. char *buff;                          /* An input buffer */
  16. unsigned bufflen;                    /* The amount of memory allocated */
  17. int s;                               /* The socket fd */
  18.  
  19. main(argc,argv)
  20. int argc;
  21. char **argv;
  22. {
  23.    int fifo=1;                       /* fifo or lifo */
  24.    int c;
  25.    static char *opts[]={"-fifo","-lifo","-string","-pop","-peek","-drop",
  26.                         "-num","-print"};  /* All the allowed options */
  27.    static int optnum=8;              /* The number of allowed options */
  28.    int opt=0;                        /* position of an option in the above */
  29.    char id;                          /* a command character */
  30.    char *string;                     /* The parameter of -string flag */
  31.    int len;
  32.    static char out[10];              /* A buffer for sprintf */
  33.    char *env=getenv("RXSTACK");      /* The socket's file name */
  34.    if(!env)fputs("RX Stack not found\n",stderr),exit(1);
  35.    if(!(buff=malloc(bufflen=256)))perror("Unable to allocate memory"),exit(1);
  36.    strcpy(sock.name,env);
  37.    socklen=sizeof(u_short)+strlen(env);
  38.    for(c=1;c<argc;c++){              /* Find first "action" flag */
  39.       for(opt=0;opt<optnum&&strcmp(opts[opt],argv[c]);opt++);
  40.       if(opt==optnum)fprintf(stderr,"Invalid option: %s\n",argv[c]),exit(1);
  41.       if(opt>1)break;
  42.       if(opt==0)fifo=1;else fifo=0;  /* Deal with -fifo and -lifo and go on */
  43.    }
  44.    if(argc>++c+(opt==2))fputs("Too many options\n",stderr),exit(1);
  45.    if(opt<2)opt=0;                   /* no "action"; stack from stdin */
  46.    s=socket(AF_UNIX,SOCK_STREAM,0);  /* Try to connect... */
  47.    if(s<0)perror("Error in socket call"),exit(1);
  48.    if(connect(s,(struct sockaddr *)&sock,socklen)<0)perror("Error in connect call"),exit(1);
  49.    id=fifo?'Q':'S';                  /* Queue if fifo, Stack if lifo. */
  50.    switch(opt){                      /* Select the appropriate action */
  51.       case 0:while(1){               /* Default: collect lines from stdin */
  52.                 len=0;
  53.                 while((c=getchar())!=EOF&&c!='\n'){
  54.                    if(len>=bufflen&&!(buff=realloc(buff,bufflen<<=1)))
  55.                       perror("Out of memory"),exit(1);
  56.                    buff[len++]=c;
  57.                 }
  58.                 if(c==EOF&&!len)break;
  59.                 sprintf(out,"%c%06X\n",id,len);
  60.                 if(write(s,out,8)<8||write(s,buff,len)<len)
  61.                    perror("Error writing data"),exit(1);
  62.              }
  63.              break;
  64.       case 2:string=(c>=argc?"":argv[c]);/* Stack argument following -string */
  65.              sprintf(out,"%c%06X\n",id,len=strlen(string)); 
  66.              if(write(s,out,8)<8||write(s,string,len)<len)
  67.                 perror("Error writing data"),exit(1);
  68.              break;
  69.       case 3:pop('G',1);break;       /* -pop: use the "Get" command */
  70.       case 4:pop('P',1);break;       /* -peek: use the "Peek" command */
  71.       case 5:if(write(s,"D",1)<1)    /* -drop: write a "Drop" command */
  72.                 perror("Error writing data"),exit(1);
  73.              break;
  74.       case 6:if(write(s,"N",1)<1)    /* -num: write a "Num" command; get ans */
  75.                 perror("Error reading data"),exit(1);
  76.              if(read(s,buff,7)<7)perror("Error reading data"),exit(1);
  77.              len=x2d(buff);
  78.              printf("%d\n",len);
  79.              fflush(stdout);
  80.              break;
  81.       case 7:while(pop('P',0)!=0xffffff) /* -print: continually peek, then */
  82.                 if(write(s,"D",1)<1)     /* drop.                          */
  83.            perror("Error writing data"),exit(1);
  84.    }               /* This way, if the output is being read by a program which
  85.                       terminates, a SIGPIPE arrives and any unread data is
  86.               still on the stack. */
  87.    if(opt<3||opt==5){ /* wait for the stack process to catch up */
  88.       signal(15,ex1t); /* kludge to make a zero return code */
  89.       sprintf(out,"K%06X\n\017",getpid()); /* kill me with SIGTERM */
  90.       if(write(s,out,9)<9)perror("Error writing data"),exit(1);
  91.       pause();
  92.    }
  93.    close(s);
  94.    return 0;
  95. }
  96.  
  97. void ex1t() {close(s);exit(0);} /* on SIGTERM, just exit with return code 0 */
  98.  
  99. int x2d(hex)       /* Convert six hex digits from "hex" into an integer */
  100. char *hex;
  101. {
  102.    int i,len=0;
  103.    char c;
  104.    for(i=0;i<6;i++){
  105.       len<<=4;
  106.       if((c=hex[i])>='0'&&c<='9')len+=c-'0';
  107.       else if(c>='A'&&c<='F')len+=c-'A'+10;
  108.       else if(c>='a'&&c<='f')len+=c-'a'+10;
  109.    }
  110.    return len;
  111. }
  112.  
  113. int pop(id,nullok)  /* Print the top value from the stack, using "id" as */
  114. char id;            /* the command character.  If the stack is empty and */
  115. int nullok;         /* nullok!=0 then print a newline, else just return. */
  116. {                   /* The return value is the length given by the stack */
  117.    int len;
  118.    int rdlen;
  119.    int i;
  120.    if(write(s,&id,1)<1)    /* write the command character */
  121.       perror("Error writing data"),exit(1);
  122.    if(read(s,buff,7)<7)    /* Expect a length to be returned */
  123.       perror("Error reading data"),exit(1);
  124.    len=x2d(buff);
  125.    if(len!=0xffffff){      /* Stack wasn't empty, so expect some data */
  126.       if(len>bufflen&&!(buff=realloc(buff,(unsigned)len)))
  127.          perror("Out of memory"),exit(1);
  128.       rdlen=0;
  129.       while(rdlen<len)     /* Read the data */
  130.          if((i=read(s,buff+rdlen,len-rdlen))<1)
  131.         perror("Error reading data"),exit(1);
  132.      else rdlen+=i;
  133.       fwrite(buff,1,len,stdout); /* Write the data to stdout */
  134.       putchar('\n');
  135.       fflush(stdout);      /* Make sure the application reads this */
  136.    }
  137.    else if(nullok){        /* Stack was empty; write an empty line */
  138.       putchar('\n');
  139.       fflush(stdout);
  140.    }
  141.    return len;
  142. }
  143.