[news.software.anu-news] sending old articles to new client - BATCHNEWS 2/2

mark@infopiz.uucp (02/19/90)

+-+-+-+ Beginning of part 2 +-+-+-+
X    char `009`009*out = NULL;`009/* Output File Name`009    */
X    char `009`009*outmode = "w";`009/* Mode to Open Output File */
X    int`009`009`009cmargc = 0;    `009/* Piped Command Arg Count  */
X    char`009`009**cmargv = NULL;/* Piped Command Arg Vector */
X
X    /*
X     * First handle the case where the last thing on the line ends with
X     * a '&'.  This indicates the desire for the command to be run in a
X     * subprocess, so we satisfy that desire.
X     */
X    ap = argv[argc-1];
X    if (0 == strcmp("&", ap))
X`009exit(background_process(--argc, argv));
X    if ('&' == ap[strlen(ap)-1])
X`009`123
X`009ap[strlen(ap)-1] = '\0';
X`009exit(background_process(argc, argv));
X`009`125
X    /*
X     * Now we handle the general redirection cases that involve '>', '>>',
X     * '<', and pipes '`124'.
X     */
X    for (j = 0; j < argc; ++j)
X`009`123
X`009if (0 == strcmp("<", argv[j]))
X`009    `123
X`009    if (j+1 >= argc)
X`009`009`123
X`009`009errno = EINVAL;
X`009`009perror("No input file");
X`009`009exit(EXIT_ERR);
X`009`009`125
X`009    in = argv[++j];
X`009    continue;
X`009    `125
X`009if ('<' == *(ap = argv[j]))
X`009    `123
X`009    in = 1 + ap;
X`009    continue;
X`009    `125
X`009if (0 == strcmp(">", ap))
X`009    `123
X`009    if (j+1 >= argc)
X`009`009`123
X`009`009errno = EINVAL;
X`009`009perror("No output file");
X`009`009exit(EXIT_ERR);
X`009`009`125
X`009    out = argv[++j];
X`009    continue;
X`009    `125
X`009if ('>' == *ap)
X`009    `123
X`009    if ('>' == ap[1])
X`009`009`123
X`009`009outmode = "a";
X`009`009if ('\0' == ap[2])
X`009`009    out = argv[++j];
X`009`009else
X`009`009    out = 2 + ap;
X`009`009`125
X`009    else
X`009`009out = 1 + ap;
X`009    continue;
X`009    `125
X`009if (0 == strcmp("`124", argv[j]))
X`009    `123
X`009    if (j+1 >= argc)
X`009`009`123
X`009`009errno = EPIPE;
X`009`009perror("No command to Pipe to");
X`009`009exit(EXIT_ERR);
X`009`009`125
X`009    cmargc = argc-(j+1);
X`009    cmargv = &argv[j+1];
X`009    argc = j;
X`009    continue;
X`009    `125
X`009if ('`124' == *(ap = argv[j]))
X`009    `123
X`009    ++argv[j];
X`009    cmargc = argc-j;
X`009    cmargv = &argv[j];
X`009    argc = j;
X`009    continue;
X`009    `125
X`009expand_wild_cards(ap, &list_head, &list_tail, &item_count);
X`009`125
X    /*
X     * Allocate and fill in the new argument vector, Some Unix's terminate
X     * the list with an extra null pointer.
X     */
X    argv = *av = calloc(item_count+1, sizeof(char *));
X    for (j = 0; j < item_count; ++j, list_head = list_head->next)
X`009argv[j] = list_head->value;
X    *ac = item_count;
X    if (cmargv != NULL)
X`009`123
X`009char subcmd[1024];
X`009static char *pipe_and_fork();
X
X`009if (out != NULL)
X`009    `123
X`009    errno = EINVAL;
X`009    perror("Invalid '`124' and '>' specified");
X`009    exit(EXIT_ERR);
X`009    `125
X`009strcpy(subcmd, cmargv[0]);
X`009for (j = 1; j < cmargc; ++j)
X`009    `123
X`009    strcat(subcmd, " \"");
X`009    strcat(subcmd, cmargv[j]);
X`009    strcat(subcmd, "\"");
X`009    `125
X`009out = pipe_and_fork(subcmd);
X`009`125
X    if ((in != NULL) && (NULL == freopen(in, "r", stdin, "mbc=32", "mbf=2")))
X`009`123
X`009perror(in);    `009       `009/* Can't find file`009`009*/
X`009exit(EXIT_ERR);`009`009/* Is a fatal error`009`009*/
X`009`125
V    if ((out != NULL) && (NULL == freopen(out, outmode, stdout, "mbc=32", "mbf=
X2")))
X`009`123`009
X`009perror(ap);`009`009/* Error, can't write or append`009*/
X`009exit(EXIT_ERR);`009`009/* Is a fatal error`009`009*/
X`009`125
X#ifdef DEBUG
X    fprintf(stderr, "Arglist:\n");
X    for (j = 0; j < *ac;  ++j)
X`009fprintf(stderr, "argv[%d] = '%s'\n", j, argv[j]);
X#endif
X`125
X
Xstatic add_item(head, tail, value, count)
Xstruct list_item **head;
Xstruct list_item **tail;
Xchar *value;
Xint *count;
X`123
X    if (*head == 0)
X`009`123
X`009if (NULL == (*head = calloc(1, sizeof(**head))))
X`009    `123
X`009    errno = ENOMEM;
X`009    perror("");
X`009    exit(EXIT_ERR);
X`009    `125
X`009*tail = *head;
X`009`125
X    else
X`009if (NULL == ((*tail)->next = calloc(1, sizeof(**head))))
X`009    `123
X`009    errno = ENOMEM;
X`009    perror("");
X`009    exit(EXIT_ERR);
X`009    `125
X`009else
X`009    *tail = (*tail)->next;
X    (*tail)->value = value;
X    ++(*count);
X`125
X
Xstatic expand_wild_cards(item, head, tail, count)
Xchar *item;
Xstruct ltem_list **head;
Xstruct ltem_list **tail;
Xint *count;
X`123
Xint expcount = 0;
Xint context = 0;
Xint status;
Xint status_value;
Xint had_version;
X$DESCRIPTOR(filespec, item);
X$DESCRIPTOR(defaultspec, "SYS$DISK:[]*.*;");
X$DESCRIPTOR(resultspec, "");
X
X    if (strcspn(item, "*%") == strlen(item))
X`009`123
X`009add_item(head, tail, item, count);
X`009return;
X`009`125
X    resultspec.dsc$b_dtype = DSC$K_DTYPE_T;
X    resultspec.dsc$b_class = DSC$K_CLASS_D;
X    resultspec.dsc$a_pointer = NULL;
X    filespec.dsc$w_length = strlen(item);
X    /*
X     * Only return version specs, if the caller specified a version
X     */
X    had_version = strchr(item, ';');
X    while (1 == (1&lib$find_file(&filespec, &resultspec, &context,
X    `009`009`009`009 &defaultspec, 0, &status_value, &0)))
X`009`123
X`009char *string;
X`009char *c;
X
X`009if (NULL == (string = calloc(1, resultspec.dsc$w_length+1)))
X`009    `123
X`009    errno = ENOMEM;
X`009    perror("");
X`009    exit(EXIT_ERR);
X`009    `125
X`009strncpy(string, resultspec.dsc$a_pointer, resultspec.dsc$w_length);
X`009string[resultspec.dsc$w_length] = '\0';
X`009if (NULL == had_version)
X`009    *((char *)strrchr(string, ';')) = '\0';
X`009/*
X`009 * Be consistent with what the C RTL has already done to the rest of
X`009 * the argv items and lowercase all of these names.
X`009 */
X`009for (c = string; *c; ++c)
X`009    if (isupper(*c))
X`009`009*c = tolower(*c);
X`009add_item(head, tail, string, count);
X`009++expcount;
X`009`125
X    if (expcount == 0)
X`009add_item(head, tail, item, count);
X    lib$sfree1_dd(&resultspec);
X    lib$find_file_end(&context);
X`125
X
Xstatic int child_st[2];`009/* Event Flag set when child process completes`009*/
X
Xstatic short child_chan;/* I/O Channel for Pipe Mailbox`009`009`009*/
X
Xstatic exit_handler(status)
Xint *status;
X`123
Xshort iosb[4];
X
X    if (0 == child_st[0])
X`009`123
X#ifdef DEBUG
X`009fprintf(stderr, "Waiting for Child Process to Finnish . . .\n");
X#endif
X`009sys$qiow(0, child_chan, IO$_WRITEOF, iosb, 0, 0, 0, 0, 0, 0, 0, 0);
X`009sys$dassgn(child_chan);
X`009fclose(stdout);
X`009sys$synch(0, child_st);
X`009`125
X`125
X
X#include syidef`009`009/* System Information Definitions`009*/
X
Xstatic sig_child(chan)
Xint chan;
X`123
X#ifdef DEBUG
X    fprintf(stderr, "Child Completion AST\n");
X#endif
X    if (child_st[0] == 0)
X`009child_st[0] = 1;
X`125
X
Xstatic struct exit_control_block
X    `123
X    struct exit_control_block *flink;
X    int`009(*exit_routine)();
X    int arg_count;
X    int *status_address;
X    int exit_status;
X    `125 exit_block =
X    `123
X    0,
X    exit_handler,
X    1,
X    &exit_block.exit_status,
X    0
X    `125;
X
Xstatic char *pipe_and_fork(cmd)
Xchar *cmd;
X`123
X    $DESCRIPTOR(cmddsc, cmd);
X    static char mbxname[64];
X    $DESCRIPTOR(mbxdsc, mbxname);
X    short iosb[4];
X    int status;
X    int pid;
X    struct
X`009`123
X`009short dna_buflen;
X`009short dna_itmcod;
X`009char *dna_buffer;
X`009short *dna_retlen;
X`009int listend;
X`009`125 itmlst =
X`009`123
X`009sizeof(mbxname),
X`009DVI$_DEVNAM,
X`009mbxname,
X`009&mbxdsc.dsc$w_length,
X`0090
X`009`125;
X    int mbxsize;
X    struct
X`009`123
X`009short mbf_buflen;
X`009short mbf_itmcod;
X`009int *mbf_maxbuf;
X`009short *mbf_retlen;
X`009int listend;
X`009`125 syiitmlst =
X`009`123
X`009sizeof(mbxsize),
X`009SYI$_MAXBUF,
X`009&mbxsize,
X`0090,
X`0090
X`009`125;
X
X    cmddsc.dsc$w_length = strlen(cmd);
X    /*
X     * Get the SYSGEN parameter MAXBUF, and the smaller of it and 2048 as
X     * the size of the 'pipe' mailbox.
X     */
V    if (1 == (1&(vaxc$errno = sys$getsyiw(0, 0, 0, &syiitmlst, iosb, 0, 0, 0)))
X)
X`009vaxc$errno = iosb[0];
X    if (0 == (1&vaxc$errno))
X`009`123
X `009errno = EVMSERR;
X`009perror("Can't get SYSGEN parameter value for MAXBUF");
X`009exit(EXIT_ERR);
X`009`125
X    if (mbxsize > 2048)
X`009mbxsize = 2048;
V    if (0 == (1&(vaxc$errno = sys$crembx(0, &child_chan, mbxsize, mbxsize, 0, 0
X, 0))))
X`009`123
X`009errno = EVMSERR;
X`009perror("Can't create pipe mailbox");
X`009exit(EXIT_ERR);
X`009`125
X    if (1 == (1&(vaxc$errno = sys$getdviw(0, child_chan, 0, &itmlst, iosb,
X    `009`009`009`009`009  0, 0, 0))))
X`009vaxc$errno = iosb[0];
X    if (0 == (1&vaxc$errno))
X`009`123
X `009errno = EVMSERR;
X`009perror("Can't get pipe mailbox device name");
X`009exit(EXIT_ERR);
X`009`125
X    mbxname[mbxdsc.dsc$w_length] = '\0';
X#ifdef DEBUG
X    fprintf(stderr, "Pipe Mailbox Name = '%s'\n", mbxname);
X#endif
X    if (0 == (1&(vaxc$errno = lib$spawn(&cmddsc, &mbxdsc, 0, &1,
X    `009`009`009`009`0090, &pid, child_st, &0, sig_child,
X    `009`009`009`009`009&child_chan))))
X`009`123
X`009errno = EVMSERR;
X`009perror("Can't spawn subprocess");
X`009exit(EXIT_ERR);
X`009`125
X#ifdef DEBUG
X    fprintf(stderr, "Subprocess's Pid = %08X\n", pid);
X#endif
X    sys$dclexh(&exit_block);
X    return(mbxname);
X`125
X
Xbackground_process(argc, argv)
Xint argc;
Xchar **argv;
X`123
Xchar command[2048] = "$";
X$DESCRIPTOR(value, command);
X$DESCRIPTOR(cmd, "BACKGROUND$COMMAND");
X$DESCRIPTOR(null, "NLA0:");
Xint pid;
X
X    strcat(command, argv[0]);
X    while (--argc)
X`009`123
X`009strcat(command, " \"");
X`009strcat(command, *(++argv));
X`009strcat(command, "\"");
X`009`125
X    value.dsc$w_length = strlen(command);
X    if (0 == (1&(vaxc$errno = lib$set_symbol(&cmd, &value))))
X`009`123
X`009errno = EVMSERR;
X`009perror("Can't create symbol for subprocess command");
X`009exit(EXIT_ERR);
X`009`125
X    if (0 == (1&(vaxc$errno = lib$spawn(&cmd, &null, 0, &17, 0, &pid))))
X`009`123
X`009errno = EVMSERR;
X`009perror("Can't spawn subprocess");
X`009exit(EXIT_ERR);
X`009`125
X#ifdef DEBUG
X    fprintf(stderr, "%s\n", command);
X#endif
X    fprintf(stderr, "%08X\n", pid);
X    return(EXIT_OK);
X`125
X`012
X/* got this off net.sources */
X
X#ifdef`009VMS
X#define`009index`009strchr
X#endif`009/*VMS*/
X
X/*
X * get option letter from argument vector
X */
Xint`009opterr = 1,`009`009/* useless, never set or used */
X`009optind = 1,`009`009/* index into parent argv vector */
X`009optopt;`009`009`009/* character checked for validity */
Xchar`009*optarg;`009`009/* argument associated with option */
X
X#define BADCH`009(int)'?'
X#define EMSG`009""
X#define tell(s)`009fputs(*nargv,stderr);fputs(s,stderr); \
X`009`009fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
X
Xgetopt(nargc,nargv,ostr)
Xint`009nargc;
Xchar`009**nargv,
X`009*ostr;
X`123
X`009static char`009*place = EMSG;`009/* option letter processing */
X`009register char`009*oli;`009`009/* option letter list index */
X`009char`009*index();
X
X`009if(!*place) `123`009`009`009/* update scanning pointer */
V`009`009if(optind >= nargc `124`124 *(place = nargv[optind]) != '-' `124`124 !*
X++place) return(EOF);
X`009`009if (*place == '-') `123`009/* found "--" */
X`009`009`009++optind;
X`009`009`009return(EOF);
X`009`009`125
X`009`125`009`009`009`009/* option letter okay? */
V`009if ((optopt = (int)*place++) == (int)':' `124`124 !(oli = index(ostr,optopt
X))) `123
X`009`009if(!*place) ++optind;
X`009`009tell(": illegal option -- ");
X`009`125
X`009if (*++oli != ':') `123`009`009/* don't need argument */
X`009`009optarg = NULL;
X`009`009if (!*place) ++optind;
X`009`125
X`009else `123`009`009`009`009/* need an argument */
X`009`009if (*place) optarg = place;`009/* no white space */
X`009`009else if (nargc <= ++optind) `123`009/* no arg */
X`009`009`009place = EMSG;
X`009`009`009tell(": option requires an argument -- ");
X`009`009`125
X`009 `009else optarg = nargv[optind];`009/* white space */
X`009`009place = EMSG;
X`009`009++optind;
X`009`125
X`009return(optopt);`009`009`009/* dump back option letter */
X`125
$ GOSUB UNPACK_FILE
$ EXIT
-+-+-+-+-+ End of part 2 +-+-+-+-+-