minow@decvax.UUCP (Martin Minow) (04/27/87)
In article <224@unc.cs.unc.edu> mcguffey@unc.cs.unc.edu (Michael McGuffey) requests a method to allow command line redirection under VMS. What I use follows the signature. Martin Minow decvax!minow main(argc, argv) int argc; char *argv[]; { #ifdef vms argc = getredirection(argc, argv); #endif ... } -------- /* * getredirection() is intended to aid in porting C programs * to VMS (Vax-11 C) which does not support '>' and '<' * I/O redirection. With suitable modification, it may * useful for other portability problems as well. */ static int getredirection(argc, argv) int argc; char **argv; /* * Process vms redirection arg's. Exit if any error is seen. * If getredirection() processes an argument, it is erased * from the vector. getredirection() returns a new argc value. * * Warning: do not try to simplify the code for vms. The code * presupposes that getredirection() is called before any data is * read from stdin or written to stdout. * * Normal usage is as follows: * * main(argc, argv) * int argc; * char *argv[]; * { * argc = getredirection(argc, argv); * } */ { #ifdef vms register char *ap; /* Argument pointer */ int i; /* argv[] index */ int j; /* Output index */ int file; /* File_descriptor */ extern int errno; /* Last vms i/o error */ for (j = i = 1; i < argc; i++) { /* Do all arguments */ switch (*(ap = argv[i])) { case '<': /* <file */ if (freopen(++ap, "r", stdin) == NULL) { perror(ap); /* Can't find file */ exit(errno); /* Is a fatal error */ } case '>': /* >file or >>file */ if (*++ap == '>') { /* >>file */ /* * If the file exists, and is writable by us, * call freopen to append to the file (using the * file's current attributes). Otherwise, create * a new file with "vanilla" attributes as if * the argument was given as ">filename". * access(name, 2) is TRUE if we can write on * the specified file. */ if (access(++ap, 2) == 0) { if (freopen(ap, "a", stdout) != NULL) break; /* Exit case statement */ perror(ap); /* Error, can't append */ exit(errno); /* After access test */ } /* If file accessable */ } /* * On vms, we want to create the file using "standard" * record attributes. create(...) creates the file * using the caller's default protection mask and * "variable length, implied carriage return" * attributes. dup2() associates the file with stdout. */ if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1 || dup2(file, fileno(stdout)) == -1) { perror(ap); /* Can't create file */ exit(errno); /* is a fatal error */ } /* If '>' creation */ break; /* Exit case test */ default: argv[j++] = ap; /* Not a redirector */ break; /* Exit case test */ } } /* For all arguments */ return (j); #else /* * Note: argv[] is referenced to fool the Decus C * syntax analyser, supressing an unneeded warning * message. */ return (argv[0], argc); /* Just return as seen */ #endif }
gwalker@SPCA.BBN.COM.UUCP (04/27/87)
The following are the ways I know of to get stdio redirection on VMS. This is just a summary and doesn't give a lot of details. Whether these work out for you may depend on what programs you are trying to use this way and even what language they are written in. 1. For all programs that use SYS$OUTPUT (stdout for VMS) for their output (as most do) you can either a) use ASSIGN/USER somefile SYS$OUTPUT just before running the program to make everything directed to SYS$OUTPUT go to the file "somefile" instead OR b) Put the call to your program in a command file and invoke it with @commandfile /OUTPUT=somefile to redirect the output. (If the program takes input from the terminal you need to ASSIGN/USER SYS$COMMAND SYS$INPUT before running the program from the command file.) There may be some cases where the file comes out funny if the program is one that believes its output is always a terminal, or anything like that. I guess the best way to know if these will meet your needs is to try them. On the input side (SYS$INPUT), method (a) can be used: ASSIGN/USER myinfile SYS$INPUT also in command files you can follow the call to the program with the input itself (the input data lines just don't start with a '$' sign.) 2. For VMS commands, many of them now have a /OUTPUT switch to allow you to redirect their output to a file. 3. If what you really want is to have your programs accept ">somefile" or "<myinfile" on their command line and redirect output or input, they would have to be explicitly written to look for that construct. I don't know offhand if VAX C and its runtime library will do this for you automatically, I haven't used the VAX C runtime library, but it is just possible that it will handle this for you for programs written in VAX C. -- Gail Walker
carl@CITHEX.CALTECH.EDU.UUCP (04/27/87)
> Does anyone know of any tools that allow command line redirection of > stdio under VMS. Something similar to the way unix and msdos does it is > preferable to some of the methods that have previously been proposed. The following is C code to do at least more or less what you want. First a short rationale for using the technique I did, rather than something else: The C run time library does things like setting up the array of io blocks and parsing the command line for you; while I could have written code to do this, and then linked this code with everything I wrote, I decided to use the default startup routines, and then to do any I/O redirection later. The end result is a routine called ioinit that is used as follows: main(nargs, args) int nargs; char **args; { ... ioinit(&nargs, args); ... } It redirects any or all of stdin, stdout, or stderr, using the same syntax as under UNIX* (with the exception of "here documents"); /******************************************************************************/ /* IOINIT.C -- I/O redirection subroutine. Redirects stdin (< or <<); * stdout (> or >>); or stderr ( 2>, 2>>) * Usage: * main(nargs, args) * { ... * ioinit(&nargs, args); * ... * } */ #include <errno.h> #include <stdio.h> typedef char *STR; ioinit(nargs, args) int *nargs; STR *args; { int argnum; for (argnum = 1; argnum < *nargs; ++argnum) { if (strncmp(args[argnum], "<", 1) == 0) { args[argnum] += 1; *nargs = u_reopen(*nargs, args, argnum, "r", stdin); argnum--; } else if (strncmp(args[argnum], ">>", 2) == 0) { args[argnum] += 2; *nargs = u_reopen(*nargs, args, argnum, "a", stdout); argnum--; } else if (strncmp(args[argnum], ">", 1) == 0) { args[argnum] += 1; *nargs = u_reopen(*nargs, args, argnum, "w", stdout); argnum--; } else if (strncmp(args[argnum], "2>>", 3) == 0) { args[argnum] += 3; *nargs = u_reopen(*nargs, args, argnum, "a", stderr); argnum--; } else if (strncmp(args[argnum], "2>", 2) == 0) { args[argnum] += 2; *nargs = u_reopen(*nargs, args, argnum, "w", stderr); argnum--; } } } u_reopen(nargs, args, argnum, acmod, chan) int nargs, argnum; STR *args, acmod; FILE *chan; { char *file; int offset, i, errornum; if (args[argnum][0] != '\0') { offset = 1; file = args[argnum]; } else if ((argnum + 1) < nargs) { offset = 2; file = args[argnum+1]; } else { fprintf(stderr, "Illegal redirection on command line.\n"); exit(1); } for (i = argnum; i < nargs - offset; ++i) args[i] = args[i + offset]; if (((*acmod == ' ' || strcmp(acmod,"a+") == 0) && freopen(file, acmod, chan ,"rfm=stm") != chan) || freopen(file, acmod, chan) != chan) { if (errno == EVMSERR) { errornum = vaxc$errno; fprintf(stderr, "Failure opening redirected stream.\n"); exit(errornum); } else { perror("Failure opening redirected stream."); exit(1); } } return(nargs - offset); } /******************************************************************************/ Using this as a starting point, you should be able to tailor it to your needs.
LEICHTER-JERRY@YALE.ARPA.UUCP (04/28/87)
To: unc!mcguffey@mcnc.org (Michael McGuffey) Does anyone know of any tools that allow command line redirection of stdio under VMS. Something similar to the way unix and msdos does it is preferable to some of the methods that have previously been proposed. The following is from the DECUS C library; it's meant for programs written in C - which seems to be what you have in mind - though it could be adapted for other languages. getredirection() was written by Martin Minow. Note that the code dates back to V1 of C; some of it could be simplified, as you no longer need to creat/fdopen's to get at various RMS options. -- Jerry /* * getredirection() is intended to aid in porting C programs * to VMS (Vax-11 C) which does not support '>' and '<' * I/O redirection. With suitable modification, it may * useful for other portability problems as well. * * Modified, 24-Jan-86 by Jerry Leichter * When creating a new output file, force the maximum record size to * 512; otherwise, it ends up as 0 (though the C I/O system won't write * a record longer than 512 bytes anyway) which will cause problems if * the file is later opened for APPEND - if the maximum record size is * 0, C will use the length of the longest record written to the file * for its buffer! [This was a C RTL bug, probably since fixed.] */ #ifdef vms #include <stdio.h> #include <errno.h> int getredirection(argc, argv) int argc; char **argv; /* * Process vms redirection arg's. Exit if any error is seen. * If getredirection() processes an argument, it is erased * from the vector. getredirection() returns a new argc value. * * Warning: do not try to simplify the code for vms. The code * presupposes that getredirection() is called before any data is * read from stdin or written to stdout. * * Normal usage is as follows: * * main(argc, argv) * int argc; * char *argv[]; * { * argc = getredirection(argc, argv); * } */ { register char *ap; /* Argument pointer */ int i; /* argv[] index */ int j; /* Output index */ int file; /* File_descriptor */ for (j = i = 1; i < argc; i++) { /* Do all arguments */ switch (*(ap = argv[i])) { case '<': /* <file */ if (freopen(++ap, "r", stdin) == NULL) { perror(ap); /* Can't find file */ exit(errno); /* Is a fatal error */ } break; case '>': /* >file or >>file */ if (*++ap == '>') { /* >>file */ /* * If the file exists, and is writable by us, * call freopen to append to the file (using the * file's current attributes). Otherwise, create * a new file with "vanilla" attributes as if * the argument was given as ">filename". * access(name, 2) is TRUE if we can write on * the specified file. */ if (access(++ap, 2) == 0) { if (freopen(ap, "a", stdout) != NULL) break; /* Exit case statement */ perror(ap); /* Error, can't append */ exit(errno); /* After access test */ } /* If file accessable */ } /* * On vms, we want to create the file using "standard" * record attributes. create(...) creates the file * using the caller's default protection mask and * "variable length, implied carriage return" * attributes. dup2() associates the file with stdout. */ if ((file = creat(ap, 0, "rat=cr", "rfm=var", "mrs=512")) == -1 || dup2(file, fileno(stdout)) == -1) { perror(ap); /* Can't create file */ exit(errno); /* is a fatal error */ } /* If '>' creation */ break; /* Exit case test */ default: argv[j++] = ap; /* Not a redirector */ break; /* Exit case test */ } } /* For all arguments */ argv[j] = NULL; /* Terminate argv[] */ return (j); /* Return new argc */ } #else getredirection(argc, argv) int argc; char *argv[]; /* * Dummy routine. */ { return (argv[0], argc); } #endif -------
gdw@ssl-macc.co.uk (Grenville Whelan) (04/30/87)
In article <224@unc.cs.unc.edu> mcguffey@unc.cs.unc.edu (Michael McGuffey) writes: > >Does anyone know of any tools that allow command line redirection of >stdio under VMS. Something similar to the way unix and msdos does it is >preferable to some of the methods that have previously been proposed. > >-mike mcguffey Simply redirect the logical SYS$OUTPUT to a file rather than the terminal, ie. $ ASSIGN <FILE> SYS$OUTPUT $ <commands> $ DEASSIGN SYS$OUTPUT -- # Grenville Whelan - Software Sciences Ltd, Park Street, Macclesfield, UK # # (EMAIL gdw@uk.co.ssl-macc) (UUCP !mcvax!ukc!mcvax!gdw) (TEL +44 625 29241) # "Are you the Police?" "No ma'am, we're musicians!" -- Elwood.
jimp@cognos.uucp (Jim Patterson) (05/02/87)
In article <8704272220.AA01440@ucbvax.Berkeley.EDU> gwalker@SPCA.BBN.COM.UUCP writes: >The following are the ways I know of to get stdio >redirection on VMS. >1. For all programs that use SYS$OUTPUT (stdout for VMS) for their output (as > most do) you can either > a) use > ASSIGN/USER somefile SYS$OUTPUT >On the input side (SYS$INPUT), method (a) can be used: > ASSIGN/USER myinfile SYS$INPUT For VAX 11 C users, ASSIGN/USER doesn't work. You can use ASSIGN (which assigns a supervisor-level logical), but of course you have to remember to DEASSIGN it after. As near as I can figure out, this is because the VAX 11 C I/O interface doesn't actually open the standard input/output files but instead relies on the process-permanent file opens. You can also do your own I/O redirection as noted in some of the other articles. No, VAX 11 C won't do this for you (or at least it won't for me). There is a product called VAX Shell that I think does all of this redirection etc. for you. I haven't used it, though, so have no idea how it works or what it does for you. From what I know of it, VAX Shell gives you a UNIX-like shell environment to replace the VMS DCL environment. -- Jim Patterson Cognos Inc.
kenw@noah.arc.CDN (Ken Wallewein) (05/02/87)
A while back, I wrote a set of DCL command files to perform piping a la unix. It allows me to say things like pipe dir | dups > purgable.lst. I write a number of filters and filter templates in TECO, C, BASIC, and DCL. The redirection was just a tad tricky, and I learned a bit about logical device handling. I used temporary files and sequential processing rather than pipes between spawned processes, but that is irrelevant to the redirection aspect. Also easier under restrictive environments. Anyway, I could provide it (post it, whatever) if anybody's interested. /kenw
gore@nucsrl.UUCP (05/03/87)
>Does anyone know of any tools that allow command line redirection of >stdio under VMS. Something similar to the way unix and msdos does it is >preferable to some of the methods that have previously been proposed. > >-mike mcguffey $ run/input=input_file/output=output_file program is all it takes. Note that you do have to have both /input and /output. If you want one of them to remain your terminal, use /input=TT: or /output=TT:. If you don't have any input, use /input=NLA0: (the null device). Warning: this is all from memory. Use HELP RUN to confirm this. Jacob Gore Northwestern University, Computer Science Research Lab {gargoyle,ihnp4,chinet}!nucsrl!gore gore@EECS.NWU.Edu (for now, only from ARPA)