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

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

unix.superglobalmegacorp.com

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