home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / vmspipe.c < prev    next >
C/C++ Source or Header  |  1996-02-25  |  6KB  |  268 lines

  1. /*
  2.  *    vmspipe.c
  3.  *        adapted from elvis, in turn from
  4.  *        Chris Janton's (chj) VMS Icon port.
  5.  *
  6.  * $Header: /usr/build/vile/vile/RCS/vmspipe.c,v 1.12 1996/02/26 04:24:35 pgf Exp $
  7.  *
  8.  */
  9.  
  10. #include "estruct.h"
  11.  
  12. #include <starlet.h>
  13. #include <lib$routines.h>
  14.  
  15. #include <iodef.h>
  16. #include <ssdef.h>
  17. #include <dvidef.h>
  18. #include <file.h>
  19.  
  20. #define    OK(f)    ((f) & STS$M_SUCCESS)
  21. #define    MAXBFR    256
  22.  
  23. /*
  24.  *    Here we fudge to help the "elvis" program implement rpipe.  The
  25.  *    routine essentially does an popen using fd as stdin--except that
  26.  *    few VMS utilities use the 'C' library.    So we pass in the standard
  27.  *    input file name and use it if fd is non-zero.
  28.  */
  29.  
  30. typedef struct _descr {
  31.         int    length;
  32.         char *    ptr;
  33.     } descriptor;
  34.  
  35. typedef struct _pipe {
  36.     long    pid;        /* process id of child */
  37.     long    status;        /* exit status of child */
  38.     long    flags;        /* lib$spawn flags */
  39.     int    ichan;        /* MBX channel number */
  40.     int    ochan;
  41.     int    efn;
  42.     unsigned running : 1;    /* 1 if child is running */
  43. } Pipe;
  44.  
  45. Pipe _pipes[_NFILE];        /* one for every open file */
  46.  
  47. #define NOWAIT        1
  48. #define NOCLISYM    2
  49. #define NOLOGNAM    4
  50. #define NOKEYPAD    8
  51. #define NOTIFY        16
  52. #define NOCONTROL    32
  53. #define SFLAGS    (NOWAIT|NOKEYPAD|NOCONTROL)
  54.  
  55.  
  56. /*
  57.  * Taken from pclose - close a pipe
  58.  * Last modified 2-Apr-86/chj
  59.  */
  60. static int
  61. vms_rpclose(int pfile)
  62. {
  63.     Pipe *pd = (pfile >= 0 && pfile < TABLESIZE(_pipes)) ? &_pipes[pfile] : 0;
  64.     int status;
  65.     int fstatus;
  66.  
  67.     if (pd == NULL)
  68.         return (-1);
  69.     fstatus = close(pfile);
  70.     sys$dassgn(pd->ichan);
  71.     sys$dassgn(pd->ochan);
  72.     lib$free_ef(&pd->efn);
  73.     pd->running = 0;
  74.     return (fstatus);
  75. }
  76.  
  77. static int
  78. vms_pread (int pfile, char *buffer, int size)
  79. /* Be compatible when we read data in (handle newlines). */
  80. {
  81.     Pipe *pd = (pfile >= 0 && pfile < TABLESIZE(_pipes)) ? &_pipes[pfile] : 0;
  82.     struct {
  83.         short    status,
  84.             count;
  85.         int:16;
  86.     } iosb;
  87.  
  88.     /*
  89.      * This is sort of nasty.  The default mailbox size is 256 maxmsg and
  90.      * 1056 bufquo if your sysgen parameters are standard.  Asking for more
  91.      * on the CREMBX command (in rpipe) might be a bad idea as that could
  92.      * cause an "exceeded quota" error.  Since we only return -1 on error,
  93.      * there's no hope that the poor user would ever know what went wrong.
  94.      */
  95.     if (pd != 0) {
  96.         int    request = size > MAXBFR ? MAXBFR : size - 1;
  97.         register int    got;
  98.  
  99.         if (OK(sys$qiow(0, pd->ochan, IO$_READVBLK, &iosb, 0, 0,
  100.                 buffer, request, 0, 0, 0, 0))) {
  101.  
  102.             if (iosb.status == SS$_ENDOFFILE)
  103.                 return 0;
  104.             got = iosb.count;
  105.             if (got == 0 || buffer[got-1] != '\n')
  106.                 buffer[got++] = '\n';
  107.             buffer[got] = EOS;
  108.             return got;
  109.         }
  110.     }
  111.     return -1;
  112. }
  113.  
  114. FILE *
  115. vms_rpipe (const char *cmd, int fd, const char *input_file)
  116. {
  117.     int    pfile;        /* the Pfile */
  118.     Pipe    *pd;        /* _pipe database */
  119.     descriptor inmbxname;    /* name of input mailbox */
  120.     descriptor outmbxname;    /* name of mailbox */
  121.     char    inmname[65];
  122.     char    outmname[65];    /* mailbox name string */
  123.     int    ochan;        /* mailbox channel number */
  124.     int    ichan;        /* Input mailbox channel number */
  125.     int    efn;
  126.  
  127.     struct {
  128.         short    len;
  129.         short    code;
  130.         void *    address;
  131.         void *    retlen;
  132.         int    last;
  133.     } itmlst;
  134.  
  135.     if (!cmd || cmd[0] == EOS)
  136.         return (0);
  137.     lib$get_ef(&efn);
  138.     if (efn == -1)
  139.         return (0);
  140.  
  141.     /* create and open the input mailbox */
  142.     if (!OK(sys$crembx(0, &ichan, 0, 0, 0, 0, 0))) {
  143.         lib$free_ef(&efn);
  144.         return (0);
  145.     }
  146.  
  147.     itmlst.last = inmbxname.length = 0;
  148.     itmlst.address = inmbxname.ptr = inmname;
  149.     itmlst.retlen = &inmbxname.length;
  150.     itmlst.code = DVI$_DEVNAM;
  151.     itmlst.len = 64;
  152.     if (!OK(sys$getdviw(0, ichan, 0, &itmlst, 0, 0, 0, 0))) {
  153.         lib$free_ef(&efn);
  154.         return (0);
  155.     }
  156.     inmname[inmbxname.length] = EOS;
  157.  
  158.     /* create and open the output mailbox */
  159.     if (!OK(sys$crembx(0, &ochan, 0, 0, 0, 0, 0))) {
  160.         lib$free_ef(&efn);
  161.         return (0);
  162.     }
  163.  
  164.     itmlst.last = outmbxname.length = 0;
  165.     itmlst.address = outmbxname.ptr = outmname;
  166.     itmlst.retlen = &outmbxname.length;
  167.     if (!OK(sys$getdviw(0, ochan, 0, &itmlst, 0, 0, 0, 0))) {
  168.         lib$free_ef(&efn);
  169.         return (0);
  170.     }
  171.  
  172.     outmname[outmbxname.length] = EOS;
  173.     pfile = open(outmname, O_RDONLY, S_IREAD);
  174.     if (pfile < 0) {
  175.         lib$free_ef(&efn);
  176.         sys$dassgn(ichan);
  177.         sys$dassgn(ochan);
  178.         return (0);
  179.     }
  180.  
  181.     /* Save file information now */
  182.     pd = &_pipes[pfile]; /* get Pipe pointer */
  183.     pd->pid   = pd->status = pd->running = 0;
  184.     pd->flags = SFLAGS;
  185.     pd->ichan = ichan;
  186.     pd->ochan = ochan;
  187.     pd->efn   = efn;
  188.  
  189.     /* Initiate the command by writing down the input mailbox (SYS$INPUT). */
  190.  
  191.     if (fd > 0) {
  192.         char    pre_command[132+12];
  193.  
  194.         (void)strcpy (pre_command, "DEFINE/USER SYS$INPUT ");
  195.         (void)strcat (pre_command, input_file);
  196.         if (!OK(
  197.             sys$qiow(0,
  198.                 ichan,
  199.                 IO$_WRITEVBLK | IO$M_NOW,
  200.                 0, 0, 0,
  201.                 pre_command, strlen(pre_command),
  202.                 0, 0, 0, 0))) {
  203.             lib$free_ef(&efn);
  204.             sys$dassgn(ichan);
  205.             sys$dassgn(ochan);
  206.             return (0);
  207.         }
  208.     }
  209.  
  210.     if (!OK(
  211.         sys$qiow(0,
  212.         ichan,
  213.         IO$_WRITEVBLK | IO$M_NOW,
  214.         0, 0, 0, cmd, strlen(cmd), 0, 0, 0, 0))) {
  215.         ;
  216.     } else if (!OK(
  217.         sys$qiow(0,
  218.             ichan,
  219.             IO$_WRITEOF | IO$M_NOW,
  220.             0, 0, 0, 0, 0, 0, 0, 0, 0))) {
  221.         ;
  222.     } else if (!OK(
  223.         lib$spawn(0,
  224.             &inmbxname,        /* input file */
  225.             &outmbxname,        /* output file */
  226.             &pd->flags,
  227.             0,
  228.             &pd->pid,
  229.             &pd->status,
  230.             &pd->efn,
  231.             0, 0, 0, 0))) {
  232.         ;
  233.     } else {
  234.         FILE    *pp;
  235.         int    len;
  236.         int    count    = 0;
  237.         char    buffer[MAXBFR];
  238.  
  239.         pd->running = 1;
  240.  
  241.         /*
  242.          * For our application, we need a file-pointer.  Empty the
  243.          * pipe into a temporary file.  Unfortunately, this means that
  244.          * the application will use 'slowreadf()' to write the data.
  245.          */
  246.         if (pp = tmpfile()) {
  247.             for_ever {
  248.                 len = vms_pread(pfile, buffer, sizeof(buffer));
  249.                 if (len <= 0)
  250.                     break;
  251.                 fwrite(buffer, sizeof(*buffer), len, pp);
  252.                 count++;
  253.             }
  254.             mlforce("[Read %d lines from %s ]", count, cmd);
  255.             vms_rpclose(pfile);
  256.             (void)fflush(pp);
  257.             rewind(pp);
  258.             return pp;
  259.         }
  260.         return (0);
  261.     }
  262.  
  263.     lib$free_ef(&efn);
  264.     sys$dassgn(ichan);
  265.     sys$dassgn(ochan);
  266.     return (0);
  267. }
  268.