/* RTRSX.C - Read directories and files from an RSX volume 19-May-83 */ /* Placed in the public domain by: Bryan Kattwinkel * 520 Palm Springs Blvd #502 * Indian Harbour Beach, FL 32937 * * Adapted from the Unix program GETRSX written by Mark Bartelt. * * An RT-11 style command line is used: outfile=infile/switch * * /D List an RSX directory (otherwise transfer file). * /I Transfer in image mode (otherwise text mode assumed). * /N Do not add newlines in text conversion (otherwise add newlines). * /T Input file is on an RT-11 volume (otherwise RSX assumed). * * The output file is RT-11, and the input file is RSX. The /T switch * may be used to translate an RSX text file which is already on an * RT-11 volume, otherwise an RSX volume is expected. * * Transfer modes supported are text (default) - FCS stuff is thrown * away and newline is tacked on the end of each RSX record, and image * (/I) - straight byte-by-byte transfer. The /N switch prevents * newlines from being added in text mode, for files such as RUNOFF * output which contain imbedded carriage control. It might be nicer to * use the record attributes (RATT) byte to do this, but that would open * up a can of worms, and the RATT is not available with the /T switch. * * The input filename syntax is the same as the standard RSX naming * scheme, which differs from RT-11 in that a UFD can appear between * the device and filename, the filename can be up to 9 characters, * and a semicolon and octal version number can be tacked on the end. * The default input device and UFD are RSX:[0,0]. These are "sticky", * any explicit input device or UFD becomes the new default. * * If no output file is specified, TT: is assumed. Otherwise, the * default device is DK:, and the default filename and type are derived * from the input filespec (specify neither or both). * * The /D switch is used to get a directory of a UFD. A directory of * [0,0] provides a list of all the UFD's on the volume. Wildcards are * not supported in the directory operation, but the directory can be * written to an RT-11 file and processed with grep, sortc, etc. * * Link command: LINK/BOT:2400 RTRSX,RSXSUB,DOPEN,C:(SUPORT,CLIB) */ #include int $$narg = 1; /* suppress argv prompt */ FILE *rsx = NULL; /* global rsx device file vector */ int nflag = 0; /* global newline flag */ typedef unsigned ushort; /* 16 bits unsigned */ #define DIRBEG '[' #define DIREND ']' #define NULLCHR '\0' #define NULLSTR "" #define TEXT 0 #define IMAGE 1 static char defdev[4] = "RSX"; /* default input device */ static char defufd[8] = "0,0"; /* default ufd */ static char lsflag; /* Nonzero ==> list directory */ static char rtflag; /* Nonzero ==> rt11 input file */ static int xfermode; /* Transfer mode, TEXT or IMAGE */ /* Pointers to filename fields */ static char *dev, *dir, *fil, *typ, *ver; static char prompt[2] = { '*', '\200' }; /* CSI prompt for GTLIN */ static int env[6]; /* environment save for longjmp */ /* simplifies error handling */ static FILE *ttsave; /* saved iov for TT: output */ /* Note: due to bugs in the DECUS library, TT: should not be repeatedly */ /* closed and reopened for output, since the iov is never freed. Also, */ /* any attempt to open TT: in "wn" mode will corrupt dynamic storage, */ /* since $$flsh requires a guard byte which $$flun does not allocate. */ /* Extra carriage returns caused by the "w" mode (for TT: output only) */ /* should be invisible. */ main () /* note: argc and argv not used */ { register char *pos; char cmd[82]; extern gtlin (); /* fortran subroutine from syslib */ ttsave = stdout; /* HACK: save stdout opened to TT: */ while (1) /* loop through commands */ { if (setjmp (env)) /* errors will return here */ { if (rsx != NULL) fclose (rsx); /* close rsx on error */ rsx = NULL; } if (stdout == ttsave) fflush (stdout); /* make sure TT: flushed */ else if (stdout != NULL) fclose (stdout); /* else stdout closed */ stdout = NULL; nflag = 0; lsflag = 0; /* reset mode flags */ rtflag = 0; xfermode = TEXT; call (gtlin, 2, cmd, prompt); /* get a command (file) line */ if (cmd[0] == '\0') usage (); /* empty input line */ else { /* look for a switch */ if ((pos = index (cmd, '/')) != NULL) { options (pos); /* process switches */ *pos = '\0'; /* terminate filenames */ } getrsx (cmd); /* now really do it */ if (ferror (stdout)) err0 ("Write error"); /* check for stdout error */ if (dev != NULL && rtflag == 0) /* success, set defaults */ strcpy (defdev, dev); /* for next time through */ if (dir != NULL) strcpy (defufd, dir); } } } static usage() { err1 ("usage: [rtoutfile=]rsxinfile[/switches]\n\t%s", "/D-directory /I-image /N-no newlines /T-rtinfile"); } /* * Process option flags */ static options (ix) char *ix; { while (*ix++ == '/') switch (toupper (*ix++)) { case 'D': ++lsflag; break; case 'I': xfermode = IMAGE; break; case 'N': ++nflag; break; case 'T': ++rtflag; break; default: usage (); break; } if (*--ix != '\0') usage (); if ((rtflag || nflag) && (lsflag || xfermode != TEXT)) err0 ("Incompatible switches"); } /* * Open files and choose function */ static getrsx (cmd) char *cmd; { register char *pos; char dirname [7]; /* default name for directory file */ if ((pos = index (cmd, '=')) == NULL) pos = cmd; /* no output file */ else *pos++ = '\0'; /* or split them */ if (rtflag) rtfile (cmd, pos); /* get file from rt11 */ else /* or deal with RSX volume */ { crack (pos); /* parse filename */ if (dev != NULL) rsxdev (dev); /* specified device */ else if (rsx == NULL) rsxdev (defdev); /* or default */ if (dir != NULL) rsxdir (dir, dirname); /* find directory */ else rsxdir (defufd, dirname); /* or default */ if (lsflag) /* directory list */ { /* open output file */ openout ((pos == cmd) ? NULLSTR : cmd, dirname); if (*fil != NULLCHR || *typ != NULLCHR || *ver != NULLCHR) fprintf (stderr, "?RTRSX-W-Filename ignored for directory\n\n"); listdir (); /* list directory */ } else /* or file copy */ { if (*fil == NULLCHR) err0 ("Input filename required"); rsxfile (fil, typ, ver); /* open rsx file */ openout ((pos == cmd) ? NULLSTR : cmd); /* open output file */ copyfile (xfermode); /* and copy it over */ } } } /* * Crack the filename string -- First step in parsing it; just * locates the fields, doesn't do much real validity checking */ static crack (inf) char *inf; /* input filestring */ { register char *q; register char *p; p = inf; /* make this handy */ dev = NULL; dir = NULL; /* init to nothing */ fil = NULLSTR; typ = NULLSTR; /* note nullstr here */ ver = NULLSTR; if ((q = index (p, ':')) != NULL) /* got a device */ { dev = p; /* save pointer */ p = q; /* advance to the : */ *p++ = NULLCHR; /* and terminate */ } if (*p == DIRBEG) /* got a UFD */ { dir = ++p; /* point to numbers */ while ( *p != DIREND ) if ( *p++ == NULLCHR ) err0 ("Bad UFD syntax"); *p++ = NULLCHR; /* terminate */ } fil = p; /* got a file name */ if ((q = index (p, '.')) != NULL) /* got a type */ { p = q; /* point to the . */ *p++ = NULLCHR; /* terminate file name */ typ = p; /* point to type */ } if ((q = index (p, ';')) != NULL) /* got a version */ { p = q; /* point to the ; */ *p++ = NULLCHR; /* terminate name or typ */ ver = p; /* point to version */ } } /* * Open output file */ static openout (cmd, dirname) char *cmd, *dirname; { char outfile [24]; if (*cmd == NULLCHR) /* default to terminal */ { stdout = ttsave; /* HACK: TT: stays opened */ return; } else if (cmd [strlen (cmd) - 1] == ':') /* RT device only given */ { /* make up name and type */ if (lsflag) /* directory name */ sprintf (outfile, "%s%s.dir", cmd, dirname); else /* normal file name */ sprintf (outfile, "%s%.6s.%s", cmd, fil, typ); } else strcpy (outfile, cmd); /* explicitly named */ if ((stdout = fopen (outfile, "wn")) == NULL) /* open, binary */ err1 ("Can't open output file %s", outfile); if (isatty (stdout)) { /* HACK: user entered TT: */ fclose (stdout); /* close the new one */ stdout = ttsave; /* and use the original */ } } /* * Translate a file already on an RT11 volume */ static rtfile (cmd, pos) char *cmd, *pos; /* filename pointers */ { register char ch; register int zcnt; if (stdin != NULL) fclose (stdin); /* close stdin if open */ if ((stdin = fopen (pos, "rn")) == NULL) /* open input file */ err1 ("Cant open input file %s", pos); crack (pos); /* parse for defaults */ openout ((pos == cmd) ? NULLSTR : cmd); /* open output file */ rputch (); /* reset putch routine */ zcnt = 0; while ((ch = getchar ()) != EOF) /* read characters */ { if (ch == '\0') ++zcnt; /* just count zeros */ else { /* now spit out any zeros */ for (; zcnt; --zcnt) putch ('\0'); putch (ch); /* and copy data */ } } } /* * Issue an error message */ err0 (msg) char *msg; { /* simple error message */ fprintf (stderr, "?RTRSX-E-%s\n", msg); longjmp (env, 1); /* prompt again */ } err1 (msg, arg) char *msg; int arg; { /* complex error message */ fprintf (stderr, "?RTRSX-E-"); fprintf (stderr, msg, arg); fprintf (stderr, "\n"); longjmp (env, 1); /* prompt again */ }