This is vmspipe.c in view mode; [Download] [Up]
/* * vmspipe.c * adapted from elvis, in turn from * Chris Janton's (chj) VMS Icon port. * * $Header: /usr2/foxharp/src/pgf/vile/RCS/vmspipe.c,v 1.12 1996/02/26 04:24:35 pgf Exp $ * */ #include "estruct.h" #include <starlet.h> #include <lib$routines.h> #include <iodef.h> #include <ssdef.h> #include <dvidef.h> #include <file.h> #define OK(f) ((f) & STS$M_SUCCESS) #define MAXBFR 256 /* * Here we fudge to help the "elvis" program implement rpipe. The * routine essentially does an popen using fd as stdin--except that * few VMS utilities use the 'C' library. So we pass in the standard * input file name and use it if fd is non-zero. */ typedef struct _descr { int length; char * ptr; } descriptor; typedef struct _pipe { long pid; /* process id of child */ long status; /* exit status of child */ long flags; /* lib$spawn flags */ int ichan; /* MBX channel number */ int ochan; int efn; unsigned running : 1; /* 1 if child is running */ } Pipe; Pipe _pipes[_NFILE]; /* one for every open file */ #define NOWAIT 1 #define NOCLISYM 2 #define NOLOGNAM 4 #define NOKEYPAD 8 #define NOTIFY 16 #define NOCONTROL 32 #define SFLAGS (NOWAIT|NOKEYPAD|NOCONTROL) /* * Taken from pclose - close a pipe * Last modified 2-Apr-86/chj */ static int vms_rpclose(int pfile) { Pipe *pd = (pfile >= 0 && pfile < TABLESIZE(_pipes)) ? &_pipes[pfile] : 0; int status; int fstatus; if (pd == NULL) return (-1); fstatus = close(pfile); sys$dassgn(pd->ichan); sys$dassgn(pd->ochan); lib$free_ef(&pd->efn); pd->running = 0; return (fstatus); } static int vms_pread (int pfile, char *buffer, int size) /* Be compatible when we read data in (handle newlines). */ { Pipe *pd = (pfile >= 0 && pfile < TABLESIZE(_pipes)) ? &_pipes[pfile] : 0; struct { short status, count; int:16; } iosb; /* * This is sort of nasty. The default mailbox size is 256 maxmsg and * 1056 bufquo if your sysgen parameters are standard. Asking for more * on the CREMBX command (in rpipe) might be a bad idea as that could * cause an "exceeded quota" error. Since we only return -1 on error, * there's no hope that the poor user would ever know what went wrong. */ if (pd != 0) { int request = size > MAXBFR ? MAXBFR : size - 1; register int got; if (OK(sys$qiow(0, pd->ochan, IO$_READVBLK, &iosb, 0, 0, buffer, request, 0, 0, 0, 0))) { if (iosb.status == SS$_ENDOFFILE) return 0; got = iosb.count; if (got == 0 || buffer[got-1] != '\n') buffer[got++] = '\n'; buffer[got] = EOS; return got; } } return -1; } FILE * vms_rpipe (const char *cmd, int fd, const char *input_file) { int pfile; /* the Pfile */ Pipe *pd; /* _pipe database */ descriptor inmbxname; /* name of input mailbox */ descriptor outmbxname; /* name of mailbox */ char inmname[65]; char outmname[65]; /* mailbox name string */ int ochan; /* mailbox channel number */ int ichan; /* Input mailbox channel number */ int efn; struct { short len; short code; void * address; void * retlen; int last; } itmlst; if (!cmd || cmd[0] == EOS) return (0); lib$get_ef(&efn); if (efn == -1) return (0); /* create and open the input mailbox */ if (!OK(sys$crembx(0, &ichan, 0, 0, 0, 0, 0))) { lib$free_ef(&efn); return (0); } itmlst.last = inmbxname.length = 0; itmlst.address = inmbxname.ptr = inmname; itmlst.retlen = &inmbxname.length; itmlst.code = DVI$_DEVNAM; itmlst.len = 64; if (!OK(sys$getdviw(0, ichan, 0, &itmlst, 0, 0, 0, 0))) { lib$free_ef(&efn); return (0); } inmname[inmbxname.length] = EOS; /* create and open the output mailbox */ if (!OK(sys$crembx(0, &ochan, 0, 0, 0, 0, 0))) { lib$free_ef(&efn); return (0); } itmlst.last = outmbxname.length = 0; itmlst.address = outmbxname.ptr = outmname; itmlst.retlen = &outmbxname.length; if (!OK(sys$getdviw(0, ochan, 0, &itmlst, 0, 0, 0, 0))) { lib$free_ef(&efn); return (0); } outmname[outmbxname.length] = EOS; pfile = open(outmname, O_RDONLY, S_IREAD); if (pfile < 0) { lib$free_ef(&efn); sys$dassgn(ichan); sys$dassgn(ochan); return (0); } /* Save file information now */ pd = &_pipes[pfile]; /* get Pipe pointer */ pd->pid = pd->status = pd->running = 0; pd->flags = SFLAGS; pd->ichan = ichan; pd->ochan = ochan; pd->efn = efn; /* Initiate the command by writing down the input mailbox (SYS$INPUT). */ if (fd > 0) { char pre_command[132+12]; (void)strcpy (pre_command, "DEFINE/USER SYS$INPUT "); (void)strcat (pre_command, input_file); if (!OK( sys$qiow(0, ichan, IO$_WRITEVBLK | IO$M_NOW, 0, 0, 0, pre_command, strlen(pre_command), 0, 0, 0, 0))) { lib$free_ef(&efn); sys$dassgn(ichan); sys$dassgn(ochan); return (0); } } if (!OK( sys$qiow(0, ichan, IO$_WRITEVBLK | IO$M_NOW, 0, 0, 0, cmd, strlen(cmd), 0, 0, 0, 0))) { ; } else if (!OK( sys$qiow(0, ichan, IO$_WRITEOF | IO$M_NOW, 0, 0, 0, 0, 0, 0, 0, 0, 0))) { ; } else if (!OK( lib$spawn(0, &inmbxname, /* input file */ &outmbxname, /* output file */ &pd->flags, 0, &pd->pid, &pd->status, &pd->efn, 0, 0, 0, 0))) { ; } else { FILE *pp; int len; int count = 0; char buffer[MAXBFR]; pd->running = 1; /* * For our application, we need a file-pointer. Empty the * pipe into a temporary file. Unfortunately, this means that * the application will use 'slowreadf()' to write the data. */ if (pp = tmpfile()) { for_ever { len = vms_pread(pfile, buffer, sizeof(buffer)); if (len <= 0) break; fwrite(buffer, sizeof(*buffer), len, pp); count++; } mlforce("[Read %d lines from %s ]", count, cmd); vms_rpclose(pfile); (void)fflush(pp); rewind(pp); return pp; } return (0); } lib$free_ef(&efn); sys$dassgn(ichan); sys$dassgn(ochan); return (0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.