--- pgp/src/system.c 2018/04/24 16:38:20 1.1.1.2 +++ pgp/src/system.c 2018/04/24 16:43:24 1.1.1.7 @@ -3,21 +3,39 @@ * * Routines specific for non-MSDOS implementations of pgp. * + * (c) Copyright 1990-1994 by Philip Zimmermann. All rights reserved. + * The author assumes no liability for damages resulting from the use + * of this software, even if the damage results from defects in this + * software. No warranty is expressed or implied. + * + * Note that while most PGP source modules bear Philip Zimmermann's + * copyright notice, many of them have been revised or entirely written + * by contributors who frequently failed to put their names in their + * code. Code that has been incorporated into PGP from other authors + * was either originally published in the public domain or is used with + * permission from the various authors. + * + * PGP is available for free to the public under certain restrictions. + * See the PGP User's Guide (included in the release package) for + * important information about licensing, patent restrictions on + * certain algorithms, trademarks, copyrights, and export controls. + * * Modified 24-Jun-92 HAJK * Adapt for VAX/VMS. * * Modified: 11-Nov-92 HAJK * Add FDL Support Routines. + * + * Modified: 31-Jan-93 HAJK + * Misc. updates for terminal handling. + * Add VMS command stuff. + * Add fileparse routine. */ #include -#ifdef VMS -#include -#include "pgp.h" -#include "mpilib.h" -#include "mpiio.h" -#include "fileio.h" -extern byte textbuf[DISKBUFSIZE]; /* Defined in FILEIO.C */ -#endif /* VMS */ +#include "exitpgp.h" +#include "system.h" +#include "usuals.h" + /*===========================================================================*/ /* * UNIX @@ -34,9 +52,6 @@ extern byte textbuf[DISKBUFSIZE]; /* D */ #include #include -#if !defined(MACH) && !defined(BSD) -#include -#endif #ifndef NOTERMIO #ifndef SVR2 @@ -50,6 +65,9 @@ extern byte textbuf[DISKBUFSIZE]; /* D #ifdef USE_SELECT #include +#ifdef _IBMR2 +#include +#endif /* _IBMR2 */ #else #ifndef USE_NBIO #ifndef sun @@ -79,6 +97,9 @@ static int (*savesig)(int); void ttycbreak(void); void ttynorm(void); +#ifndef NEED_KBHIT +#undef USE_NBIO +#endif #ifndef NOTERMIO #ifndef SVR2 @@ -111,7 +132,8 @@ void ttycbreak(void) #else if (ioctl(ttyfd, TCGETA, &tio) < 0) #endif /* not SVR2 */ - { fprintf (stderr, "\nUnable to get terminal characteristics: "); + { + fprintf (stderr, "\nUnable to get terminal characteristics: "); perror("ioctl"); exitPGP(1); } @@ -126,13 +148,18 @@ void ttycbreak(void) tio.c_cc[VTIME] = 0; tio.c_lflag &= ~(ECHO|ICANON); #ifndef SVR2 +#ifdef ultrix + /* Ultrix is broken and flushes the output as well! */ + tcsetattr (ttyfd, TCSANOW, &tio); +#else tcsetattr (ttyfd, TCSAFLUSH, &tio); +#endif #else - ioctl(ttyfd, TCSETAW, &tio); + ioctl(ttyfd, TCSETAF, &tio); #endif /* not SVR2 */ #else - if (ioctl(ttyfd, TIOCGETP, &sg) < 0) - { fprintf (stderr, "\nUnable to get terminal characteristics: "); + if (ioctl(ttyfd, TIOCGETP, &sg) < 0) { + fprintf (stderr, "\nUnable to get terminal characteristics: "); perror("ioctl"); exitPGP(1); } @@ -165,9 +192,14 @@ void ttynorm(void) #endif #ifndef NOTERMIO #ifndef SVR2 +#ifdef ultrix + /* Ultrix is broken and flushes the output as well! */ + tcsetattr (ttyfd, TCSANOW, &tio); +#else tcsetattr (ttyfd, TCSAFLUSH, &itio); +#endif #else - ioctl(ttyfd, TCSETAW, &itio); + ioctl(ttyfd, TCSETAF, &itio); #endif /* not SVR2 */ #else ioctl(ttyfd, TIOCSETP, &isg); @@ -193,14 +225,16 @@ static void sig1 (int sig) } static void sig2 (int sig) -{ if (gottio) +{ + if (gottio) ttycbreak(); else setsigs(); } static void setsigs(void) -{ savesig = signal (SIGINT, sig1); +{ + savesig = signal (SIGINT, sig1); #ifdef SIGTSTP signal (SIGCONT, sig2); signal (SIGTSTP, sig1); @@ -215,6 +249,7 @@ static void rmsigs(void) #endif } +#ifdef NEED_KBHIT #ifndef CRUDE int kbhit(void) /* Return TRUE if there is a key to be read */ @@ -254,6 +289,7 @@ int kbhit(void) #endif } #endif /* !CRUDE */ +#endif int getch(void) { @@ -268,7 +304,8 @@ int getch(void) return(c); } -#ifdef BSD +#if defined(_BSD) && !defined(__STDC__) + VOID *memset(s, c, n) VOID *s; register int c, n; @@ -301,9 +338,10 @@ register int n; *s1++ = *s2++; return(p); } -#endif /* BSD */ +#endif /* _BSD */ -#if defined(MACH) || defined(SVR2) || defined(BSD) +#if (defined(MACH) || defined(SVR2) || defined(_BSD)) && !defined(NEXT) \ +&& !defined(AUX) || (defined(sun) && defined(i386)) int remove(name) char *name; { @@ -311,7 +349,7 @@ char *name; } #endif -#ifdef SVR2 +#if defined(SVR2) && !defined(AUX) int rename(old, new) register char *old, *new; { @@ -330,7 +368,8 @@ register char *old, *new; long Clock() /* not a replacement for clock(), just for random number generation */ { -#if defined(BSD) || defined(sun) || defined(MACH) || defined(linux) +#if defined(_BSD) || (defined(sun) && !defined(SOLARIS)) || \ +defined(MACH) || defined(linux) #include #include struct rusage ru; @@ -370,17 +409,74 @@ Clock() /* not a replacement for clock() * get the answer. */ +#include +#include +#include +#include +#include "pgp.h" +#include "mpilib.h" +#include "mpiio.h" +#include "fileio.h" +extern byte textbuf[DISKBUFSIZE]; /* Defined in FILEIO.C */ + +/* +** VMS Private Macros +*/ #include #include #include #include #include #include +#include #include +#include + +#define MAX_CMDSIZ 256 /* Maximum command size */ +#define MAX_FILENM 255 /* Mamimum file name size */ #define FDL$M_FDL_STRING 2 /* Use string for fdl text */ #define FDLSIZE 4096 /* Maximum possible file size */ +#ifdef _USEDCL_ + +/* + * Declare some external procedure prototypes (saves me confusion!) + */ +extern int lib$get_input( + struct dsc$descriptor *resultant, + struct dsc$descriptor *prompt, + unsigned short *resultant_length); +extern int lib$put_output( + struct dsc$descriptor *output); +extern int lib$sig_to_ret(); +/* +** The CLI routines are documented in the system routines manual. +*/ +extern int cli$dcl_parse( + struct dsc$descriptor *command, + char cmd_table[], + int (*get_command)( + struct dsc$descriptor *resultant, + struct dsc$descriptor *prompt, + unsigned short *resultant_length), + int (*get_parameter)( + struct dsc$descriptor *resultant, + struct dsc$descriptor *prompt, + unsigned short *resultant_length), + struct dsc$descriptor *prompt); +extern int cli$present( struct dsc$descriptor *object); +extern int cli$_get_value( + struct dsc$descriptor *object, + struct dsc$decsriptor *value, + unsigned short *value_len); +/* + * Static Data + */ +static $DESCRIPTOR (cmdprmt_d, "DROPSAFE> "); /* Prompt string */ + +#endif /* _USEDCL_ */ + static volatile short _kbhitChan_ = 0; static volatile struct IOSB { @@ -400,12 +496,12 @@ static volatile struct { int ExtChar; } CharBuf, OldCharBuf; -static $DESCRIPTOR (out_file_descr, "SYS$DISK:[]"); /* Default Output File Descr */ +static $DESCRIPTOR (out_file_descr, "SYS$DISK:[]"); /* Default Output + File Descr */ static int flags = FDL$M_FDL_STRING; - -/* + /* * **-kbhit_handler-This exit handler restores the terminal characteristics * * Description: @@ -414,57 +510,167 @@ static int flags = FDL$M_FDL_STRING; * on what you think is normal!). Anyway, it gets called to restore * characteristics either through ttynorm or via an exit handler. */ -void kbhit_handler(int *sts) +static void kbhit_handler(int *sts) { - int mysts; - - CharBuf.Mode = OldCharBuf.Mode; - CharBuf.ExtChar = OldCharBuf.ExtChar; - CharBuf.Mode &= ~TT$M_NOECHO; - CharBuf.ExtChar &= ~TT2$M_PASTHRU; - if ((mysts = sys$qiow ( - 0, - _kbhitChan_, - IO$_SETMODE, - &iosb, - 0, - 0, - &CharBuf, - 12, - 0, - 0, - 0, - 0)) & 01) mysts = iosb.sts; + ttynorm(); (void) sys$dassgn ( _kbhitChan_); _kbhitChan_ = 0; - if (!(mysts & 01)) { - fprintf(stderr,"\nFailed to reset terminal characteristics!"); - (void) lib$signal(mysts); - } } - +/* + * Data Structures For Linking Up Exit Handler + */ unsigned int exsts; static struct { int link; - void *rtn; + VOID *rtn; int argcnt; int *stsaddr; } exhblk = { 0, &(kbhit_handler), 1, &(exsts)}; + /* + * **-kbhit_Getchn-Get Channel + * + * Functional Description: + * + * Private routine to get a terminal channel and save the terminal + * characteristics. + * + * Arguments: + * + * None. + * + * Returns: + * + * If 0, channel already assigned. If odd, then assign was successful + * otherwise returns VMS error status. + * + * Implicit Inputs: + * + * _kbhitChan_ Channel assigned to the terminal (if any). + * + * Implicit Outputs: + * + * OldCharBuf Initial terminal characteristics. + * _kbhitChan_ Channel assigned to the terminal. + * + * Side Effects: + * + * Establishes an exit handler to restore characteristics and deassign + * terminal channel. + */ +static int kbhit_Getchn() +{ + int sts = 0; + if (_kbhitChan_ == 0) { + if ((sts = sys$assign ( + &kbdev_desc, + &_kbhitChan_, + 0, + 0)) & 1) { + if ((sts = sys$qiow ( + 0, + _kbhitChan_, + IO$_SENSEMODE, + &iosb, + 0, + 0, + &OldCharBuf, + 12, + 0, + 0, + 0, + 0)) & 01) sts = iosb.sts; + if (sts & 01) { + if (!(OldCharBuf.Class & DC$_TERM)) { + fprintf(stderr,"\nNot running on a terminal"); + exitPGP(1); + } + (void) sys$dclexh (&exhblk); + } + } + } + return(sts); +} +/* + * **-ttynorm-Restore initial terminal characteristics + * + * Functional Description: + * + * This procedure is invoked to restore the initial terminal characteristics. + */ +void ttynorm() /* + * Arguments: + * + * None. + * + * Implicit Inputs: + * + * OldCharBuf Initial terminal characteristics. + * _kbhitChan_ Channel assigned to the terminal. + * + * Implicit Outputs: + * + * None. + */ +{ + int sts; + + if (_kbhitChan_ != 0) { + CharBuf.Mode = OldCharBuf.Mode; + CharBuf.ExtChar = OldCharBuf.ExtChar; + /* + CharBuf.Mode &= ~TT$M_NOECHO; + CharBuf.ExtChar &= ~TT2$M_PASTHRU; + */ + if ((sts = sys$qiow ( + 0, + _kbhitChan_, + IO$_SETMODE, + &iosb, + 0, + 0, + &OldCharBuf, + 12, + 0, + 0, + 0, + 0)) & 01) sts = iosb.sts; + if (!(sts & 01)) { + fprintf(stderr,"\nFailed to reset terminal characteristics!"); + (void) lib$signal(sts); + } + } + return; +} + /* * **-kbhit-Find out if a key has been pressed * * Description: * * Make the terminal noecho and sense the characters coming in by looking at - * the typeahead count. + * the typeahead count. Note that the character remains in the typeahead buffer + * untill either read, or that the user types a Control-X when not in 'passall' + * mode. */ int kbhit() +/* + * Arguments: + * + * None. + * + * Returns: + * + * TRUE if there is a character in the typeahead buffer. + * FALSE if there is no character in the typeahead buffer. + */ + + { - int sts = 1; + int sts; struct { unsigned short TypAhdCnt; @@ -472,60 +678,6 @@ int kbhit() char Reserved[5]; } TypCharBuf; - if (_kbhitChan_ == 0) { - if ((sts = sys$assign ( - &kbdev_desc, - &_kbhitChan_, - 0, - 0)) & 1 == 0) lib$stop(sts); - if ((sts = sys$qiow ( - 0, - _kbhitChan_, - IO$_SENSEMODE, - &iosb, - 0, - 0, - &CharBuf, - 12, - 0, - 0, - 0, - 0)) & 01) sts = iosb.sts; - if (sts & 01) { - if (!(CharBuf.Class & DC$_TERM)) { - fprintf(stderr,"\nNot running on a terminal"); - exitPGP(1); - } else { - OldCharBuf.Mode = CharBuf.Mode; - OldCharBuf.ExtChar = CharBuf.ExtChar; - CharBuf.Mode |= TT$M_NOECHO; - CharBuf.ExtChar |= TT2$M_PASTHRU; - if ((sts = sys$qiow ( - 0, - _kbhitChan_, - IO$_SETMODE, - &iosb, - 0, - 0, - &CharBuf, - 12, - 0, - 0, - 0, - 0)) & 01) sts = iosb.sts; - if (sts & 01) { - /* - ** Declare Exit Handler - */ - (void) sys$dclexh (&exhblk); - } else { - fprintf(stderr,"\nFailed to set terminal characteristics!"); - (void) lib$signal(sts); - exitPGP(1); - } - } - } - } /* ** Get typeahead count */ @@ -547,52 +699,434 @@ int kbhit() exitPGP(1); } +static int NoTerm[2] = { 0, 0}; /* TT Terminator Mask (Nothing) */ + /* * **-getch-Get a character and return it * * Description: * - * Get a character from the keyboard and return it. + * Get a character from the keyboard and return it. Unlike Unix, the character + * will be explicitly echoed unless ttycbreak() has been called first. If the + * character is in the typeahead, that will be read first. */ int getch() +/* + * Arguments: + * + * None. + * + * Returns: + * + * Character Read. + */ { unsigned int sts; volatile char CharBuf; - if ((sts = sys$qiow ( - 0, - _kbhitChan_, - IO$_READVBLK, - &iosb, - 0, - 0, - &CharBuf, - 1, - 0, - 0, - 0, - 0)) & 01) sts = iosb.sts; + if (((sts = kbhit_Getchn()) & 01) || sts == 0) { + if ((sts = sys$qiow ( + 0, + _kbhitChan_, + IO$_READVBLK, + &iosb, + 0, + 0, + &CharBuf, + 1, + 0, + &NoTerm, + 0, + 0)) & 01) sts = iosb.sts; + } if (sts & 01) return ((int) CharBuf); fprintf(stderr,"\nFailed to get character"); (void) lib$signal(sts); } - -ttynorm() + /* + * **-putch-Put Character To 'Console' Device + * + * This procedure is a companion to getch, outputing a character to the + * terminal with a minimum of fuss (no VAXCRTLK, no RMS!). This routine + * simply gets a channel (if there isn't one already and uses QIO to + * output. + * + */ +int putch(int chr) +/* + * Arguments: + * chr Character to output. + * + * Returns: + * + * Status return from Getchn and qio. + * + * Side Effects + * + * May assign a channel to the terminal. + */ { - int sts; + unsigned int sts; - if (_kbhitChan_ != 0) { - (void) SYS$CANEXH(&exhblk); - kbhit_handler(&sts); + if (((sts = kbhit_Getchn()) & 01) || sts == 0) { + if ((sts = sys$qiow ( + 0, + _kbhitChan_, + IO$_WRITEVBLK, + &iosb, + 0, + 0, + &chr, + 1, + 0, + 0, + 0, + 0)) & 01) sts = iosb.sts; } + if (sts & 01) return (sts); + fprintf(stderr,"\nFailed to put character"); + (void) lib$signal(sts); } - + /* + * **-ttycbreak-Set Unix-like Cbreak mode + * + * Functional Description: + * + * This code must be invoked to produce the Unix-like cbreak operation which + * disables echo, allows control character input. + */ void ttycbreak () +/* + * Arguments: + * + * None. + * + * Returns: + * + * None. + * + * Side Effects + * + * May assign a channel to the terminal. + */ +{ + struct { + unsigned short TypAhdCnt; + char FirstChar; + char Reserved[5]; + } TypCharBuf; + char buf[80]; + int sts; + + if (((sts = kbhit_Getchn()) & 01) || sts == 0) { +/* + * Flush any typeahead before we change characteristics + */ + if ((sts = sys$qiow ( + 0, + _kbhitChan_, + IO$_SENSEMODE | IO$M_TYPEAHDCNT, + &iosb, + 0, + 0, + &TypCharBuf, + 8, + 0, + 0, + 0, + 0)) & 01) sts = iosb.sts; + if (sts) { + if (TypCharBuf.TypAhdCnt>0) { + if ((sts = sys$qiow ( + 0, + _kbhitChan_, + IO$_READVBLK | IO$M_NOECHO | IO$M_TIMED, + &iosb, + 0, + 0, + &buf, + (TypCharBuf.TypAhdCnt >= 80 ? 80 : + TypCharBuf.TypAhdCnt), + 1, + &NoTerm, + 0, + 0)) & 01) sts = iosb.sts; + + if (sts) + TypCharBuf.TypAhdCnt -= iosb.byteCount; + } + } + if (!(sts & 01)) TypCharBuf.TypAhdCnt = 0; +/* + * Modify characteristics + */ + CharBuf = OldCharBuf; + CharBuf.Mode = (OldCharBuf.Mode | TT$M_NOECHO) & ~TT$M_NOTYPEAHD; + CharBuf.ExtChar = OldCharBuf.ExtChar | TT2$M_PASTHRU; + if ((sts = sys$qiow ( + 0, + _kbhitChan_, + IO$_SETMODE, + &iosb, + 0, + 0, + &CharBuf, + 12, + 0, + 0, + 0, + 0)) & 01) sts = iosb.sts; + if (!(sts & 01)) { + fprintf(stderr, + "\nttybreak()- Failed to set terminal characteristics!"); + (void) lib$signal(sts); + exitPGP(1); + } + } +} + + +#ifdef _USEDCL_ + +/* + * **-vms_getcmd-Get VMS Style Foreign Command + * + * Functional Description: + * + * Get command from VAX/VMS foreign command line interface and parse + * according to DCL rules. If the command line is ok, it can then be + * parsed according to the rules in the DCL command language table. + * + */ +int vms_GetCmd( char *cmdtbl) +/* + * Arguments: + * + * cmdtbl Pointer to command table to parse. + * + * Returns: + * + * ...TBS... + * + * Implicit Inputs: + * + * Command language table defined in DROPDCL.CLD + */ +{ + int sts; + char cmdbuf[MAX_CMDSIZ]; + unsigned short cmdsiz; + struct dsc$descriptor cmdbuf_d = {0,0,0,0}; + struct dsc$descriptor infile_d = {0,0,0,0}; + char filenm[MAX_FILENM]; + unsigned short filenmsiz; + unsigned short verb_size; + + /* + ** DCL Parse Expects A Command Verb Prefixing The Argumnents + ** fake it! + */ + verb_size = cmdprmt_d.dsc$w_length - 2; /* Loose '> ' characters */ + cmdbuf_d.dsc$w_length = MAX_CMDSIZ-verb_size-1; + cmdbuf_d.dsc$a_pointer = strncpy(cmdbuf,cmdprmt_d.dsc$a_pointer,verb_size) + + verb_size+1; + cmdbuf[verb_size++]=' '; + if ((sts = lib$get_foreign ( /* Recover command line from DCL */ + &cmdbuf_d, + 0, + &cmdsiz, + 0)) & 01) { + cmdbuf_d.dsc$a_pointer = cmdbuf; + cmdbuf_d.dsc$w_length = cmdsiz + verb_size; + VAXC$ESTABLISH(lib$sig_to_ret); /* Force unhandled exceptions + to return */ + sts = cli$dcl_parse( /* Parse Command Line */ + &cmdbuf_d, + cmdtbl, + lib$get_input, + lib$get_input, + &cmdprmt_d); + } + return(sts); +} + /* + * **-vms_TstOpt-Test for command qualifier present + * + * Functional Description: + * + * This procedure is invoked to test whether an option is present. It is + * really just a jacket routine for the system routine CLI$PRESENT + * converting the argument and result into 'C' speak. + * + */ +vms_TstOpt(char opt) +/* + * Arguments: + * + * opt Character label of qualifier to test for. + * + * Returns: + * + * +1 Option present. + * 0 Option absent. + * -1 Option negated. + * + * Implicit Inputs: + * + * Uses DCL command line context established by vms_GetOpt. + */ +{ + int sts; + char buf; + struct dsc$descriptor option_d = { 1, 0, 0, &buf}; + + buf = _toupper(opt); + VAXC$ESTABLISH(lib$sig_to_ret); /* Force unhandled exceptions + to return */ + switch (sts=cli$present(&option_d)) + { + + case CLI$_PRESENT : + return(1); + case CLI$_ABSENT: + return(0); + case CLI$_NEGATED: + return(-1); + default: + return(0); + } +} + /* + * **-vms_GetVal-Get Qualifier Value. + * + * Functional Description: + * + * This procedure is invoked to return the value associated with a + * qualifier that exists (See TstOpt). + */ +vms_GetVal( char opt, char *resval, unsigned short maxsiz) +/* + * Arguments: + * + * opt Character label of qualifier to test for. + * resval Pointer to resulting value string. + * maxsiz Maximum size of string. + * + * Returns: + * + * ...TBS... + * + * Implicit Inputs: + * + * Uses DCL command line context established by vms_GetOpt. + */ { - ttynorm(); + int sts; + char buf; + struct dsc$descriptor option_d = { 1, 0, 0, &buf}; + struct dsc$descriptor value_d = {maxsiz-1, 0, 0, resval }; + unsigned short valsiz; + + VAXC$ESTABLISH(lib$sig_to_ret); /* Force unhandled exceptions + to return */ + buf = _toupper(opt); + if ((sts = cli$get_value( + &option_d, + &value_d, + &valsiz)) & 01) resval[valsiz] = '\0'; + return(sts); +} + /* + * **-vms_GetArg-Get Argument Value. + * + * Functional Description: + * + * This procedure is invoked to return the value associated with an + * argument. + */ +vms_GetArg( unsigned short arg, char *resval, unsigned short maxsiz) +/* + * Arguments: + * + * arg Argument Number (1-9) + * resval Pointer to resulting value string. + * maxsiz Maximum size of string. + * + * Returns: + * + * ...TBS... + * + * Implicit Inputs: + * + * Uses DCL command line context established by vms_GetOpt. + */ +{ + int sts; + char buf[2] = "P"; + struct dsc$descriptor option_d = { 2, 0, 0, buf}; + struct dsc$descriptor value_d = {maxsiz-1, 0, 0, resval }; + unsigned short valsiz; + + VAXC$ESTABLISH(lib$sig_to_ret); /* Force unhandled exceptions + to return */ + buf[1] = arg + '0'; + if ((sts = cli$present(&option_d)) & 01) { + if ((sts = cli$get_value( + &option_d, + &value_d, + &valsiz)) & 01) resval[valsiz] = '\0'; + } else return(0); + return(sts); } + -unsigned long vms_clock_bits[2]; /* VMS Hardware Clock */ + +/* + * **-do_help-Invoke VMS Help Processor + * + * Functional Description: + * + * This procedure is invoked to display a suitable help message to the caller + * using the standard VMS help library. + * + */ +do_help(char *helptext, char *helplib) +/* + * Arguments: + * + * helptext Text of help request. + * helplib Help library. + * + * Returns: + * + * As for kbhit_Getchn and lbr$output_help. + * + * Side Effects: + * + * A channel may be opened to the terminal. A library is opened. + */ +{ + int sts; + int helpflags; + struct dsc$descriptor helptext_d = { strlen(helptext), 0, 0, helptext}; + struct dsc$descriptor helplib_d = { strlen(helplib), 0, 0, helplib}; + + VAXC$ESTABLISH(lib$sig_to_ret); /* Force unhandled + exceptions to return */ + if (((sts = kbhit_Getchn()) & 01) || sts == 0) { + helpflags = HLP$M_PROMPT|HLP$M_SYSTEM|HLP$M_GROUP|HLP$M_PROCESS; + sts = lbr$output_help( + lib$put_output, + &OldCharBuf.BufferSize, + &helptext_d, + &helplib_d, + &helpflags, + lib$get_input); + } + return(sts); +} +#endif /* _USEDCL_ */ + unsigned long vms_clock_bits[2]; /* VMS Hardware Clock */ const long vms_ticks_per_update = 100000L; /* Clock update int. */ /* @@ -687,7 +1221,8 @@ int fdl_generate(char *in_file, char **f &badblk, len)) & 01)) { if (verbose) - fprintf(stderr,"\n(SYSTEM) Failed to generate FDL\n",in_file); + fprintf(stderr,"\n(SYSTEM) Failed to generate FDL\n", + in_file); free(fdl); } else { if (!(*fdl = malloc(*len))) return(0); @@ -712,7 +1247,7 @@ void fdl_close(void* rab) /* * Arguments: * - * rab void * Pointer to RAB (voided to avoid problems for caller). + * rab VOID * Pointer to RAB (voided to avoid problems for caller). * * Returns: * @@ -737,7 +1272,7 @@ void fdl_close(void* rab) * there is no way we can easily patch into the back of the VAX C I/O * subsystem. */ -void * fdl_create( char *fdl, short len, char *outfile, char *preserved_name) +VOID * fdl_create( char *fdl, short len, char *outfile, char *preserved_name) /* * Arguments: * @@ -754,7 +1289,7 @@ void * fdl_create( char *fdl, short len, * 0 in case of error, or otherwise the RAB pointer. */ { - void *sts; + VOID *sts; int sts2; struct FAB *fab; struct RAB *rab; @@ -774,9 +1309,9 @@ void * fdl_create( char *fdl, short len, * Initialize RMS NAM Block */ nam = cc$rms_nam; - nam.nam$b_rss = NAM$C_MAXRSS; - nam.nam$b_ess = NAM$C_MAXRSS; - if (!(resnam = nam.nam$l_esa = malloc(NAM$C_MAXRSS+1))) { + nam.nam$b_rss = NAM$C_MAXRSSLCL; + nam.nam$b_ess = NAM$C_MAXRSSLCL; + if (!(resnam = nam.nam$l_esa = malloc(NAM$C_MAXRSSLCL+1))) { fprintf(stderr,"\n(FDL_CREATE) Out of memory!\n"); return(NULL); } @@ -825,7 +1360,8 @@ void * fdl_create( char *fdl, short len, fdl_close(rab); } else sts = rab; } - fab->fab$l_nam = 0; /* I allocated NAM block, so I must deallocate it! */ + fab->fab$l_nam = 0; /* I allocated NAM block, + so I must deallocate it! */ } free(resnam); return(sts); @@ -843,7 +1379,7 @@ void * fdl_create( char *fdl, short len, * * Calling Sequence: */ -int fdl_copyfile2bin( FILE *f, void *rab, word32 longcount) +int fdl_copyfile2bin( FILE *f, VOID *rab, word32 longcount) /* * Arguments: * @@ -872,15 +1408,16 @@ int fdl_copyfile2bin( FILE *f, void *rab count = fread(textbuf,1,count,f); if (count > 0) { /* - * No byte order conversion required, source and target system are both VMS so have - * the same byte ordering. + * No byte order conversion required, source and target system are both + * VMS so have the same byte ordering. */ ((struct RAB *) rab)->rab$w_rsz = (unsigned short) count; if (!(sys$write ( rab, NULL, NULL) & 01)) { - lib$signal(((struct RAB *) rab)->rab$l_sts,((struct RAB *) rab)->rab$l_stv); + lib$signal(((struct RAB *) rab)->rab$l_sts, + ((struct RAB *) rab)->rab$l_stv); status = 1; break; } @@ -890,6 +1427,117 @@ int fdl_copyfile2bin( FILE *f, void *rab burn(textbuf); return(status); } + /* + * **-vms_fileparse-Parse A VMS File Specification + * + * Functional Description: + * + * This procedure is invoked to parse a VMS file specification using default + * and related specifications to fill in any missing components. This works a + * little like DCL's F$PARSE function with the syntax check only specified + * (that is we don't check the device or the directory). The related file + * spec is really for when we want to use the name of an input file (w/o the + * directory) to supply the name of an output file. + * + * Note that we correctly handle the situation where the output buffer overlays + * the input filespec by testing for the case and then handling it by copying + * the primary input specification to a temporary buffer before parsing. + */ +int vms_fileparse( char *outbuf, char *filespec, char *defspec, char *relspec) +/* + * Arguments: + * + * outbuf Returned file specification. + * filespec Primary file specification (optional). + * defspec Default file specification (optional). + * relspec Related file specification (optional). + * + * Returns: + * + * As for SYS$PARSE. + * + * Implicit Inputs: + * + * None. + * + * Implicit Outputs: + * + * None. + * + * Side Effects: + * + * ...TBS... + */ +{ + struct FAB fab = cc$rms_fab; + struct NAM nam = cc$rms_nam; + struct NAM rlnam = cc$rms_nam; + int sts = 1; + int len; + char tmpbuf[NAM$C_MAXRSSLCL]; + char expfnam2[NAM$C_MAXRSSLCL]; + + if (outbuf != NULL) { + outbuf[0] = '\0'; + fab.fab$l_fop != FAB$M_NAM; /* Enable RMS NAM block processing */ + nam.nam$b_nop |= NAM$M_PWD | NAM$M_SYNCHK; + /* + ** Handle Related Spec (If reqd). + */ + if (relspec != NULL) { + if ((len = strlen(relspec)) > 0) { + fab.fab$l_nam = &rlnam; + fab.fab$b_fns = len; + fab.fab$l_fna = relspec; + rlnam.nam$b_ess = NAM$C_MAXRSSLCL; + rlnam.nam$l_esa = expfnam2; + rlnam.nam$b_nop |= NAM$M_PWD | NAM$M_SYNCHK; + if ((sts = sys$parse ( + &fab, + 0, + 0)) & 01) { + rlnam.nam$l_rsa = rlnam.nam$l_esa; + rlnam.nam$b_rsl = rlnam.nam$b_esl; + nam.nam$l_rlf = &rlnam; + fab.fab$l_fop |= FAB$M_OFP; + } + } + } + if (sts) { + fab.fab$l_nam = &nam; + nam.nam$l_esa = outbuf; + nam.nam$b_ess = NAM$C_MAXRSSLCL; + /* + ** Process Default Specification: + */ + if (defspec != NULL) { + if ((len = strlen(defspec)) > 0) { + fab.fab$l_dna = defspec; + fab.fab$b_dns = len; + } + } + /* + ** Process Main File Specification: + */ + fab.fab$l_fna = NULL; + fab.fab$b_fns = 0; + if (filespec != NULL) { + if ((len = strlen(filespec)) > 0) { + fab.fab$b_fns = len; + if (filespec == outbuf) + fab.fab$l_fna = memcpy(tmpbuf,filespec,len); + else + fab.fab$l_fna = filespec; + } + } + if ((sts = sys$parse( + &fab, + 0, + 0)) && 01) outbuf[nam.nam$b_esl] = '\0'; + } + } + return (sts); +} #endif /* VMS */ @@ -1064,6 +1712,7 @@ long clock() #if !defined(MSDOS) && !defined(ATARI) #include +#include "charset.h" char *strlwr(char *s) { /* ** Turns string s into lower case.