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

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

unix.superglobalmegacorp.com

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