--- pgp/src/system.c 2018/04/24 16:37:52 1.1.1.1 +++ pgp/src/system.c 2018/04/24 16:45:12 1.1.1.9 @@ -3,12 +3,38 @@ * * Routines specific for non-MSDOS implementations of pgp. * + * (c) Copyright 1990-1996 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 -#include "pgp.h" - +#include "exitpgp.h" +#include "system.h" +#include "usuals.h" /*===========================================================================*/ /* @@ -26,25 +52,29 @@ */ #include #include -#ifndef NeXT -#include -#endif #ifndef NOTERMIO -#ifndef M_XENIX +#ifndef SVR2 #include #else #include -#endif /* not M_XENIX */ +#endif /* not SVR2 */ #else #include #endif #ifdef USE_SELECT #include +#ifdef _IBMR2 +#include +#endif /* _IBMR2 */ #else #ifndef USE_NBIO +#ifndef sun #include /* for FIONREAD */ +#else /* including both ioctl.h and termios.h gives a lot of warnings on sun */ +#include +#endif /* sun */ #ifndef FIONREAD #define FIONREAD TIOCINQ #endif @@ -58,7 +88,7 @@ static void sig1(int); static void sig2(int); void breakHandler(int); static int ttyfd= -1; -#ifndef M_XENIX +#ifndef SVR2 static void (*savesig)(int); #else static int (*savesig)(int); @@ -67,13 +97,16 @@ static int (*savesig)(int); void ttycbreak(void); void ttynorm(void); +#ifndef NEED_KBHIT +#undef USE_NBIO +#endif #ifndef NOTERMIO -#ifndef M_XENIX +#ifndef SVR2 static struct termios itio, tio; #else static struct termio itio, tio; -#endif /* not M_XENIX */ +#endif /* not SVR2 */ #else static struct sgttyb isg, sg; #endif @@ -94,12 +127,13 @@ void ttycbreak(void) } } #ifndef NOTERMIO -#ifndef M_XENIX +#ifndef SVR2 if (tcgetattr(ttyfd, &tio) < 0) #else if (ioctl(ttyfd, TCGETA, &tio) < 0) -#endif /* not M_XENIX */ - { fprintf (stderr, "\nUnable to get terminal characteristics: "); +#endif /* not SVR2 */ + { + fprintf (stderr, "\nUnable to get terminal characteristics: "); perror("ioctl"); exitPGP(1); } @@ -113,26 +147,38 @@ void ttycbreak(void) #endif tio.c_cc[VTIME] = 0; tio.c_lflag &= ~(ECHO|ICANON); -#ifndef M_XENIX +#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); -#endif /* not M_XENIX */ + 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); } isg = sg; setsigs(); gottio = 1; +#ifdef CBREAK sg.sg_flags |= CBREAK; +#else + sg.sg_flags |= RAW; +#endif sg.sg_flags &= ~ECHO; ioctl(ttyfd, TIOCSETP, &sg); #endif /* !NOTERMIO */ #ifdef USE_NBIO - if ((fflags = fcntl(ttyfd, F_GETFL)) != -1) +#ifndef O_NDELAY +#define O_NDELAY O_NONBLOCK +#endif + if ((fflags = fcntl(ttyfd, F_GETFL, 0)) != -1) fcntl(ttyfd, F_SETFL, fflags|O_NDELAY); #endif } @@ -145,11 +191,16 @@ void ttynorm(void) perror("fcntl"); #endif #ifndef NOTERMIO -#ifndef M_XENIX +#ifndef SVR2 +#ifdef ultrix + /* Ultrix is broken and flushes the output as well! */ + tcsetattr (ttyfd, TCSANOW, &itio); +#else tcsetattr (ttyfd, TCSAFLUSH, &itio); +#endif #else - ioctl(ttyfd, TCSETAW, &itio); -#endif /* not M_XENIX */ + ioctl(ttyfd, TCSETAF, &itio); +#endif /* not SVR2 */ #else ioctl(ttyfd, TIOCSETP, &isg); #endif @@ -159,11 +210,11 @@ void ttynorm(void) static void sig1 (int sig) { #ifndef NOTERMIO -#ifndef M_XENIX +#ifndef SVR2 tcsetattr (ttyfd, TCSANOW, &itio); #else ioctl(ttyfd, TCSETAW, &itio); -#endif /* not M_XENIX */ +#endif /* not SVR2 */ #else ioctl(ttyfd, TIOCSETP, &isg); #endif @@ -174,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); @@ -196,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 */ @@ -235,6 +289,7 @@ int kbhit(void) #endif } #endif /* !CRUDE */ +#endif int getch(void) { @@ -244,14 +299,16 @@ int getch(void) c = kbuf; kbuf = -1; #else + c = 0; read(ttyfd, &c, 1); #endif - return(c); + return(c & 0xFF); } -#ifdef BSD_OLD -void *memset(s, c, n) -void *s; +#if defined(_BSD) && !defined(__STDC__) + +VOID *memset(s, c, n) +VOID *s; register int c, n; { register char *p = s; @@ -272,7 +329,7 @@ register int n; } return(*s1 - *s2); } -void *memcpy(s1, s2, n) +VOID *memcpy(s1, s2, n) register char *s1, *s2; register int n; { @@ -282,30 +339,58 @@ register int n; *s1++ = *s2++; return(p); } -#endif /* BSD_OLD */ +#endif /* _BSD */ -#ifdef M_XENIX /* XENIX/286 specific stuff */ +#if (defined(MACH) || defined(SVR2) || defined(_BSD)) && !defined(NEXT) \ +&& !defined(AUX) && !defined(__MACHTEN__) || (defined(sun) && defined(i386)) int remove(name) char *name; { return unlink(name); } +#endif +#if defined(SVR2) && !defined(AUX) int rename(old, new) register char *old, *new; { - (void) unlink(new); + unlink(new); if (link(old, new) < 0) return -1; if (unlink(old) < 0) { - (void) unlink(new); + unlink(new); return -1; } return 0; } -#endif /* M_XENIX */ -#endif /* UNIX */ +#endif /* SVR2 */ +/* not all unices have clock() */ +long +Clock() /* not a replacement for clock(), just for random number generation */ +{ +#if defined(_BSD) || (defined(sun) && !defined(SOLARIS)) || \ +defined(MACH) || defined(linux) +#include +#include + struct rusage ru; + + getrusage(RUSAGE_SELF, &ru); + return ru.ru_utime.tv_sec + ru.ru_utime.tv_usec + + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec + + ru.ru_minflt + ru.ru_majflt + + ru.ru_inblock + ru.ru_oublock + + ru.ru_maxrss + ru.ru_nvcsw + ru.ru_nivcsw; + +#else /* no getrusage() */ +#include + struct tms tms; + + times(&tms); + return(tms.tms_utime + tms.tms_stime); +#endif +} +#endif /* UNIX */ /*===========================================================================*/ @@ -325,17 +410,74 @@ register char *old, *new; * 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 -#ifdef VAXC #include #include #include -#else /* Probably GNU */ -#include -#include -#include -#endif /* VAXC */ +#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 { @@ -344,6 +486,7 @@ static volatile struct IOSB { unsigned short terminator; unsigned short terminatorSize; } iosb; + static $DESCRIPTOR (kbdev_desc, "SYS$COMMAND:"); static volatile struct { @@ -354,48 +497,181 @@ static volatile struct { int ExtChar; } CharBuf, OldCharBuf; -void kbhit_handler(int *sts) -{ - int mysts; +static $DESCRIPTOR (out_file_descr, "SYS$DISK:[]"); /* Default Output + File Descr */ - 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; +static int flags = FDL$M_FDL_STRING; + + /* + * **-kbhit_handler-This exit handler restores the terminal characteristics + * + * Description: + * + * This procedure is invoked to return the the terminal to normality (depends + * on what you think is normal!). Anyway, it gets called to restore + * characteristics either through ttynorm or via an exit handler. + */ +static void kbhit_handler(int *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. 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; @@ -403,60 +679,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 */ @@ -477,91 +699,973 @@ int kbhit() (void) lib$signal(sts); 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. 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. + */ +{ + 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. + */ { - ttynorm(); + 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. */ + +/* + * FDL Stuff For Getting & Setting File Characteristics + * This code was derived (loosely!) from the module LZVIO.C in the public + * domain LZW compress routine as found on the DECUS VAX SIG tapes (no author + * given, so no credits!) + */ -#endif /* VMS */ +/* + * **-fdl_generate-Generate An FDL + * + * Description: + * + * This procedure takes the name of an existing file as input and creates + * an fdl. The FDL is retuned by pointer and length. The FDL space should be + * released after use with a call to free(); + */ +int fdl_generate(char *in_file, char **fdl, short *len) +/* + * Arguments: + * + * in_file char* Filename of file to examine (Zero terminated). + * + * fdl char* Pointer to FDL that was created. + * + * len short Length of FDL created. + * + * Status Returns: + * + * VMS style. lower bit set means success. + */ +{ + struct dsc$descriptor fdl_descr = { 0, + DSC$K_DTYPE_T, + DSC$K_CLASS_D, + 0}; + struct FAB fab, *fab_addr; + struct RAB rab, *rab_addr; + struct NAM nam; + struct XABFHC xab; + int sts; + int badblk; +/* + * Build FDL Descriptor + */ + if (!(sts = str$get1_dx(&FDLSIZE,&fdl_descr)) & 01) return(0); +/* + * Build RMS Data Structures + */ + fab = cc$rms_fab; + fab_addr = &fab; + nam = cc$rms_nam; + rab = cc$rms_rab; + rab_addr = &rab; + xab = cc$rms_xabfhc; + fab.fab$l_nam = &nam; + fab.fab$l_xab = &xab; + fab.fab$l_fna = in_file; + fab.fab$b_fns = strlen(in_file); + rab.rab$l_fab = &fab; + fab.fab$b_fac = FAB$M_GET | FAB$M_BIO; /* This open block mode only */ +/* + * Attempt to Open File + */ + if (!((sts = sys$open(&fab)) & 01)) { + if (verbose) { + fprintf(stderr,"\n(SYSTEM) Failed to $OPEN %s\n",in_file); + (void) lib$signal(fab.fab$l_sts,fab.fab$l_stv); + } + return(sts); + } + if (fab.fab$l_dev & DEV$M_REC) { + fprintf(stderr,"\n(SYSTEM) Attempt to read from output only device\n"); + sts = 0; + } else { + rab.rab$l_rop = RAB$M_BIO; + if (!((sts = sys$connect(&rab)) & 01)) { + if (verbose) { + fprintf(stderr,"\n(SYSTEM) Failed to $CONNECT %s\n",in_file); + (void) lib$signal(fab.fab$l_sts,fab.fab$l_stv); + } + } else { + if (!((sts = fdl$generate( + &flags, + &fab_addr, + &rab_addr, + NULL,NULL, + &fdl_descr, + &badblk, + len)) & 01)) { + if (verbose) + fprintf(stderr,"\n(SYSTEM) Failed to generate FDL\n", + in_file); + free(fdl); + } else { + if (!(*fdl = malloc(*len))) return(0); + memcpy(*fdl,fdl_descr.dsc$a_pointer,*len); + } + (void) str$free1_dx(&fdl_descr); + } + sys$close(&fab); + } + return(sts); +} + +/* + * **-fdl_close-Closes files created by fdl_generate + * + * Description: + * + * This procedure is invoked to close the file and release the data structures + * allocated by fdl$parse. + */ +void fdl_close(void* rab) +/* + * Arguments: + * + * rab VOID * Pointer to RAB (voided to avoid problems for caller). + * + * Returns: + * + * None. + */ +{ + struct FAB *fab; -/*========================================================================*/ + fab = ((struct RAB *) rab)->rab$l_fab; + if (fab) { /* Close file if not already closed */ + if (fab->fab$w_ifi) sys$close(fab); + } + fdl$release( NULL, &rab); +} + /* - * AMIGA + * **-fdl_create-Create A File Using the recorded FDL (hope we get it right!) + * + * Description: + * + * This procedure accepts an FDL and uses it create a file. Unfortunately + * 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) +/* + * Arguments: + * + * fdl char* FDL string descriptor. + * + * len short Returned string length. + * + * outfile char* Output filename. + * + * preserved_name char* Name from FDL. + * + * Returns: + * + * 0 in case of error, or otherwise the RAB pointer. + */ +{ + VOID *sts; + int sts2; + struct FAB *fab; + struct RAB *rab; + struct NAM nam; + int badblk; + char *resnam; + + struct dsc$descriptor fdl_descr = { + len, + DSC$K_DTYPE_T, + DSC$K_CLASS_S, + fdl + }; -#ifdef AMIGA /* Amiga-specific stuff */ + sts = NULL; +/* + * Initialize RMS NAM Block + */ + nam = cc$rms_nam; + 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); + } +/* + * Parse FDL + */ + if (!((sts2 = fdl$parse( &fdl_descr, + &fab, + &rab, + &flags)) & 01)) { + fprintf(stderr,"\nCreating (fdl$parse)\n"); + (void) lib$signal(sts2); + } else { +/* + * Extract & Return Name of FDL Supplied Filename + */ + memcpy (preserved_name,fab->fab$l_fna,fab->fab$b_fns); + preserved_name[fab->fab$b_fns] = '\0'; +/* + * Set Name Of Temporary File + */ + fab->fab$l_fna = outfile; + fab->fab$b_fns = strlen(outfile); +/* + * Connect NAM Block + */ + fab->fab$l_nam = &nam; + fab->fab$l_fop |= FAB$M_NAM | FAB$M_CIF; + fab->fab$b_fac |= FAB$M_BIO | FAB$M_PUT; +/* + * Create File + */ + if (!(sys$create(fab) & 01)) { + fprintf(stderr,"\nCreating (RMS)\n"); + (void) lib$signal(fab->fab$l_sts,fab->fab$l_stv); + fdl_close(rab); + } else { + if (verbose) { + resnam[nam.nam$b_esl+1] = '\0'; + fprintf(stderr,"\nCreated %s successfully\n",resnam); + } + rab->rab$l_rop = RAB$M_BIO; + if (!(sys$connect(rab) & 01)) { + fprintf(stderr,"\nConnecting (RMS)\n"); + (void) lib$signal(rab->rab$l_sts,rab->rab$l_stv); + fdl_close(rab); + } else sts = rab; + } + fab->fab$l_nam = 0; /* I allocated NAM block, + so I must deallocate it! */ + } + free(resnam); + return(sts); +} + +/* + * **-fdl_copyfile2bin-Copies the input file to a 'binary' output file + * + * Description: + * + * This procedure is invoked to copy from an opened file f to a file opened + * directly through RMS. This allows us to make a block copy into one of the + * many esoteric RMS file types thus preserving characteristics without blowing + * up the C RTL. This code is based directly on copyfile from FILEIO.C. + * + * Calling Sequence: + */ +int fdl_copyfile2bin( FILE *f, VOID *rab, word32 longcount) +/* + * Arguments: + * + * f FILE* Pointer to input file + * + * rab RAB* Pointer to output file RAB + * + * longcount word32 Size of file + * + * Returns: + * + * 0 If we were successful. + * -1 We had an error on the input file (VAXCRTL). + * +1 We had an error on the output file (direct RMS). + */ +{ + int status = 0; + word32 count; + ((struct RAB *) rab)->rab$l_rbf = &textbuf; + ((struct RAB *) rab)->rab$l_bkt = 0; + do { /* Read and write longcount bytes */ + if (longcount < (word32) DISKBUFSIZE) + count = longcount; + else + count = DISKBUFSIZE; + 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. + */ + ((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); + status = 1; + break; + } + longcount -= count; + } + } while (count==DISKBUFSIZE); + 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 */ + -#include +/* + * ------------------------- Amiga specific routines ------------------------- + */ + +#ifdef AMIGA + +#include +#include #include #include +#include #include -#ifdef LATTICE -#include +#include #include -#endif /* LATTICE */ -extern FILE *pgpout; -extern int aecho; +#include +#include +#include "pgp.h" -FILE *tmpfile() -{ - FILE *fp; +/* + * This getenv will use the WB2.0 calls if you have the 2.0 + * rom. If not, it resorts to looking in the ENV: directory. + */ - if ((fp=fopen("tmpfile.tmp","w+b"))==NULL) { - perror("tmpfile.tmp"); - return(NULL); - } - return(fp); +/* + * I am sorry to report that SAS/C is buggy. :-( + * It doesn't recognize replacement routines if they are linked + * to the main code and not included in the file itself. I hate + * stuff like that. :-( + * -peter + */ +char *amiga_getenv(const char *name) +{ + FILE *fp; + char *ptr; + static char value[256]; + static char buf[256]; + + /* + * 2.0 style? + */ + if (DOSBase->dl_lib.lib_Version >= 36) { + if (GetVar((char *) name, value, 256, 0L) == -1) + return NULL; + } + else { + if (strlen(name) > 252) + return NULL; + strcpy(buf, "ENV:"); + strcpy(&buf[4], name); + if (!(fp = fopen(buf, "r"))) + return NULL; + for (ptr = value; (*ptr = getc(fp)) != EOF + && *ptr != '\n' + && ++ptr < &value[256];) ; + fclose(fp); + *ptr = 0; + } + return value; } -/* amiga version of getch() - Cor Bosman , jul-22-92 -*/ +extern FILE *pgpout; +char *requesterdesc; + +/* + * AmigaRequestString() is a trick to make PGP more usable from scripts. + * The problem is, that most scripts don't allow user interaction over + * the standard input. The same problem occurs when working in filter mode. + * + * This routine will be called by PGP's getstring() whenever user input + * is requested but the standard input is not interactive. Because the + * routine can't know what string to ask for, I added the Amiga-specific + * variable requesterdesc, which holds the last string printed to pgpout + * before getstring was called. + * + * This solution is not pretty, but it works. + * Peter Simons + */ + +int AmigaRequestString(char *buffer, int maxlen, int echo) +{ + struct ReqToolsBase *ReqToolsBase; + struct TagItem ti[] = { + {RTGS_Invisible, FALSE}, + {RTGS_TextFmt, 0L}, + {RTGS_Flags, GSREQF_CENTERTEXT}, + {TAG_DONE, 0L} + }; + int len = 0; + char name[64]; + + if (!maxlen) + return 0; + if (!echo) + ti[0].ti_Data = TRUE; + ti[1].ti_Data = (ULONG) (requesterdesc) ? ((*requesterdesc == '\n') ? requesterdesc+1 : requesterdesc) : "Please enter required string"; + /* This one is tricky, too. Because of the format of the + * LANG() module we have a prefacing return before most + * strings, which will make our beautiful requester look + * a bit stupid. This way, we get rid of it. :-) + */ + sprintf(name, "PGPAmiga %s", rel_version); + + if (ReqToolsBase = (struct ReqToolsBase *) OpenLibrary(REQTOOLSNAME, 38L)) + { + *buffer = '\0'; + if (rtGetStringA(buffer, maxlen, name, NULL, ti)) + len = strlen(buffer); + CloseLibrary((struct Library *) ReqToolsBase); + } + else + { fprintf(stderr,"Could not open ReqTools.library! Try using PGP " + "without -f.\n"); + exitPGP(7); /* Error exit */ + } + requesterdesc=NULL; /* Program will re-set it before next getstring() call */ + return len; +} sendpacket(struct MsgPort *rec,LONG action,LONG arg1) { struct StandardPacket *pkt; - struct msgPort *rp; + struct MsgPort *rp; LONG res1 = 0L; if (rp = (struct MsgPort *)CreatePort(NULL,0L)) { @@ -584,103 +1688,99 @@ sendpacket(struct MsgPort *rec,LONG acti } -/* ttycbreak for amiga. - * Cor Bosman , jul-30-92 -*/ - -void ttycbreak() +void ttycbreak(void) { - BPTR in,out; - char buf[128]; struct MsgPort *ch; - in=Input(); - out=Output(); - ch = ((struct FileHandle *)BADDR(in))->fh_Type; + ch = ((struct FileHandle *)BADDR(Input()))->fh_Type; sendpacket(ch,ACTION_SCREEN_MODE,-1L); } -/* ttynorm for amiga - * Cor Bosman , jul-30-92 -*/ - -void ttynorm() +void ttynorm(void) { - - BPTR in,out; - char buf[128]; struct MsgPort *ch; - in=Input(); - out=Output(); - ch = ((struct FileHandle *)BADDR(in))->fh_Type; + ch = ((struct FileHandle *)BADDR(Input()))->fh_Type; sendpacket(ch,ACTION_SCREEN_MODE,0L); } -char getch(void) +int getch(void) { - char buf[128]; - BPTR in,out; + char buf; - in = Input(); - out = Output(); - Read(in,buf,1); - if (aecho) - Write(out, buf, 1); - return(buf[0]); + Read(Input(),&buf,1); + return((int)buf); } -/* kbhit() function for amiga. - * Cor Bosman , jul-30-92 -*/ - -int kbhit() +int kbhit(void) { if(WaitForChar(Input(), 1)) return 1; return 0; } -#ifdef LATTICE +/* GetSysTime problem with WB 1.3 fixed by A. Hartley (february@genie.com) */ + +extern struct timerequest *TimerIO; /* Defined in random.c */ + +void am_GetSysTime(struct timeval *tv) +{ + TimerIO->tr_node.io_Command=TR_GETSYSTIME; + DoIO((struct IORequest *) TimerIO); + *tv=TimerIO->tr_time; +} + +#ifdef __SASC /* - * Lattice-C ^C-Handler -*/ + * SAS/C CTRL-C handler + */ -int CXBRK() +void __regargs _CXBRK(void) { - BPTR in,out; struct MsgPort *ch; - in=Input(); - out=Output(); /* it might happen we catch a ^C while in cbreak mode. * so always set the screen to the normal mode. */ - ch = ((struct FileHandle *)BADDR(in))->fh_Type; + ch = ((struct FileHandle *)BADDR(Input()))->fh_Type; sendpacket(ch, ACTION_SCREEN_MODE, 0L); fprintf(pgpout, "\n*** Program Aborted.\n"); exitPGP(6); /* INTERRUPT */ } -#endif +#endif /* __SASC */ #endif /* AMIGA */ - /*===========================================================================*/ /* * other stuff for non-MSDOS systems */ #ifdef ATARI -#include +#ifdef __PUREC__ +#include +#else +#include /* use GEMDOS functions for I/O */ #endif +int kbhit(void) +{ + return Cconis(); /* ret == 0 : no char available */ +} + +int getch(void) +{ + return (Cnecin() & 0x000000FF); /* ASCII-Code in Bits 0..7 */ +} /* Scan-Codes in Bits 16..23 */ +#endif /* ATARI */ + #if !defined(MSDOS) && !defined(ATARI) #include +#include "charset.h" char *strlwr(char *s) { /* ** Turns string s into lower case. @@ -688,7 +1788,7 @@ char *strlwr(char *s) int c; char *p = s; while (c = *p) - *p++ = tolower(c); + *p++ = to_lower(c); return(s); } #endif /* !MSDOS && !ATARI */ @@ -751,3 +1851,154 @@ FILE *myfopen(char *filename, char *type } #endif /* not ATARI */ #endif /* fopen */ + + +#ifndef MSDOS +#ifdef OS2 + +static int chr = -1; + +int kbhit(void) +{ + if (chr == -1) + chr = _read_kbd(0, 0, 0); + return (chr != -1); +} + +int getch(void) +{ + int c; + + if (chr >= 0) { + c = chr; + chr = -1; + } else + c = _read_kbd(0, 1, 0); + + return c; +} + +#endif /* OS2 */ +#endif /* MSDOS */ + +#ifdef MACTC5 /* 203a */ + +#include "My_console.h" + +int getch(void) { + while( !kbhit() ); + return( getc(stdin) ); +} + +int kbhit(void) { + int kbuf; + + csetmode(C_RAW, stdin); + kbuf = getc(stdin); + if( kbuf != EOF ) ungetc((kbuf & 0xff), stdin); + csetmode(C_ECHO, stdin); + return( (kbuf == EOF) ? 0 : 1 ); +} + +#endif + +/*EWS Fix -f lockup on passphrase prompts for TURBO C++ */ +#if defined(MSDOS) && !defined(__GO32__) && defined(__TURBOC__) +#include +#include + +#if !defined(_KEYBRD_READY) +#define _KEYBRD_READY 1 /* To support old versions of Turbo C */ +#endif +#if !defined(_KEYBRD_READ) +#define _KEYBRD_READ 0 /* To support old versions of Turbo C */ +#endif + +int kbhit(void) +{ + int c; + c=bioskey(_KEYBRD_READY); + if (c != 0) c=1; + return c; +} /*kbhit*/ + +int getch(void) +{ + int c; + c=bioskey(_KEYBRD_READ); + if (c==11779) raise(SIGINT); /* Ctrl-C */ + return c & 0xff; +} /*getch*/ +#endif + +/*EWS Fix -f lockup on passphrase prompts for MSC */ +#if defined(MSDOS) && !defined(__GO32__) && defined(_MSC_VER) +#include +#include +#include + +int getcbrk(void) +{ + union REGS r; + + r.x.ax=0x3300; + intdos(&r, &r); + return(r.h.dl); +} + +int setcbrk(int xx) +{ + union REGS r; + + r.x.ax=0x3301; + r.h.dl=xx; + intdos(&r, &r); + return(r.h.dl); +} + +int kbhit(void) +{ + int c; + c=_bios_keybrd(_KEYBRD_READY); + if (c != 0) c=1; + return c; +} /*kbhit*/ + +int getch(void) +{ + int c; + c=_bios_keybrd(_KEYBRD_READ); + if (c==11779) raise(SIGINT); /* Ctrl-C */ + return c & 0xff; +} /*getch*/ +#endif + +#ifdef EBCDIC +static int kbuf = -1; + +int kbhit(void) +{ + int ch; + if (kbuf >= 0) + return 1; + if (ch = getchar()) { + kbuf = ch; + return 1; + } + return 0; +} + +int getch(void) +{ + int ch; + while (!kbhit()); + ch = kbuf; + kbuf = -1; + return ch; +} + +int c370_rename(char *from, char *to) +{ + return rename(from,to) == 0 ? 0 : -1; +} +#endif /* EBCDIC */