Annotation of pgp/src/system.c, revision 1.1.1.9

1.1.1.9 ! root        1: /*
        !             2:  * system.c
        !             3:  *
        !             4:  * Routines specific for non-MSDOS implementations of pgp.
        !             5:  * 
        !             6:  * (c) Copyright 1990-1996 by Philip Zimmermann.  All rights reserved.
        !             7:  * The author assumes no liability for damages resulting from the use
        !             8:  * of this software, even if the damage results from defects in this
        !             9:  * software.  No warranty is expressed or implied.
        !            10:  *
        !            11:  * Note that while most PGP source modules bear Philip Zimmermann's
        !            12:  * copyright notice, many of them have been revised or entirely written
        !            13:  * by contributors who frequently failed to put their names in their
        !            14:  * code.  Code that has been incorporated into PGP from other authors
        !            15:  * was either originally published in the public domain or is used with
        !            16:  * permission from the various authors.
        !            17:  *
        !            18:  * PGP is available for free to the public under certain restrictions.
        !            19:  * See the PGP User's Guide (included in the release package) for
        !            20:  * important information about licensing, patent restrictions on
        !            21:  * certain algorithms, trademarks, copyrights, and export controls.
        !            22:  *
        !            23:  *     Modified 24-Jun-92 HAJK
        !            24:  *     Adapt for VAX/VMS.
        !            25:  *
        !            26:  *     Modified: 11-Nov-92 HAJK
        !            27:  *     Add FDL Support Routines. 
        !            28:  *
        !            29:  *     Modified: 31-Jan-93 HAJK
        !            30:  *     Misc. updates for terminal handling.
        !            31:  *     Add VMS command stuff.
        !            32:  *     Add fileparse routine.
        !            33:  */
        !            34: #include <stdio.h>
        !            35: #include "exitpgp.h"
        !            36: #include "system.h"
        !            37: #include "usuals.h"
        !            38: 
        !            39: /*===========================================================================*/
        !            40: /*
        !            41:  * UNIX
        !            42:  */
        !            43: 
        !            44: #ifdef UNIX
        !            45: /*
        !            46:  * Define USE_SELECT to use the select() system call to check if
        !            47:  * keyboard input is available. Define USE_NBIO to use non-blocking
        !            48:  * read(). If you don't define anything the FIONREAD ioctl() command
        !            49:  * will be used.
        !            50:  *
        !            51:  * Define NOTERMIO if you don't have the termios stuff
        !            52:  */
        !            53: #include <sys/types.h>
        !            54: #include <fcntl.h>
        !            55: 
        !            56: #ifndef        NOTERMIO
        !            57: #ifndef SVR2
        !            58: #include <termios.h>
        !            59: #else
        !            60: #include <termio.h>
        !            61: #endif /* not SVR2 */
        !            62: #else
        !            63: #include <sgtty.h>
        !            64: #endif
        !            65: 
        !            66: #ifdef USE_SELECT
        !            67: #include <sys/time.h>
        !            68: #ifdef _IBMR2
        !            69: #include <sys/select.h>
        !            70: #endif /* _IBMR2 */
        !            71: #else
        !            72: #ifndef USE_NBIO
        !            73: #ifndef sun
        !            74: #include <sys/ioctl.h>         /* for FIONREAD */
        !            75: #else /* including both ioctl.h and termios.h gives a lot of warnings on sun */
        !            76: #include <sys/filio.h>
        !            77: #endif /* sun */
        !            78: #ifndef FIONREAD
        !            79: #define        FIONREAD        TIOCINQ
        !            80: #endif
        !            81: #endif
        !            82: #endif
        !            83: #include <signal.h>
        !            84: 
        !            85: static void setsigs(void);
        !            86: static void rmsigs(void);
        !            87: static void sig1(int);
        !            88: static void sig2(int);
        !            89: void breakHandler(int);
        !            90: static int ttyfd= -1;
        !            91: #ifndef SVR2
        !            92: static void (*savesig)(int);
        !            93: #else
        !            94: static int (*savesig)(int);
        !            95: #endif
        !            96: 
        !            97: void ttycbreak(void);
        !            98: void ttynorm(void);
        !            99: 
        !           100: #ifndef NEED_KBHIT
        !           101: #undef USE_NBIO
        !           102: #endif
        !           103: 
        !           104: #ifndef NOTERMIO
        !           105: #ifndef SVR2
        !           106: static struct termios itio, tio;
        !           107: #else
        !           108: static struct termio itio, tio;
        !           109: #endif /* not SVR2 */
        !           110: #else
        !           111: static struct sgttyb isg, sg;
        !           112: #endif
        !           113: 
        !           114: #ifdef USE_NBIO
        !           115: static int kbuf= -1;   /* buffer to store char read by kbhit() */
        !           116: static int fflags;
        !           117: #endif
        !           118: 
        !           119: static int gottio = 0;
        !           120: 
        !           121: void ttycbreak(void)
        !           122: {
        !           123:        if (ttyfd == -1) {
        !           124:                if ((ttyfd = open("/dev/tty", O_RDWR)) < 0) {
        !           125:                    fprintf(stderr, "cannot open tty, using stdin\n");
        !           126:                        ttyfd = 0;
        !           127:                }
        !           128:        }
        !           129: #ifndef NOTERMIO
        !           130: #ifndef SVR2
        !           131:        if (tcgetattr(ttyfd, &tio) < 0)
        !           132: #else
        !           133:        if (ioctl(ttyfd, TCGETA, &tio) < 0)
        !           134: #endif  /* not SVR2 */
        !           135:        {
        !           136:                fprintf (stderr, "\nUnable to get terminal characteristics: ");
        !           137:                perror("ioctl");
        !           138:                exitPGP(1);
        !           139:        }
        !           140:        itio = tio;
        !           141:        setsigs();
        !           142:        gottio = 1;
        !           143: #ifdef USE_NBIO
        !           144:        tio.c_cc[VMIN] = 0;
        !           145: #else
        !           146:        tio.c_cc[VMIN] = 1;
        !           147: #endif
        !           148:        tio.c_cc[VTIME] = 0;
        !           149:        tio.c_lflag &= ~(ECHO|ICANON);
        !           150: #ifndef SVR2
        !           151: #ifdef ultrix
        !           152:        /* Ultrix is broken and flushes the output as well! */
        !           153:        tcsetattr (ttyfd, TCSANOW, &tio);
        !           154: #else
        !           155:        tcsetattr (ttyfd, TCSAFLUSH, &tio);
        !           156: #endif
        !           157: #else
        !           158:        ioctl(ttyfd, TCSETAF, &tio);
        !           159: #endif /* not SVR2 */
        !           160: #else
        !           161:        if (ioctl(ttyfd, TIOCGETP, &sg) < 0) {
        !           162:                fprintf (stderr, "\nUnable to get terminal characteristics: ");
        !           163:                perror("ioctl");
        !           164:                exitPGP(1);
        !           165:        }
        !           166:        isg = sg;
        !           167:        setsigs();
        !           168:        gottio = 1;
        !           169: #ifdef CBREAK
        !           170:     sg.sg_flags |= CBREAK;
        !           171: #else
        !           172:     sg.sg_flags |= RAW;
        !           173: #endif
        !           174:        sg.sg_flags &= ~ECHO;
        !           175:     ioctl(ttyfd, TIOCSETP, &sg);
        !           176: #endif /* !NOTERMIO */
        !           177: #ifdef USE_NBIO
        !           178: #ifndef O_NDELAY
        !           179: #define        O_NDELAY        O_NONBLOCK
        !           180: #endif
        !           181:        if ((fflags = fcntl(ttyfd, F_GETFL, 0)) != -1)
        !           182:                fcntl(ttyfd, F_SETFL, fflags|O_NDELAY);
        !           183: #endif
        !           184: }
        !           185: 
        !           186: 
        !           187: void ttynorm(void)
        !           188: {      gottio = 0;
        !           189: #ifdef USE_NBIO
        !           190:        if (fcntl(ttyfd, F_SETFL, fflags) == -1)
        !           191:                perror("fcntl");
        !           192: #endif
        !           193: #ifndef NOTERMIO
        !           194: #ifndef SVR2
        !           195: #ifdef ultrix
        !           196:        /* Ultrix is broken and flushes the output as well! */
        !           197:        tcsetattr (ttyfd, TCSANOW, &itio);
        !           198: #else
        !           199:        tcsetattr (ttyfd, TCSAFLUSH, &itio);
        !           200: #endif
        !           201: #else
        !           202:        ioctl(ttyfd, TCSETAF, &itio);
        !           203: #endif /* not SVR2 */
        !           204: #else
        !           205:     ioctl(ttyfd, TIOCSETP, &isg);
        !           206: #endif
        !           207:        rmsigs();
        !           208: }
        !           209: 
        !           210: static void sig1 (int sig)
        !           211: {
        !           212: #ifndef NOTERMIO
        !           213: #ifndef SVR2
        !           214:        tcsetattr (ttyfd, TCSANOW, &itio);
        !           215: #else
        !           216:        ioctl(ttyfd, TCSETAW, &itio);
        !           217: #endif /* not SVR2 */
        !           218: #else
        !           219:     ioctl(ttyfd, TIOCSETP, &isg);
        !           220: #endif
        !           221:        signal (sig, SIG_DFL);
        !           222:        if (sig == SIGINT)
        !           223:                breakHandler(SIGINT);
        !           224:        kill (getpid(), sig);
        !           225: }
        !           226: 
        !           227: static void sig2 (int sig)
        !           228: {
        !           229:        if (gottio)
        !           230:                ttycbreak();
        !           231:        else
        !           232:                setsigs();
        !           233: }
        !           234: 
        !           235: static void setsigs(void)
        !           236: {
        !           237:        savesig = signal (SIGINT, sig1);
        !           238: #ifdef SIGTSTP
        !           239:        signal (SIGCONT, sig2);
        !           240:        signal (SIGTSTP, sig1);
        !           241: #endif
        !           242: }
        !           243: 
        !           244: static void rmsigs(void)
        !           245: {      signal (SIGINT, savesig);
        !           246: #ifdef SIGTSTP
        !           247:        signal (SIGCONT, SIG_DFL);
        !           248:        signal (SIGTSTP, SIG_DFL);
        !           249: #endif
        !           250: }
        !           251: 
        !           252: #ifdef NEED_KBHIT
        !           253: #ifndef CRUDE
        !           254: int kbhit(void)
        !           255: /* Return TRUE if there is a key to be read */
        !           256: {
        !           257: #ifdef USE_SELECT              /* use select() system call */
        !           258:        struct timeval t;
        !           259:        fd_set n;
        !           260:        int r;
        !           261: 
        !           262:        timerclear(&t);
        !           263:        FD_ZERO(&n);
        !           264:        FD_SET(ttyfd, &n);
        !           265:        r = select(32, &n, NULL, NULL, &t);
        !           266:        if (r == -1) {
        !           267:                perror("select");
        !           268:                exitPGP(1);
        !           269:        }
        !           270:        return r > 0;
        !           271: #else
        !           272: #ifdef USE_NBIO                /* use non-blocking read() */
        !           273:        unsigned char ch;
        !           274:        if (kbuf >= 0) 
        !           275:                return(1);
        !           276:        if (read(ttyfd, &ch, 1) == 1) {
        !           277:                kbuf = ch;
        !           278:                return(1);
        !           279:        }
        !           280:        return(0);
        !           281: #else
        !           282:        long lf;
        !           283:        if (ioctl(ttyfd, FIONREAD, &lf) == -1) {
        !           284:                perror("ioctl: FIONREAD");
        !           285:                exitPGP(1);
        !           286:        }
        !           287:        return(lf);
        !           288: #endif
        !           289: #endif
        !           290: }
        !           291: #endif /* !CRUDE */
        !           292: #endif
        !           293: 
        !           294: int getch(void)
        !           295: {
        !           296:        char c;
        !           297: #ifdef USE_NBIO
        !           298:        while (!kbhit());       /* kbhit() does the reading */
        !           299:        c = kbuf;
        !           300:        kbuf = -1;
        !           301: #else
        !           302:        c = 0;
        !           303:        read(ttyfd, &c, 1);
        !           304: #endif
        !           305:        return(c & 0xFF);
        !           306: }
        !           307: 
        !           308: #if defined(_BSD) && !defined(__STDC__)
        !           309: 
        !           310: VOID *memset(s, c, n)
        !           311: VOID *s;
        !           312: register int c, n;
        !           313: {
        !           314:        register char *p = s;
        !           315:        ++n;
        !           316:        while (--n)
        !           317:                *p++ = c;
        !           318:        return(s);
        !           319: }
        !           320: int memcmp(s1, s2, n)
        !           321: register unsigned char *s1, *s2;
        !           322: register int n;
        !           323: {
        !           324:        if (!n)
        !           325:                return(0);
        !           326:        while (--n && *s1 == *s2) {
        !           327:                ++s1;
        !           328:                ++s2;
        !           329:        }
        !           330:        return(*s1 - *s2);
        !           331: }
        !           332: VOID *memcpy(s1, s2, n)
        !           333: register char *s1, *s2;
        !           334: register int n;
        !           335: {
        !           336:        char *p = s1;
        !           337:        ++n;
        !           338:        while (--n)
        !           339:                *s1++ = *s2++;
        !           340:        return(p);
        !           341: }
        !           342: #endif /* _BSD */
        !           343: 
        !           344: #if (defined(MACH) || defined(SVR2) || defined(_BSD)) && !defined(NEXT) \
        !           345: && !defined(AUX) && !defined(__MACHTEN__) || (defined(sun) && defined(i386))
        !           346: int remove(name)
        !           347: char *name;
        !           348: {
        !           349:        return unlink(name);
        !           350: }
        !           351: #endif
        !           352: 
        !           353: #if defined(SVR2) && !defined(AUX)
        !           354: int rename(old, new)
        !           355: register char *old, *new;
        !           356: {
        !           357:        unlink(new);
        !           358:        if (link(old, new) < 0)
        !           359:                return -1;
        !           360:        if (unlink(old) < 0) {
        !           361:                unlink(new);
        !           362:                return -1;
        !           363:        }
        !           364:        return 0;
        !           365: }
        !           366: #endif /* SVR2 */
        !           367: 
        !           368: /* not all unices have clock() */
        !           369: long
        !           370: Clock()        /* not a replacement for clock(), just for random number generation */
        !           371: {
        !           372: #if defined(_BSD) || (defined(sun) && !defined(SOLARIS)) || \
        !           373: defined(MACH) || defined(linux)
        !           374: #include <sys/time.h>
        !           375: #include <sys/resource.h>
        !           376:        struct rusage ru;
        !           377: 
        !           378:        getrusage(RUSAGE_SELF, &ru);
        !           379:        return ru.ru_utime.tv_sec + ru.ru_utime.tv_usec +
        !           380:                ru.ru_stime.tv_sec + ru.ru_stime.tv_usec +
        !           381:                ru.ru_minflt + ru.ru_majflt +
        !           382:                ru.ru_inblock + ru.ru_oublock +
        !           383:                ru.ru_maxrss + ru.ru_nvcsw + ru.ru_nivcsw;
        !           384: 
        !           385: #else  /* no getrusage() */
        !           386: #include <sys/times.h>
        !           387:        struct tms tms;
        !           388: 
        !           389:        times(&tms);
        !           390:        return(tms.tms_utime + tms.tms_stime);
        !           391: #endif
        !           392: }
        !           393: #endif /* UNIX */
        !           394: 
        !           395: 
        !           396: /*===========================================================================*/
        !           397: /*
        !           398:  * VMS
        !           399:  */
        !           400: 
        !           401: #ifdef VMS                     /* kbhit()/getch() equivalent */
        !           402: 
        !           403: /*
        !           404:  * This code defines an equivalent version of kbhit() and getch() for
        !           405:  * use under VAX/VMS, together with an exit handler to reset terminal
        !           406:  * characteristics.
        !           407:  *
        !           408:  * This code assumes that kbhit() has been invoked to test that there
        !           409:  * are characters in the typeahead buffer before getch() is invoked to
        !           410:  * get the answer.
        !           411:  */
        !           412: 
        !           413: #include <signal.h>
        !           414: #include <string.h>
        !           415: #include <file.h>
        !           416: #include <ctype.h>
        !           417: #include "pgp.h"
        !           418: #include "mpilib.h"
        !           419: #include "mpiio.h"
        !           420: #include "fileio.h"
        !           421: extern byte textbuf[DISKBUFSIZE];   /* Defined in FILEIO.C */
        !           422: 
        !           423: /*       
        !           424: **  VMS Private Macros
        !           425: */       
        !           426: #include <descrip.h>
        !           427: #include <devdef>
        !           428: #include <iodef.h>
        !           429: #include <ttdef.h>
        !           430: #include <tt2def.h>
        !           431: #include <dcdef.h>
        !           432: #include <climsgdef.h>
        !           433: #include <rms.h>
        !           434: #include <hlpdef.h>
        !           435: 
        !           436: #define MAX_CMDSIZ     256  /*  Maximum command size */
        !           437: #define MAX_FILENM     255 /* Mamimum file name size */
        !           438: 
        !           439: #define FDL$M_FDL_STRING    2          /* Use string for fdl text */
        !           440: #define FDLSIZE                    4096        /* Maximum possible file size */
        !           441: 
        !           442: #ifdef _USEDCL_
        !           443: 
        !           444: /*
        !           445:  * Declare some external procedure prototypes (saves me confusion!)
        !           446:  */
        !           447: extern int lib$get_input(
        !           448:            struct dsc$descriptor *resultant,
        !           449:            struct dsc$descriptor *prompt, 
        !           450:            unsigned short *resultant_length);
        !           451: extern int lib$put_output(
        !           452:            struct dsc$descriptor *output);
        !           453: extern int lib$sig_to_ret();
        !           454: /*       
        !           455: **  The CLI routines are documented in the system routines manual.
        !           456: */       
        !           457: extern int cli$dcl_parse(
        !           458:            struct dsc$descriptor *command,
        !           459:            char cmd_table[],
        !           460:            int (*get_command)(
        !           461:                struct dsc$descriptor *resultant,
        !           462:                struct dsc$descriptor *prompt, 
        !           463:                unsigned short *resultant_length),
        !           464:            int (*get_parameter)(
        !           465:                struct dsc$descriptor *resultant,
        !           466:                struct dsc$descriptor *prompt, 
        !           467:                unsigned short *resultant_length),
        !           468:            struct dsc$descriptor *prompt);
        !           469: extern int cli$present( struct dsc$descriptor *object);
        !           470: extern int cli$_get_value(
        !           471:            struct dsc$descriptor *object,
        !           472:            struct dsc$decsriptor *value,
        !           473:            unsigned short *value_len);
        !           474: /*
        !           475:  * Static Data
        !           476:  */
        !           477: static $DESCRIPTOR (cmdprmt_d, "DROPSAFE> ");  /*  Prompt string */
        !           478: 
        !           479: #endif /* _USEDCL_ */
        !           480: 
        !           481: static volatile short  _kbhitChan_ = 0;
        !           482: 
        !           483: static volatile struct IOSB {
        !           484:        unsigned short sts;
        !           485:        unsigned short byteCount;
        !           486:        unsigned short terminator;
        !           487:        unsigned short terminatorSize;
        !           488:        } iosb;
        !           489: 
        !           490: static $DESCRIPTOR (kbdev_desc, "SYS$COMMAND:");
        !           491: 
        !           492: static volatile struct {
        !           493:        char Class;
        !           494:        char Type;
        !           495:        unsigned short BufferSize;
        !           496:        unsigned int Mode;
        !           497:        int ExtChar;
        !           498:   } CharBuf, OldCharBuf;
        !           499: 
        !           500: static $DESCRIPTOR (out_file_descr, "SYS$DISK:[]"); /* Default Output
        !           501:                                                       File Descr */
        !           502: 
        !           503: static int flags = FDL$M_FDL_STRING;
        !           504: 
        !           505: /*
        !           506:  * **-kbhit_handler-This exit handler restores the terminal characteristics
        !           507:  *
        !           508:  * Description:
        !           509:  *
        !           510:  * This procedure is invoked to return the the terminal to normality (depends
        !           511:  * on what you think is normal!). Anyway, it gets called to restore
        !           512:  * characteristics either through ttynorm or via an exit handler.
        !           513:  */
        !           514: static void kbhit_handler(int *sts)
        !           515: {
        !           516:   ttynorm();
        !           517:   (void) sys$dassgn (
        !           518:          _kbhitChan_);
        !           519:   _kbhitChan_ = 0;
        !           520: }
        !           521: 
        !           522: /*
        !           523:  * Data Structures For Linking Up Exit Handler 
        !           524:  */
        !           525: unsigned int exsts;
        !           526: 
        !           527: static struct {
        !           528:        int link;
        !           529:        VOID *rtn;
        !           530:        int argcnt;
        !           531:        int *stsaddr;
        !           532:    } exhblk = { 0, &(kbhit_handler), 1, &(exsts)};
        !           533: /*
        !           534:  * **-kbhit_Getchn-Get Channel
        !           535:  *
        !           536:  * Functional Description:
        !           537:  *
        !           538:  * Private routine to get a terminal channel and save the terminal
        !           539:  * characteristics.
        !           540:  *
        !           541:  * Arguments:
        !           542:  *
        !           543:  *  None.
        !           544:  *
        !           545:  * Returns:
        !           546:  *
        !           547:  *  If 0, channel already assigned. If odd, then assign was successful
        !           548:  * otherwise returns VMS error status.
        !           549:  *
        !           550:  * Implicit Inputs:
        !           551:  *
        !           552:  * _kbhitChan_ Channel assigned to the terminal (if any).
        !           553:  *
        !           554:  * Implicit Outputs:
        !           555:  *
        !           556:  *  OldCharBuf Initial terminal characteristics.
        !           557:  *  _kbhitChan_        Channel assigned to the terminal.
        !           558:  *
        !           559:  * Side Effects:
        !           560:  *
        !           561:  *  Establishes an exit handler to restore characteristics and deassign
        !           562:  * terminal channel.
        !           563:  */
        !           564: static int kbhit_Getchn()
        !           565: {
        !           566:     int sts = 0;
        !           567: 
        !           568:     if (_kbhitChan_ == 0) {
        !           569:        if ((sts = sys$assign (
        !           570:                           &kbdev_desc,
        !           571:                           &_kbhitChan_,
        !           572:                           0,
        !           573:                           0)) & 1) {
        !           574:            if ((sts = sys$qiow (
        !           575:                               0,
        !           576:                               _kbhitChan_,
        !           577:                               IO$_SENSEMODE,
        !           578:                               &iosb,
        !           579:                               0,
        !           580:                               0,
        !           581:                               &OldCharBuf,
        !           582:                               12,
        !           583:                               0,
        !           584:                               0,
        !           585:                               0,
        !           586:                               0)) & 01) sts = iosb.sts;
        !           587:            if (sts & 01) {
        !           588:              if (!(OldCharBuf.Class & DC$_TERM)) {
        !           589:                fprintf(stderr,"\nNot running on a terminal");
        !           590:                exitPGP(1);
        !           591:              }
        !           592:              (void) sys$dclexh (&exhblk);
        !           593:            }
        !           594:        }
        !           595:     }
        !           596:     return(sts);
        !           597: }
        !           598: /*       
        !           599:  * **-ttynorm-Restore initial terminal characteristics
        !           600:  *
        !           601:  * Functional Description:
        !           602:  *
        !           603:  * This procedure is invoked to restore the initial terminal characteristics.
        !           604:  */
        !           605: void ttynorm()
        !           606: /*
        !           607:  * Arguments:
        !           608:  *
        !           609:  *  None.
        !           610:  *
        !           611:  * Implicit Inputs:
        !           612:  *
        !           613:  *  OldCharBuf Initial terminal characteristics.
        !           614:  *  _kbhitChan_        Channel assigned to the terminal.
        !           615:  *
        !           616:  * Implicit Outputs:
        !           617:  *
        !           618:  *  None.
        !           619:  */      
        !           620: {
        !           621:   int sts;
        !           622: 
        !           623:   if (_kbhitChan_ != 0) {
        !           624:       CharBuf.Mode = OldCharBuf.Mode;
        !           625:       CharBuf.ExtChar = OldCharBuf.ExtChar;
        !           626:     /*
        !           627:       CharBuf.Mode &= ~TT$M_NOECHO;
        !           628:       CharBuf.ExtChar &= ~TT2$M_PASTHRU;
        !           629:     */
        !           630:       if ((sts = sys$qiow (
        !           631:                               0,
        !           632:                               _kbhitChan_,
        !           633:                               IO$_SETMODE,
        !           634:                               &iosb,
        !           635:                               0,
        !           636:                               0,
        !           637:                               &OldCharBuf,
        !           638:                               12,
        !           639:                               0,
        !           640:                               0,
        !           641:                               0,
        !           642:                               0)) & 01) sts = iosb.sts;
        !           643:       if (!(sts & 01)) {
        !           644:            fprintf(stderr,"\nFailed to reset terminal characteristics!");
        !           645:            (void) lib$signal(sts);
        !           646:       }
        !           647:    }
        !           648:    return;
        !           649: }
        !           650: /*
        !           651:  * **-kbhit-Find out if a key has been pressed
        !           652:  *
        !           653:  * Description:
        !           654:  *
        !           655:  * Make the terminal noecho and sense the characters coming in by looking at
        !           656:  * the typeahead count. Note that the character remains in the typeahead buffer
        !           657:  * untill either read, or that the user types a Control-X when not in 'passall'
        !           658:  * mode.
        !           659:  */
        !           660: int kbhit()
        !           661: /*
        !           662:  * Arguments:
        !           663:  *
        !           664:  *  None.
        !           665:  *
        !           666:  * Returns:
        !           667:  *
        !           668:  *  TRUE  if there is a character in the typeahead buffer.
        !           669:  *  FALSE if there is no character in the typeahead buffer.
        !           670:  */
        !           671: 
        !           672: 
        !           673: {
        !           674:   int sts;
        !           675: 
        !           676:   struct {
        !           677:        unsigned short TypAhdCnt;
        !           678:        char FirstChar;
        !           679:        char Reserved[5];
        !           680:   } TypCharBuf;
        !           681: 
        !           682:   /*
        !           683:   **  Get typeahead count
        !           684:   */
        !           685:   if ((sts = sys$qiow (
        !           686:                           0,
        !           687:                           _kbhitChan_,
        !           688:                           IO$_SENSEMODE | IO$M_TYPEAHDCNT,
        !           689:                           &iosb,
        !           690:                           0,
        !           691:                           0,
        !           692:                           &TypCharBuf,
        !           693:                           8,
        !           694:                           0,
        !           695:                           0,
        !           696:                           0,
        !           697:                           0)) & 01) sts = iosb.sts;
        !           698:   if (sts & 01) return(TypCharBuf.TypAhdCnt>0);
        !           699:   (void) lib$signal(sts);
        !           700:   exitPGP(1);
        !           701: }
        !           702: 
        !           703: static int NoTerm[2] = { 0, 0};  /*  TT Terminator Mask (Nothing) */
        !           704: 
        !           705: /*
        !           706:  * **-getch-Get a character and return it
        !           707:  *
        !           708:  * Description:
        !           709:  *
        !           710:  * Get a character from the keyboard and return it. Unlike Unix, the character
        !           711:  * will be explicitly echoed unless ttycbreak() has been called first. If the
        !           712:  * character is in the typeahead, that will be read first.
        !           713:  */
        !           714: int getch()
        !           715: /*
        !           716:  * Arguments:
        !           717:  *
        !           718:  *  None.
        !           719:  *
        !           720:  * Returns:
        !           721:  *
        !           722:  *  Character Read.
        !           723:  */
        !           724: {
        !           725:   unsigned int sts;
        !           726:   volatile char CharBuf;
        !           727: 
        !           728:   if (((sts = kbhit_Getchn()) & 01) || sts == 0) {
        !           729:       if ((sts = sys$qiow (
        !           730:                              0,
        !           731:                              _kbhitChan_,
        !           732:                              IO$_READVBLK,
        !           733:                              &iosb,
        !           734:                              0,
        !           735:                              0,
        !           736:                              &CharBuf,
        !           737:                              1,
        !           738:                              0,
        !           739:                              &NoTerm,
        !           740:                              0,
        !           741:                              0)) & 01) sts = iosb.sts;
        !           742:   }
        !           743:   if (sts & 01) return ((int) CharBuf);
        !           744:   fprintf(stderr,"\nFailed to get character");
        !           745:   (void) lib$signal(sts);
        !           746: }
        !           747: /*
        !           748:  * **-putch-Put Character To 'Console' Device
        !           749:  *
        !           750:  * This procedure is a companion to getch, outputing a character to the
        !           751:  * terminal with a minimum of fuss (no VAXCRTLK, no RMS!). This routine
        !           752:  * simply gets a channel (if there isn't one already and uses QIO to
        !           753:  * output.
        !           754:  *
        !           755:  */
        !           756: int putch(int chr)
        !           757: /*
        !           758:  * Arguments:
        !           759:  *  chr                Character to output.
        !           760:  *
        !           761:  * Returns:
        !           762:  *
        !           763:  *  Status return from Getchn and qio.
        !           764:  *
        !           765:  * Side Effects
        !           766:  *
        !           767:  * May assign a channel to the terminal.
        !           768:  */
        !           769: {
        !           770:   unsigned int sts;
        !           771: 
        !           772:   if (((sts = kbhit_Getchn()) & 01) || sts == 0) {
        !           773:       if ((sts = sys$qiow (
        !           774:                              0,
        !           775:                              _kbhitChan_,
        !           776:                              IO$_WRITEVBLK,
        !           777:                              &iosb,
        !           778:                              0,
        !           779:                              0,
        !           780:                              &chr,
        !           781:                              1,
        !           782:                              0,
        !           783:                              0,
        !           784:                              0,
        !           785:                              0)) & 01) sts = iosb.sts;
        !           786:   }
        !           787:   if (sts & 01) return (sts);
        !           788:   fprintf(stderr,"\nFailed to put character");
        !           789:   (void) lib$signal(sts);
        !           790: }
        !           791: /*
        !           792:  * **-ttycbreak-Set Unix-like Cbreak mode
        !           793:  *
        !           794:  * Functional Description:
        !           795:  *
        !           796:  * This code must be invoked to produce the Unix-like cbreak operation which
        !           797:  * disables echo, allows control character input.
        !           798:  */
        !           799: void ttycbreak ()
        !           800: /*
        !           801:  * Arguments:
        !           802:  *
        !           803:  *  None.
        !           804:  *
        !           805:  * Returns:
        !           806:  *
        !           807:  *  None.
        !           808:  *
        !           809:  * Side Effects
        !           810:  *
        !           811:  * May assign a channel to the terminal.
        !           812:  */
        !           813: {
        !           814:     struct {
        !           815:        unsigned short TypAhdCnt;
        !           816:        char FirstChar;
        !           817:        char Reserved[5];
        !           818:     } TypCharBuf;
        !           819:     char buf[80];
        !           820:     int sts;
        !           821: 
        !           822:     if (((sts = kbhit_Getchn()) & 01) || sts == 0) {
        !           823: /*
        !           824:  * Flush any typeahead before we change characteristics
        !           825:  */
        !           826:        if ((sts = sys$qiow (
        !           827:                               0,
        !           828:                               _kbhitChan_,
        !           829:                               IO$_SENSEMODE | IO$M_TYPEAHDCNT,
        !           830:                               &iosb,
        !           831:                               0,
        !           832:                               0,
        !           833:                               &TypCharBuf,
        !           834:                               8,
        !           835:                               0,
        !           836:                               0,
        !           837:                               0,
        !           838:                               0)) & 01) sts = iosb.sts;
        !           839:        if (sts) {
        !           840:            if (TypCharBuf.TypAhdCnt>0) {
        !           841:                if ((sts = sys$qiow (
        !           842:                            0,
        !           843:                           _kbhitChan_,
        !           844:                           IO$_READVBLK | IO$M_NOECHO | IO$M_TIMED,
        !           845:                           &iosb,
        !           846:                           0,
        !           847:                           0,
        !           848:                           &buf,
        !           849:                           (TypCharBuf.TypAhdCnt >= 80 ? 80 :
        !           850:                            TypCharBuf.TypAhdCnt),
        !           851:                           1,
        !           852:                           &NoTerm,
        !           853:                           0,
        !           854:                           0)) & 01) sts = iosb.sts;
        !           855:                           
        !           856:                if (sts)
        !           857:                    TypCharBuf.TypAhdCnt -= iosb.byteCount;
        !           858:            }
        !           859:        }
        !           860:        if (!(sts & 01)) TypCharBuf.TypAhdCnt = 0;
        !           861: /*
        !           862:  * Modify characteristics
        !           863:  */
        !           864:        CharBuf = OldCharBuf;
        !           865:        CharBuf.Mode = (OldCharBuf.Mode | TT$M_NOECHO) & ~TT$M_NOTYPEAHD;
        !           866:        CharBuf.ExtChar = OldCharBuf.ExtChar | TT2$M_PASTHRU;
        !           867:        if ((sts = sys$qiow (
        !           868:                       0,
        !           869:                       _kbhitChan_,
        !           870:                       IO$_SETMODE,
        !           871:                       &iosb,
        !           872:                       0,
        !           873:                       0,
        !           874:                       &CharBuf,
        !           875:                       12,
        !           876:                       0,
        !           877:                       0,
        !           878:                       0,
        !           879:                       0)) & 01) sts = iosb.sts;
        !           880:        if (!(sts & 01)) {
        !           881:          fprintf(stderr,
        !           882:                  "\nttybreak()- Failed to set terminal characteristics!");
        !           883:          (void) lib$signal(sts);
        !           884:          exitPGP(1);
        !           885:        }
        !           886:     }
        !           887: }
        !           888: 
        !           889: 
        !           890: #ifdef _USEDCL_
        !           891: 
        !           892: /*
        !           893:  * **-vms_getcmd-Get VMS Style Foreign Command
        !           894:  *
        !           895:  * Functional Description:
        !           896:  *
        !           897:  *  Get command from VAX/VMS foreign command line interface and parse
        !           898:  * according to DCL rules. If the command line is ok, it can then be
        !           899:  * parsed according to the rules in the DCL command language table.
        !           900:  *
        !           901:  */
        !           902: int vms_GetCmd( char *cmdtbl)
        !           903: /*
        !           904:  * Arguments:
        !           905:  *
        !           906:  *  cmdtbl     Pointer to command table to parse.
        !           907:  *
        !           908:  * Returns:
        !           909:  *
        !           910:  *  ...TBS...
        !           911:  *
        !           912:  * Implicit Inputs:
        !           913:  *
        !           914:  *  Command language table defined in DROPDCL.CLD
        !           915:  */
        !           916: {
        !           917:     int sts;
        !           918:     char cmdbuf[MAX_CMDSIZ];
        !           919:     unsigned short cmdsiz;
        !           920:     struct dsc$descriptor cmdbuf_d = {0,0,0,0};
        !           921:     struct dsc$descriptor infile_d = {0,0,0,0};
        !           922:     char filenm[MAX_FILENM];
        !           923:     unsigned short filenmsiz;
        !           924:     unsigned short verb_size;
        !           925: 
        !           926:     /*   
        !           927:     **  DCL Parse Expects A Command Verb Prefixing The Argumnents
        !           928:     ** fake it!
        !           929:     */   
        !           930:     verb_size = cmdprmt_d.dsc$w_length - 2;  /*  Loose '> ' characters */
        !           931:     cmdbuf_d.dsc$w_length = MAX_CMDSIZ-verb_size-1;
        !           932:     cmdbuf_d.dsc$a_pointer = strncpy(cmdbuf,cmdprmt_d.dsc$a_pointer,verb_size)
        !           933:       +        verb_size+1;
        !           934:     cmdbuf[verb_size++]=' ';
        !           935:     if ((sts = lib$get_foreign (  /*  Recover command line from DCL */
        !           936:                   &cmdbuf_d, 
        !           937:                   0, 
        !           938:                   &cmdsiz, 
        !           939:                   0)) & 01) {
        !           940:        cmdbuf_d.dsc$a_pointer = cmdbuf;
        !           941:        cmdbuf_d.dsc$w_length = cmdsiz + verb_size;
        !           942:        VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions
        !           943:                                              to return */
        !           944:         sts = cli$dcl_parse(  /*  Parse Command Line */
        !           945:                    &cmdbuf_d,
        !           946:                    cmdtbl,                     
        !           947:                    lib$get_input,
        !           948:                    lib$get_input,
        !           949:                    &cmdprmt_d);
        !           950:     }
        !           951:     return(sts);
        !           952: }
        !           953: /*
        !           954:  * **-vms_TstOpt-Test for command qualifier present
        !           955:  *
        !           956:  * Functional Description:
        !           957:  *
        !           958:  * This procedure is invoked to test whether an option is present. It is
        !           959:  * really just a jacket routine for the system routine CLI$PRESENT
        !           960:  * converting the argument and result into 'C' speak.
        !           961:  *
        !           962:  */
        !           963: vms_TstOpt(char opt)
        !           964: /*
        !           965:  * Arguments:
        !           966:  *
        !           967:  *  opt            Character label of qualifier to test for.
        !           968:  *
        !           969:  * Returns:
        !           970:  *
        !           971:  *  +1 Option present.
        !           972:  *  0  Option absent.
        !           973:  *  -1 Option negated.
        !           974:  *
        !           975:  * Implicit Inputs:
        !           976:  *
        !           977:  * Uses DCL command line context established by vms_GetOpt.
        !           978:  */
        !           979: {
        !           980:     int sts;
        !           981:     char buf;
        !           982:     struct dsc$descriptor option_d = { 1, 0, 0, &buf};
        !           983: 
        !           984:     buf = _toupper(opt);
        !           985:     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions
        !           986:                                          to return */
        !           987:     switch (sts=cli$present(&option_d))
        !           988:     {
        !           989: 
        !           990:        case CLI$_PRESENT :
        !           991:            return(1);
        !           992:        case CLI$_ABSENT:
        !           993:            return(0);
        !           994:        case CLI$_NEGATED:
        !           995:            return(-1);
        !           996:        default:
        !           997:            return(0);
        !           998:     }    
        !           999: }
        !          1000: /*
        !          1001:  * **-vms_GetVal-Get Qualifier Value.
        !          1002:  *
        !          1003:  * Functional Description:
        !          1004:  *
        !          1005:  * This procedure is invoked to return the value associated with a
        !          1006:  * qualifier that exists (See TstOpt).
        !          1007:  */
        !          1008: vms_GetVal( char opt, char *resval, unsigned short maxsiz)
        !          1009: /*
        !          1010:  * Arguments:
        !          1011:  *
        !          1012:  *  opt            Character label of qualifier to test for.
        !          1013:  *  resval  Pointer to resulting value string.
        !          1014:  *  maxsiz  Maximum size of string.
        !          1015:  *
        !          1016:  * Returns:
        !          1017:  *
        !          1018:  *  ...TBS...
        !          1019:  *
        !          1020:  * Implicit Inputs:
        !          1021:  *
        !          1022:  * Uses DCL command line context established by vms_GetOpt.
        !          1023:  */
        !          1024: {
        !          1025:     int sts;
        !          1026:     char buf;
        !          1027:     struct dsc$descriptor option_d = { 1, 0, 0, &buf};
        !          1028:     struct dsc$descriptor value_d = {maxsiz-1, 0, 0, resval };
        !          1029:     unsigned short valsiz;
        !          1030: 
        !          1031:     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions
        !          1032:                                          to return */
        !          1033:     buf = _toupper(opt);
        !          1034:     if ((sts = cli$get_value( 
        !          1035:            &option_d,
        !          1036:            &value_d,
        !          1037:            &valsiz)) & 01) resval[valsiz] = '\0';
        !          1038:     return(sts);
        !          1039: }
        !          1040: /*
        !          1041:  * **-vms_GetArg-Get Argument Value.
        !          1042:  *
        !          1043:  * Functional Description:
        !          1044:  *
        !          1045:  * This procedure is invoked to return the value associated with an
        !          1046:  * argument.
        !          1047:  */
        !          1048: vms_GetArg( unsigned short arg, char *resval, unsigned short maxsiz)
        !          1049: /*
        !          1050:  * Arguments:
        !          1051:  *
        !          1052:  *  arg            Argument Number (1-9)
        !          1053:  *  resval  Pointer to resulting value string.
        !          1054:  *  maxsiz  Maximum size of string.
        !          1055:  *
        !          1056:  * Returns:
        !          1057:  *
        !          1058:  *  ...TBS...
        !          1059:  *
        !          1060:  * Implicit Inputs:
        !          1061:  *
        !          1062:  * Uses DCL command line context established by vms_GetOpt.
        !          1063:  */
        !          1064: {
        !          1065:     int sts;
        !          1066:     char buf[2] = "P";
        !          1067:     struct dsc$descriptor option_d = { 2, 0, 0, buf};
        !          1068:     struct dsc$descriptor value_d = {maxsiz-1, 0, 0, resval };
        !          1069:     unsigned short valsiz;
        !          1070: 
        !          1071:     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions
        !          1072:                                          to return */
        !          1073:     buf[1] = arg + '0';
        !          1074:     if ((sts = cli$present(&option_d)) & 01) {
        !          1075:        if ((sts = cli$get_value( 
        !          1076:            &option_d,
        !          1077:            &value_d,
        !          1078:            &valsiz)) & 01) resval[valsiz] = '\0';
        !          1079:     } else return(0);
        !          1080:     return(sts);
        !          1081: }
        !          1082: 
        !          1083: 
        !          1084: 
        !          1085: /*
        !          1086:  * **-do_help-Invoke VMS Help Processor
        !          1087:  *
        !          1088:  * Functional Description:
        !          1089:  *
        !          1090:  * This procedure is invoked to display a suitable help message to the caller
        !          1091:  * using the standard VMS help library.
        !          1092:  *
        !          1093:  */
        !          1094: do_help(char *helptext, char *helplib)
        !          1095: /*
        !          1096:  * Arguments:
        !          1097:  *
        !          1098:  *  helptext   Text of help request.
        !          1099:  *  helplib    Help library.
        !          1100:  *
        !          1101:  * Returns:
        !          1102:  *
        !          1103:  * As for kbhit_Getchn and lbr$output_help.
        !          1104:  *
        !          1105:  * Side Effects:
        !          1106:  *
        !          1107:  * A channel may be opened to the terminal. A library is opened.
        !          1108:  */
        !          1109: {
        !          1110:     int sts;
        !          1111:     int helpflags;
        !          1112:     struct dsc$descriptor helptext_d = { strlen(helptext), 0, 0, helptext};
        !          1113:     struct dsc$descriptor helplib_d = { strlen(helplib), 0, 0, helplib};
        !          1114: 
        !          1115:     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled
        !          1116:                                          exceptions to return */
        !          1117:     if (((sts = kbhit_Getchn()) & 01) || sts == 0) {
        !          1118:        helpflags = HLP$M_PROMPT|HLP$M_SYSTEM|HLP$M_GROUP|HLP$M_PROCESS;    
        !          1119:        sts = lbr$output_help(
        !          1120:                    lib$put_output,
        !          1121:                    &OldCharBuf.BufferSize,
        !          1122:                    &helptext_d,
        !          1123:                    &helplib_d,
        !          1124:                    &helpflags,
        !          1125:                    lib$get_input);
        !          1126:     }
        !          1127:     return(sts);
        !          1128: }
        !          1129: #endif /* _USEDCL_ */
        !          1130: unsigned long vms_clock_bits[2];      /* VMS Hardware Clock */
        !          1131: const long     vms_ticks_per_update = 100000L; /* Clock update int. */
        !          1132: 
        !          1133: /*
        !          1134:  * FDL Stuff For Getting & Setting File Characteristics
        !          1135:  * This code was derived (loosely!) from the module LZVIO.C in the public 
        !          1136:  * domain LZW compress routine as found on the DECUS VAX SIG tapes (no author
        !          1137:  * given, so no credits!) 
        !          1138:  */
        !          1139: 
        !          1140: /*
        !          1141:  * **-fdl_generate-Generate An FDL
        !          1142:  *
        !          1143:  * Description:
        !          1144:  *
        !          1145:  * This procedure takes the name of an existing file as input and creates
        !          1146:  * an fdl. The FDL is retuned by pointer and length. The FDL space should be
        !          1147:  * released after use with a call to free();
        !          1148:  */
        !          1149: int fdl_generate(char *in_file, char **fdl, short *len)
        !          1150: /*
        !          1151:  * Arguments:
        !          1152:  *
        !          1153:  *     in_file     char*   Filename of file to examine (Zero terminated).
        !          1154:  *
        !          1155:  *     fdl         char*   Pointer to FDL that was created.
        !          1156:  *
        !          1157:  *     len         short   Length of FDL created.
        !          1158:  *
        !          1159:  * Status Returns:
        !          1160:  *
        !          1161:  * VMS style. lower bit set means success.
        !          1162:  */
        !          1163: {
        !          1164: 
        !          1165:     struct dsc$descriptor fdl_descr = { 0,
        !          1166:                                DSC$K_DTYPE_T,
        !          1167:                                DSC$K_CLASS_D,
        !          1168:                                0};
        !          1169:     struct FAB fab, *fab_addr;
        !          1170:     struct RAB rab, *rab_addr;
        !          1171:     struct NAM nam;
        !          1172:     struct XABFHC xab;
        !          1173:     int sts;
        !          1174:     int badblk;
        !          1175: 
        !          1176: /*
        !          1177:  * Build FDL Descriptor
        !          1178:  */
        !          1179:     if (!(sts = str$get1_dx(&FDLSIZE,&fdl_descr)) & 01) return(0);
        !          1180: /*
        !          1181:  * Build RMS Data Structures
        !          1182:  */
        !          1183:     fab = cc$rms_fab;
        !          1184:     fab_addr = &fab;
        !          1185:     nam = cc$rms_nam;
        !          1186:     rab = cc$rms_rab;
        !          1187:     rab_addr = &rab;
        !          1188:     xab = cc$rms_xabfhc;
        !          1189:     fab.fab$l_nam = &nam;
        !          1190:     fab.fab$l_xab = &xab;
        !          1191:     fab.fab$l_fna = in_file;
        !          1192:     fab.fab$b_fns = strlen(in_file);
        !          1193:     rab.rab$l_fab = &fab;
        !          1194:     fab.fab$b_fac = FAB$M_GET | FAB$M_BIO; /* This open block mode only */
        !          1195: /*
        !          1196:  * Attempt to Open File
        !          1197:  */
        !          1198:     if (!((sts = sys$open(&fab)) & 01)) {
        !          1199:        if (verbose) {
        !          1200:            fprintf(stderr,"\n(SYSTEM) Failed to $OPEN %s\n",in_file);
        !          1201:            (void) lib$signal(fab.fab$l_sts,fab.fab$l_stv);
        !          1202:        }
        !          1203:        return(sts);
        !          1204:     }
        !          1205:     if (fab.fab$l_dev & DEV$M_REC) {
        !          1206:        fprintf(stderr,"\n(SYSTEM) Attempt to read from output only device\n");
        !          1207:        sts = 0;
        !          1208:     } else {
        !          1209:        rab.rab$l_rop = RAB$M_BIO;
        !          1210:        if (!((sts = sys$connect(&rab)) & 01)) {
        !          1211:            if (verbose) {
        !          1212:                fprintf(stderr,"\n(SYSTEM) Failed to $CONNECT %s\n",in_file);
        !          1213:                (void) lib$signal(fab.fab$l_sts,fab.fab$l_stv);
        !          1214:            }
        !          1215:        } else {
        !          1216:            if (!((sts = fdl$generate(
        !          1217:                        &flags,
        !          1218:                        &fab_addr,
        !          1219:                        &rab_addr,
        !          1220:                        NULL,NULL,
        !          1221:                        &fdl_descr,
        !          1222:                        &badblk,
        !          1223:                        len)) & 01)) {
        !          1224:                if (verbose)
        !          1225:                  fprintf(stderr,"\n(SYSTEM) Failed to generate FDL\n",
        !          1226:                          in_file);
        !          1227:                free(fdl);
        !          1228:            } else {
        !          1229:                if (!(*fdl = malloc(*len))) return(0);
        !          1230:                memcpy(*fdl,fdl_descr.dsc$a_pointer,*len);
        !          1231:            }
        !          1232:            (void) str$free1_dx(&fdl_descr);
        !          1233:        }
        !          1234:         sys$close(&fab);
        !          1235:     }
        !          1236:     return(sts);           
        !          1237: }
        !          1238: 
        !          1239: /*       
        !          1240:  * **-fdl_close-Closes files created by fdl_generate
        !          1241:  *  
        !          1242:  * Description:
        !          1243:  *
        !          1244:  * This procedure is invoked to close the file and release the data structures
        !          1245:  * allocated by fdl$parse.
        !          1246:  */
        !          1247: void fdl_close(void* rab)
        !          1248: /*
        !          1249:  * Arguments:
        !          1250:  *
        !          1251:  *     rab     VOID *  Pointer to RAB (voided to avoid problems for caller).
        !          1252:  *
        !          1253:  * Returns:
        !          1254:  *
        !          1255:  *     None.
        !          1256:  */
        !          1257: {
        !          1258:     struct FAB *fab;
        !          1259: 
        !          1260:     fab = ((struct RAB *) rab)->rab$l_fab;
        !          1261:     if (fab) {  /*  Close file if not already closed */
        !          1262:        if (fab->fab$w_ifi) sys$close(fab);
        !          1263:     }
        !          1264:     fdl$release( NULL, &rab);    
        !          1265: }
        !          1266: 
        !          1267: /*
        !          1268:  * **-fdl_create-Create A File Using the recorded FDL (hope we get it right!)
        !          1269:  *
        !          1270:  * Description:
        !          1271:  *
        !          1272:  * This procedure accepts an FDL and uses it create a file. Unfortunately
        !          1273:  * there is no way we can easily patch into the back of the VAX C I/O
        !          1274:  * subsystem.
        !          1275:  */
        !          1276: VOID * fdl_create( char *fdl, short len, char *outfile, char *preserved_name)
        !          1277: /*
        !          1278:  * Arguments:
        !          1279:  *
        !          1280:  *     fdl     char*   FDL string descriptor.
        !          1281:  *
        !          1282:  *     len     short   Returned string length.
        !          1283:  *
        !          1284:  *     outfile char*   Output filename.
        !          1285:  *
        !          1286:  *     preserved_name char*    Name from FDL.
        !          1287:  *
        !          1288:  * Returns:
        !          1289:  *
        !          1290:  *     0 in case of error, or otherwise the RAB pointer.
        !          1291:  */
        !          1292: {
        !          1293:     VOID *sts;
        !          1294:     int sts2;
        !          1295:     struct FAB *fab;
        !          1296:     struct RAB *rab;
        !          1297:     struct NAM nam;
        !          1298:     int badblk;
        !          1299:     char *resnam;
        !          1300: 
        !          1301:     struct dsc$descriptor fdl_descr = {
        !          1302:                            len,
        !          1303:                            DSC$K_DTYPE_T,
        !          1304:                            DSC$K_CLASS_S,
        !          1305:                            fdl
        !          1306:                            };
        !          1307: 
        !          1308:     sts = NULL;
        !          1309: /*
        !          1310:  * Initialize RMS NAM Block
        !          1311:  */
        !          1312:     nam = cc$rms_nam;
        !          1313:     nam.nam$b_rss = NAM$C_MAXRSSLCL;
        !          1314:     nam.nam$b_ess = NAM$C_MAXRSSLCL;
        !          1315:     if (!(resnam = nam.nam$l_esa = malloc(NAM$C_MAXRSSLCL+1))) {
        !          1316:        fprintf(stderr,"\n(FDL_CREATE) Out of memory!\n");
        !          1317:        return(NULL);
        !          1318:     }
        !          1319: /*
        !          1320:  * Parse FDL
        !          1321:  */
        !          1322:     if (!((sts2 = fdl$parse( &fdl_descr,
        !          1323:                                &fab,
        !          1324:                                &rab,
        !          1325:                                &flags)) & 01)) {
        !          1326:        fprintf(stderr,"\nCreating (fdl$parse)\n");
        !          1327:        (void) lib$signal(sts2);
        !          1328:     } else {
        !          1329: /*
        !          1330:  * Extract & Return Name of FDL Supplied Filename
        !          1331:  */
        !          1332:        memcpy (preserved_name,fab->fab$l_fna,fab->fab$b_fns);
        !          1333:        preserved_name[fab->fab$b_fns] = '\0';
        !          1334: /*
        !          1335:  * Set Name Of Temporary File
        !          1336:  */
        !          1337:        fab->fab$l_fna = outfile;
        !          1338:        fab->fab$b_fns = strlen(outfile);
        !          1339: /*
        !          1340:  * Connect NAM Block
        !          1341:  */
        !          1342:        fab->fab$l_nam = &nam;
        !          1343:        fab->fab$l_fop |= FAB$M_NAM | FAB$M_CIF;
        !          1344:        fab->fab$b_fac |= FAB$M_BIO | FAB$M_PUT;
        !          1345: /*
        !          1346:  * Create File
        !          1347:  */
        !          1348:        if (!(sys$create(fab) & 01)) {
        !          1349:            fprintf(stderr,"\nCreating (RMS)\n");
        !          1350:            (void) lib$signal(fab->fab$l_sts,fab->fab$l_stv);
        !          1351:            fdl_close(rab);
        !          1352:        } else {
        !          1353:            if (verbose) {
        !          1354:                resnam[nam.nam$b_esl+1] = '\0';
        !          1355:                fprintf(stderr,"\nCreated %s successfully\n",resnam);
        !          1356:            }
        !          1357:            rab->rab$l_rop = RAB$M_BIO;
        !          1358:            if (!(sys$connect(rab) & 01)) {
        !          1359:                fprintf(stderr,"\nConnecting (RMS)\n");
        !          1360:                (void) lib$signal(rab->rab$l_sts,rab->rab$l_stv);
        !          1361:                fdl_close(rab);
        !          1362:            } else sts = rab;
        !          1363:        }
        !          1364:        fab->fab$l_nam = 0; /* I allocated NAM block,
        !          1365:                               so I must deallocate it! */
        !          1366:     }
        !          1367:     free(resnam);
        !          1368:     return(sts);               
        !          1369: }
        !          1370: 
        !          1371: /*
        !          1372:  * **-fdl_copyfile2bin-Copies the input file to a 'binary' output file
        !          1373:  *
        !          1374:  * Description:
        !          1375:  *
        !          1376:  * This procedure is invoked to copy from an opened file f to a file opened
        !          1377:  * directly through RMS. This allows us to make a block copy into one of the
        !          1378:  * many esoteric RMS file types thus preserving characteristics without blowing
        !          1379:  * up the C RTL. This code is based directly on copyfile from FILEIO.C.
        !          1380:  *
        !          1381:  * Calling Sequence:
        !          1382:  */
        !          1383: int fdl_copyfile2bin( FILE *f, VOID *rab, word32 longcount)
        !          1384: /*
        !          1385:  * Arguments:
        !          1386:  *
        !          1387:  *     f           FILE*       Pointer to input file
        !          1388:  *
        !          1389:  *     rab         RAB*        Pointer to output file RAB
        !          1390:  * 
        !          1391:  *     longcount   word32      Size of file
        !          1392:  *
        !          1393:  * Returns:
        !          1394:  *
        !          1395:  *     0   If we were successful.
        !          1396:  *     -1  We had an error on the input file (VAXCRTL).
        !          1397:  *     +1  We had an error on the output file (direct RMS).
        !          1398:  */
        !          1399: {
        !          1400:     int status = 0;
        !          1401:     word32 count;
        !          1402:     ((struct RAB *) rab)->rab$l_rbf = &textbuf;
        !          1403:     ((struct RAB *) rab)->rab$l_bkt = 0;
        !          1404:     do { /*  Read and write longcount bytes */
        !          1405:        if (longcount < (word32) DISKBUFSIZE)
        !          1406:            count = longcount;
        !          1407:        else
        !          1408:            count = DISKBUFSIZE;
        !          1409:        count = fread(textbuf,1,count,f);
        !          1410:        if (count > 0) {
        !          1411: /*       
        !          1412:  *  No byte order conversion required, source and target system are both
        !          1413:  *  VMS so have the same byte ordering.
        !          1414:  */      
        !          1415:            ((struct RAB *) rab)->rab$w_rsz = (unsigned short) count;
        !          1416:            if (!(sys$write (
        !          1417:                       rab, 
        !          1418:                       NULL, 
        !          1419:                       NULL) & 01)) {
        !          1420:                  lib$signal(((struct RAB *) rab)->rab$l_sts,
        !          1421:                             ((struct RAB *) rab)->rab$l_stv);
        !          1422:                  status = 1;
        !          1423:                  break;
        !          1424:            }
        !          1425:            longcount -= count;
        !          1426:        }
        !          1427:     } while (count==DISKBUFSIZE);
        !          1428:     burn(textbuf);
        !          1429:     return(status);
        !          1430: }
        !          1431: /*
        !          1432:  * **-vms_fileparse-Parse A VMS File Specification
        !          1433:  *
        !          1434:  * Functional Description:
        !          1435:  *
        !          1436:  * This procedure is invoked to parse a VMS file specification using default 
        !          1437:  * and related specifications to fill in any missing components. This works a 
        !          1438:  * little like DCL's F$PARSE function with the syntax check only specified
        !          1439:  * (that is we don't check the device or the directory). The related file
        !          1440:  * spec is really for when we want to use the name of an input file (w/o the
        !          1441:  * directory) to supply the name of an output file.
        !          1442:  *
        !          1443:  * Note that we correctly handle the situation where the output buffer overlays
        !          1444:  * the input filespec by testing for the case and then handling it by copying
        !          1445:  * the primary input specification to a temporary buffer before parsing.
        !          1446:  */
        !          1447: int vms_fileparse( char *outbuf, char *filespec, char *defspec, char *relspec)
        !          1448: /*
        !          1449:  * Arguments:
        !          1450:  *
        !          1451:  *  outbuf     Returned file specification.
        !          1452:  *  filespec   Primary file specification (optional).
        !          1453:  *  defspec    Default file specification (optional).
        !          1454:  *  relspec    Related file specification (optional).
        !          1455:  *
        !          1456:  * Returns:
        !          1457:  *
        !          1458:  *  As for SYS$PARSE.
        !          1459:  *
        !          1460:  * Implicit Inputs:
        !          1461:  *
        !          1462:  *  None.
        !          1463:  *
        !          1464:  * Implicit Outputs:
        !          1465:  *
        !          1466:  *  None.
        !          1467:  *
        !          1468:  * Side Effects:
        !          1469:  *
        !          1470:  *  ...TBS...
        !          1471:  */
        !          1472: {
        !          1473:     struct FAB fab = cc$rms_fab;
        !          1474:     struct NAM nam = cc$rms_nam;
        !          1475:     struct NAM rlnam = cc$rms_nam;
        !          1476:     int sts = 1;
        !          1477:     int len;
        !          1478:     char tmpbuf[NAM$C_MAXRSSLCL];
        !          1479:     char expfnam2[NAM$C_MAXRSSLCL];
        !          1480: 
        !          1481:     if (outbuf != NULL) {
        !          1482:        outbuf[0] = '\0';
        !          1483:        fab.fab$l_fop != FAB$M_NAM;  /*  Enable RMS NAM block processing */
        !          1484:        nam.nam$b_nop |= NAM$M_PWD | NAM$M_SYNCHK;
        !          1485:        /*        
        !          1486:        **  Handle Related Spec (If reqd).
        !          1487:        */        
        !          1488:        if (relspec != NULL) {
        !          1489:            if ((len = strlen(relspec)) > 0) {
        !          1490:                fab.fab$l_nam = &rlnam;
        !          1491:                fab.fab$b_fns = len;
        !          1492:                fab.fab$l_fna = relspec;
        !          1493:                rlnam.nam$b_ess = NAM$C_MAXRSSLCL;
        !          1494:                rlnam.nam$l_esa = expfnam2;
        !          1495:                rlnam.nam$b_nop |= NAM$M_PWD | NAM$M_SYNCHK;
        !          1496:                if ((sts = sys$parse (
        !          1497:                            &fab, 
        !          1498:                            0, 
        !          1499:                            0)) & 01) {
        !          1500:                    rlnam.nam$l_rsa = rlnam.nam$l_esa;
        !          1501:                    rlnam.nam$b_rsl = rlnam.nam$b_esl;
        !          1502:                    nam.nam$l_rlf = &rlnam;
        !          1503:                    fab.fab$l_fop |= FAB$M_OFP;
        !          1504:                }
        !          1505:            }
        !          1506:        }
        !          1507:        if (sts) {
        !          1508:            fab.fab$l_nam = &nam;
        !          1509:            nam.nam$l_esa = outbuf;
        !          1510:            nam.nam$b_ess = NAM$C_MAXRSSLCL;
        !          1511:            /*    
        !          1512:            **  Process Default Specification:
        !          1513:            */    
        !          1514:            if (defspec != NULL) {
        !          1515:                if ((len = strlen(defspec)) > 0) {
        !          1516:                    fab.fab$l_dna = defspec;
        !          1517:                    fab.fab$b_dns = len;
        !          1518:                }
        !          1519:            }
        !          1520:            /*    
        !          1521:            **  Process Main File Specification:
        !          1522:            */    
        !          1523:            fab.fab$l_fna = NULL;
        !          1524:            fab.fab$b_fns = 0;
        !          1525:            if (filespec != NULL) {
        !          1526:                if ((len = strlen(filespec)) > 0) {
        !          1527:                    fab.fab$b_fns = len;
        !          1528:                    if (filespec == outbuf)
        !          1529:                        fab.fab$l_fna = memcpy(tmpbuf,filespec,len);
        !          1530:                    else
        !          1531:                        fab.fab$l_fna = filespec;
        !          1532:                }
        !          1533:            }
        !          1534:            if ((sts = sys$parse(
        !          1535:                       &fab, 
        !          1536:                       0, 
        !          1537:                       0)) && 01) outbuf[nam.nam$b_esl] = '\0';
        !          1538:        }
        !          1539:     }
        !          1540:     return (sts);
        !          1541: }
        !          1542: #endif /* VMS */
        !          1543: 
        !          1544: 
        !          1545: /*
        !          1546:  * ------------------------- Amiga specific routines -------------------------
        !          1547:  */
        !          1548: 
        !          1549: #ifdef AMIGA
        !          1550: 
        !          1551: #include <time.h>
        !          1552: #include <dos/var.h>
        !          1553: #include <exec/memory.h>
        !          1554: #include <exec/ports.h>
        !          1555: #include <exec/types.h>
        !          1556: #include <libraries/dosextens.h>
        !          1557: #include <libraries/reqtools.h>
        !          1558: #include <proto/dos.h> 
        !          1559: #include <proto/exec.h>
        !          1560: #include <proto/reqtools.h>
        !          1561: #include "pgp.h"
        !          1562: 
        !          1563: /*
        !          1564:  * This getenv will use the WB2.0 calls if you have the 2.0
        !          1565:  * rom. If not, it resorts to looking in the ENV: directory.
        !          1566:  */
        !          1567: 
        !          1568: /*
        !          1569:  * I am sorry to report that SAS/C is buggy. :-(
        !          1570:  * It doesn't recognize replacement routines if they are linked
        !          1571:  * to the main code and not included in the file itself. I hate
        !          1572:  * stuff like that. :-(
        !          1573:  *                                            -peter
        !          1574:  */
        !          1575: 
        !          1576: char *amiga_getenv(const char *name)
        !          1577: {
        !          1578:         FILE *fp;
        !          1579:         char *ptr;
        !          1580:         static char value[256];
        !          1581:         static char buf[256];
        !          1582: 
        !          1583:         /*
        !          1584:          * 2.0 style?
        !          1585:          */
        !          1586:         if (DOSBase->dl_lib.lib_Version >= 36) {
        !          1587:                 if (GetVar((char *) name, value, 256, 0L) == -1)
        !          1588:                         return NULL;
        !          1589:         }
        !          1590:         else {
        !          1591:                 if (strlen(name) > 252)
        !          1592:                         return NULL;
        !          1593:                 strcpy(buf, "ENV:");
        !          1594:                 strcpy(&buf[4], name);
        !          1595:                 if (!(fp = fopen(buf, "r")))
        !          1596:                         return NULL;
        !          1597:                 for (ptr = value; (*ptr = getc(fp)) != EOF
        !          1598:                      && *ptr != '\n'
        !          1599:                      && ++ptr < &value[256];) ;
        !          1600:                 fclose(fp);
        !          1601:                 *ptr = 0;
        !          1602:         }
        !          1603:         return value;
        !          1604: }
        !          1605: 
        !          1606: 
        !          1607: extern FILE *pgpout;
        !          1608: char *requesterdesc;
        !          1609: 
        !          1610: /*
        !          1611:  * AmigaRequestString() is a trick to make PGP more usable from scripts.
        !          1612:  * The problem is, that most scripts don't allow user interaction over
        !          1613:  * the standard input. The same problem occurs when working in filter mode.
        !          1614:  *
        !          1615:  * This routine will be called by PGP's getstring() whenever user input
        !          1616:  * is requested but the standard input is not interactive. Because the
        !          1617:  * routine can't know what string to ask for, I added the Amiga-specific
        !          1618:  * variable requesterdesc, which holds the last string printed to pgpout
        !          1619:  * before getstring was called.
        !          1620:  *
        !          1621:  * This solution is not pretty, but it works.
        !          1622:  *                                                      Peter Simons
        !          1623:  */
        !          1624: 
        !          1625: int AmigaRequestString(char *buffer, int maxlen, int echo)
        !          1626: {
        !          1627:         struct ReqToolsBase *ReqToolsBase;
        !          1628:         struct TagItem ti[] = {
        !          1629:                 {RTGS_Invisible, FALSE},
        !          1630:                 {RTGS_TextFmt, 0L},
        !          1631:                 {RTGS_Flags, GSREQF_CENTERTEXT},
        !          1632:                 {TAG_DONE, 0L}
        !          1633:         };
        !          1634:         int len = 0;
        !          1635:         char name[64];
        !          1636: 
        !          1637:         if (!maxlen)
        !          1638:                 return 0;
        !          1639:         if (!echo)
        !          1640:                 ti[0].ti_Data = TRUE;
        !          1641:         ti[1].ti_Data = (ULONG) (requesterdesc) ? ((*requesterdesc == '\n') ? requesterdesc+1 : requesterdesc) : "Please enter required string";
        !          1642:                                 /* This one is tricky, too. Because of the format of the
        !          1643:                                  * LANG() module we have a prefacing return before most
        !          1644:                                  * strings, which will make our beautiful requester look
        !          1645:                                  * a bit stupid. This way, we get rid of it. :-)
        !          1646:                                  */
        !          1647:         sprintf(name, "PGPAmiga %s", rel_version);
        !          1648: 
        !          1649:         if (ReqToolsBase = (struct ReqToolsBase *) OpenLibrary(REQTOOLSNAME, 38L))
        !          1650:         {
        !          1651:                 *buffer = '\0';
        !          1652:                 if (rtGetStringA(buffer, maxlen, name, NULL, ti))
        !          1653:                         len = strlen(buffer);
        !          1654:                 CloseLibrary((struct Library *) ReqToolsBase);
        !          1655:         }
        !          1656:         else
        !          1657:         {  fprintf(stderr,"Could not open ReqTools.library!  Try using PGP "
        !          1658:                    "without -f.\n");
        !          1659:            exitPGP(7);   /* Error exit */
        !          1660:         }
        !          1661:         requesterdesc=NULL;   /* Program will re-set it before next getstring() call */
        !          1662:         return len;
        !          1663: }
        !          1664: 
        !          1665: sendpacket(struct MsgPort *rec,LONG action,LONG arg1) 
        !          1666: {
        !          1667:   struct StandardPacket *pkt;
        !          1668:   struct MsgPort *rp;
        !          1669:   LONG res1 = 0L;
        !          1670: 
        !          1671:   if (rp = (struct MsgPort *)CreatePort(NULL,0L)) {
        !          1672:     if (pkt = (struct StandardPacket *)\
        !          1673:         AllocMem(sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR)) {
        !          1674:           pkt->sp_Msg.mn_Node.ln_Name = (BYTE *)&pkt->sp_Pkt;
        !          1675:           pkt->sp_Pkt.dp_Link = &pkt->sp_Msg;
        !          1676:           pkt->sp_Pkt.dp_Port = rp;
        !          1677:           pkt->sp_Pkt.dp_Type = action;
        !          1678:           pkt->sp_Pkt.dp_Arg1 = arg1;
        !          1679:           PutMsg(rec,&pkt->sp_Msg);
        !          1680:           WaitPort(rp);
        !          1681:           GetMsg(rp);
        !          1682:           res1 = pkt->sp_Pkt.dp_Res1;
        !          1683:           FreeMem((UBYTE*)pkt,sizeof(struct StandardPacket));
        !          1684:         }
        !          1685:         DeletePort(rp);
        !          1686:        }
        !          1687:        return(res1);
        !          1688: 
        !          1689: }
        !          1690: 
        !          1691: void ttycbreak(void)
        !          1692: {
        !          1693:   struct MsgPort *ch;
        !          1694: 
        !          1695:   ch = ((struct FileHandle *)BADDR(Input()))->fh_Type;
        !          1696:   sendpacket(ch,ACTION_SCREEN_MODE,-1L);
        !          1697: }
        !          1698: 
        !          1699: void ttynorm(void)
        !          1700: {
        !          1701:   struct MsgPort *ch;
        !          1702: 
        !          1703:   ch = ((struct FileHandle *)BADDR(Input()))->fh_Type;
        !          1704:   sendpacket(ch,ACTION_SCREEN_MODE,0L);
        !          1705: }
        !          1706: 
        !          1707: int getch(void)
        !          1708: {
        !          1709:   char buf;
        !          1710: 
        !          1711:   Read(Input(),&buf,1);
        !          1712:   return((int)buf);
        !          1713: }
        !          1714: 
        !          1715: int kbhit(void)
        !          1716: {
        !          1717:   if(WaitForChar(Input(), 1)) return 1;
        !          1718:   return 0;
        !          1719: }
        !          1720: 
        !          1721: /* GetSysTime problem with WB 1.3 fixed by A. Hartley ([email protected]) */
        !          1722: 
        !          1723: extern struct timerequest *TimerIO;    /* Defined in random.c */
        !          1724: 
        !          1725: void am_GetSysTime(struct timeval *tv)
        !          1726: {
        !          1727:    TimerIO->tr_node.io_Command=TR_GETSYSTIME;
        !          1728:    DoIO((struct IORequest *) TimerIO);
        !          1729:    *tv=TimerIO->tr_time;
        !          1730: }
        !          1731: 
        !          1732: #ifdef __SASC
        !          1733: 
        !          1734: /*
        !          1735:  * SAS/C CTRL-C handler
        !          1736:  */
        !          1737: 
        !          1738: void __regargs _CXBRK(void)
        !          1739: {
        !          1740:   struct MsgPort *ch;
        !          1741: 
        !          1742:   /* it might happen we catch a ^C while in cbreak mode.
        !          1743:    * so always set the screen to the normal mode.
        !          1744:   */
        !          1745: 
        !          1746:   ch = ((struct FileHandle *)BADDR(Input()))->fh_Type;
        !          1747:   sendpacket(ch, ACTION_SCREEN_MODE, 0L);
        !          1748: 
        !          1749: 
        !          1750:   fprintf(pgpout, "\n*** Program Aborted.\n");
        !          1751:   exitPGP(6); /* INTERRUPT */
        !          1752: }
        !          1753: #endif    /* __SASC */
        !          1754: 
        !          1755: #endif /* AMIGA */
        !          1756: 
        !          1757: 
        !          1758: /*===========================================================================*/
        !          1759: /*
        !          1760:  * other stuff for non-MSDOS systems
        !          1761:  */
        !          1762: 
        !          1763: #ifdef ATARI
        !          1764: #ifdef __PUREC__
        !          1765: #include <tos.h>
        !          1766: #else
        !          1767: #include <osbind.h>            /* use GEMDOS functions for I/O */
        !          1768: #endif
        !          1769: 
        !          1770: int kbhit(void)
        !          1771: {
        !          1772:        return Cconis();        /* ret == 0 : no char available */
        !          1773: }
        !          1774: 
        !          1775: int getch(void)
        !          1776: {
        !          1777:        return (Cnecin() & 0x000000FF); /* ASCII-Code in Bits 0..7   */
        !          1778: }                                      /* Scan-Codes in Bits 16..23 */
        !          1779: #endif /* ATARI */
        !          1780: 
        !          1781: #if !defined(MSDOS) && !defined(ATARI)
        !          1782: #include <ctype.h>
        !          1783: #include "charset.h"
        !          1784: char *strlwr(char *s)
        !          1785: {      /*
        !          1786:        **        Turns string s into lower case.
        !          1787:        */
        !          1788:        int c;
        !          1789:        char *p = s;
        !          1790:        while (c = *p)
        !          1791:                *p++ = to_lower(c);
        !          1792:        return(s);
        !          1793: }
        !          1794: #endif /* !MSDOS && !ATARI */
        !          1795: 
        !          1796: 
        !          1797: #ifdef strstr
        !          1798: #undef strstr
        !          1799: /* Not implemented on some systems - return first instance of s2 in s1 */
        !          1800: char *mystrstr (char *s1, char *s2)
        !          1801: {      int i;
        !          1802:        char *strchr();
        !          1803: 
        !          1804:        if (!s2 || !*s2)
        !          1805:                return s1;
        !          1806:        for ( ; ; )
        !          1807:        {       if (!(s1 = strchr (s1, *s2)))
        !          1808:                        return s1;
        !          1809:                for (i=1; s2[i] && (s1[i]==s2[i]); ++i)
        !          1810:                        ;
        !          1811:                if (!s2[i])
        !          1812:                        return s1;
        !          1813:                ++s1;
        !          1814:        }
        !          1815: }
        !          1816: #endif /* strstr */
        !          1817: 
        !          1818: 
        !          1819: #ifdef fopen
        !          1820: #undef fopen
        !          1821: 
        !          1822: #ifdef ATARI
        !          1823: #define F_BUF_SIZE 8192  /* seems to be a good value ... */
        !          1824: 
        !          1825: FILE *myfopen(const char *filename, const char *mode)
        !          1826: /* Open streams with larger buffer to increase disk I/O speed. */
        !          1827: /* Adjust F_BUF_SIZE to change buffer size.                    */
        !          1828: {
        !          1829:     FILE *f;
        !          1830: 
        !          1831:     if ( (f = fopen(filename, mode)) != NULL )
        !          1832:         if (setvbuf(f, NULL, _IOFBF, F_BUF_SIZE)) /* no memory? */
        !          1833:         {
        !          1834:             fclose(f);                 /* then close it again */
        !          1835:             f = fopen(filename, mode); /* and try again in normal mode */
        !          1836:         }
        !          1837:     return(f);                         /* return either handle or NULL */
        !          1838: }
        !          1839:        
        !          1840: #else /* ATARI */
        !          1841: 
        !          1842: /* Remove "b" from 2nd arg */
        !          1843: FILE *myfopen(char *filename, char *type)
        !          1844: {      char buf[10];
        !          1845: 
        !          1846:        buf[0] = *type++;
        !          1847:        if (*type=='b')
        !          1848:                ++type;
        !          1849:        strcpy(buf+1,type);
        !          1850:        return fopen(filename, buf);
        !          1851: }
        !          1852: #endif /* not ATARI */
        !          1853: #endif /* fopen */
        !          1854: 
        !          1855: 
        !          1856: #ifndef MSDOS
        !          1857: #ifdef OS2
        !          1858: 
        !          1859: static int chr = -1;
        !          1860: 
        !          1861: int kbhit(void)
        !          1862: {
        !          1863:        if (chr == -1)
        !          1864:                chr = _read_kbd(0, 0, 0);
        !          1865:        return (chr != -1);
        !          1866: }
        !          1867: 
        !          1868: int getch(void)
        !          1869: {
        !          1870:        int c;
        !          1871: 
        !          1872:        if (chr >= 0) {
        !          1873:                c = chr;
        !          1874:                chr = -1;
        !          1875:        } else
        !          1876:                c = _read_kbd(0, 1, 0);
        !          1877: 
        !          1878:        return c;
        !          1879: }
        !          1880: 
        !          1881: #endif /* OS2 */
        !          1882: #endif /* MSDOS */
        !          1883: 
        !          1884: #ifdef MACTC5  /* 203a */
        !          1885: 
        !          1886: #include "My_console.h"
        !          1887: 
        !          1888: int getch(void) {
        !          1889:        while( !kbhit() );
        !          1890:        return( getc(stdin) );
        !          1891: }
        !          1892: 
        !          1893: int kbhit(void) {
        !          1894:        int kbuf;
        !          1895:        
        !          1896:        csetmode(C_RAW, stdin);
        !          1897:        kbuf = getc(stdin);
        !          1898:        if( kbuf != EOF ) ungetc((kbuf & 0xff), stdin);
        !          1899:        csetmode(C_ECHO, stdin);
        !          1900:        return( (kbuf == EOF) ? 0 : 1 );
        !          1901: }
        !          1902: 
        !          1903: #endif
        !          1904: 
        !          1905: /*EWS Fix -f lockup on passphrase prompts for TURBO C++ */
        !          1906: #if defined(MSDOS) && !defined(__GO32__) && defined(__TURBOC__)
        !          1907: #include <bios.h>
        !          1908: #include <signal.h>
        !          1909: 
        !          1910: #if !defined(_KEYBRD_READY)
        !          1911: #define _KEYBRD_READY 1    /* To support old versions of Turbo C */
        !          1912: #endif
        !          1913: #if !defined(_KEYBRD_READ)
        !          1914: #define _KEYBRD_READ 0     /* To support old versions of Turbo C */
        !          1915: #endif
        !          1916: 
        !          1917: int kbhit(void)
        !          1918: {
        !          1919:   int c;
        !          1920:   c=bioskey(_KEYBRD_READY);
        !          1921:   if (c != 0) c=1;
        !          1922:   return c;
        !          1923: } /*kbhit*/
        !          1924: 
        !          1925: int getch(void)
        !          1926: {
        !          1927:    int c;
        !          1928:    c=bioskey(_KEYBRD_READ);
        !          1929:    if (c==11779) raise(SIGINT);   /* Ctrl-C */
        !          1930:    return c & 0xff;
        !          1931: } /*getch*/
        !          1932: #endif
        !          1933: 
        !          1934: /*EWS Fix -f lockup on passphrase prompts for MSC */
        !          1935: #if defined(MSDOS) && !defined(__GO32__) && defined(_MSC_VER)
        !          1936: #include <bios.h>
        !          1937: #include <signal.h>
        !          1938: #include <dos.h>
        !          1939: 
        !          1940: int getcbrk(void)
        !          1941: {
        !          1942:     union REGS r;
        !          1943: 
        !          1944:     r.x.ax=0x3300;
        !          1945:     intdos(&r, &r);
        !          1946:     return(r.h.dl);
        !          1947: }
        !          1948: 
        !          1949: int setcbrk(int xx)
        !          1950: {
        !          1951:     union REGS r;
        !          1952: 
        !          1953:     r.x.ax=0x3301;
        !          1954:     r.h.dl=xx;
        !          1955:     intdos(&r, &r);
        !          1956:     return(r.h.dl);
        !          1957: }
        !          1958: 
        !          1959: int kbhit(void)
        !          1960: {
        !          1961:     int c;
        !          1962:     c=_bios_keybrd(_KEYBRD_READY);
        !          1963:     if (c != 0) c=1;
        !          1964:     return c;
        !          1965: } /*kbhit*/
        !          1966: 
        !          1967: int getch(void)
        !          1968: {
        !          1969:     int c;
        !          1970:     c=_bios_keybrd(_KEYBRD_READ);
        !          1971:     if (c==11779) raise(SIGINT);   /* Ctrl-C */
        !          1972:     return c & 0xff;
        !          1973: } /*getch*/
        !          1974: #endif
        !          1975:  
        !          1976: #ifdef EBCDIC
        !          1977: static int kbuf = -1;
        !          1978: 
        !          1979: int kbhit(void)
        !          1980: {
        !          1981:    int ch;
        !          1982:    if (kbuf >= 0)
        !          1983:       return 1;
        !          1984:    if (ch = getchar()) {
        !          1985:       kbuf = ch;
        !          1986:       return 1;
        !          1987:    }
        !          1988:    return 0;
        !          1989: }
        !          1990: 
        !          1991: int getch(void)
        !          1992: {
        !          1993:    int ch;
        !          1994:    while (!kbhit());
        !          1995:    ch = kbuf;
        !          1996:    kbuf = -1;
        !          1997:    return ch;
        !          1998: }
        !          1999: 
        !          2000: int c370_rename(char *from, char *to)
        !          2001: {
        !          2002:    return rename(from,to) == 0 ? 0 : -1;
        !          2003: }
        !          2004: #endif /* EBCDIC */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.