Annotation of 43BSDReno/contrib/emacs-18.55/src/sysdep.c, revision 1.1.1.1

1.1       root        1: /* Interfaces to system-dependent kernel and library entries.
                      2:    Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GNU Emacs.
                      5: 
                      6: GNU Emacs is distributed in the hope that it will be useful,
                      7: but WITHOUT ANY WARRANTY.  No author or distributor
                      8: accepts responsibility to anyone for the consequences of using it
                      9: or for whether it serves any particular purpose or works at all,
                     10: unless he says so in writing.  Refer to the GNU Emacs General Public
                     11: License for full details.
                     12: 
                     13: Everyone is granted permission to copy, modify and redistribute
                     14: GNU Emacs, but only under the conditions described in the
                     15: GNU Emacs General Public License.   A copy of this license is
                     16: supposed to have been given to you along with GNU Emacs so you
                     17: can know your rights and responsibilities.  It should be in a
                     18: file named COPYING.  Among other things, the copyright notice
                     19: and this notice must be preserved on all copies.  */
                     20: 
                     21: 
                     22: #include <signal.h>
                     23: #include <setjmp.h>
                     24: 
                     25: #define USE_OLD_TTY
                     26: 
                     27: #include "config.h"
                     28: #include "lisp.h"
                     29: #undef NULL
                     30: 
                     31: #define min(x,y) ((x) > (y) ? (y) : (x))
                     32: 
                     33: /* In this file, open, read and write refer to the system calls,
                     34:    not our sugared interfaces  sys_open, sys_read and sys_write.
                     35:    Contrariwise, for systems where we use the system calls directly,
                     36:    define sys_read, etc. here as aliases for them.  */
                     37: #ifndef read
                     38: #define sys_read read
                     39: #define sys_write write
                     40: #endif /* `read' is not a macro */
                     41: 
                     42: #undef read
                     43: #undef write
                     44: 
                     45: #ifndef close
                     46: #define sys_close close
                     47: #else 
                     48: #undef close
                     49: #endif
                     50: 
                     51: #ifndef open
                     52: #define sys_open open
                     53: #else /* `open' is a macro */
                     54: #undef open
                     55: #endif /* `open' is a macro */
                     56: 
                     57: #include <stdio.h>
                     58: #include <sys/types.h>
                     59: #include <sys/stat.h>
                     60: #include <errno.h>
                     61: 
                     62: extern int errno;
                     63: #ifndef VMS
                     64: extern char *sys_errlist[];
                     65: #endif
                     66: 
                     67: #ifdef VMS
                     68: #include <rms.h>
                     69: #include <ttdef.h>
                     70: #include <tt2def.h>
                     71: #include <iodef.h>
                     72: #include <ssdef.h>
                     73: #include <descrip.h>
                     74: #include <ctype.h>
                     75: #include <file.h>
                     76: #ifndef RAB$C_BID
                     77: #include <rab.h>
                     78: #endif
                     79: #define        MAXIOSIZE ( 32 * PAGESIZE )     /* Don't I/O more than 32 blocks at a time */
                     80: #endif /* VMS */
                     81: 
                     82: #ifndef BSD4_1
                     83: #ifdef BSD /* this is done this way to avoid defined(BSD) || defined (USG)
                     84:              because the vms compiler doesn't grok `defined' */
                     85: #include <fcntl.h>
                     86: #endif
                     87: #ifdef USG
                     88: #include <fcntl.h>
                     89: #endif
                     90: #endif /* not 4.1 bsd */
                     91: 
                     92: #ifdef BSD
                     93: #include <sys/ioctl.h>
                     94: #ifdef BSD4_1
                     95: #include <wait.h>
                     96: #else /* not 4.1 */
                     97: #include <sys/wait.h>
                     98: #endif /* not 4.1 */
                     99: #endif /* BSD */
                    100: 
                    101: #ifdef STRIDE
                    102: #include <sys/ioctl.h>
                    103: #endif 
                    104: 
                    105: #ifdef mips
                    106: #include <sys/ioctl.h>
                    107: #endif 
                    108: 
                    109: /* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs.  */
                    110: #ifdef BSD4_1
                    111: #undef LLITOUT
                    112: #define LLITOUT 0
                    113: #endif /* 4.1 */
                    114: 
                    115: #ifdef HAVE_TERMIO
                    116: #include <termio.h>
                    117: #undef TIOCGETP
                    118: #define TIOCGETP TCGETA
                    119: #undef TIOCSETN
                    120: #define TIOCSETN TCSETAW
                    121: #undef TIOCSETP
                    122: #define TIOCSETP TCSETAF
                    123: #define TERMINAL struct termio
                    124: #define OSPEED(str) (str.c_cflag & CBAUD)
                    125: #define SETOSPEED(str,new) (str.c_cflag = (str.c_cflag & ~CBAUD) | (new))
                    126: #define TABS_OK(str) ((str.c_oflag & TABDLY) != TAB3)
                    127: #endif /* HAVE_TERMIO */
                    128: 
                    129: #ifdef XENIX
                    130: #undef TIOCGETC  /* Avoid confusing some conditionals that test this.  */
                    131: #endif
                    132: 
                    133: #ifndef HAVE_TERMIO
                    134: #ifndef VMS
                    135: #include <sgtty.h>
                    136: #define TERMINAL struct sgttyb
                    137: #define OSPEED(str) str.sg_ospeed
                    138: #define SETOSPEED(str,new) (str.sg_ospeed = (new))
                    139: #define TABS_OK(str) ((str.sg_flags & XTABS) != XTABS)
                    140: #undef TCSETAW
                    141: #define TCSETAW TIOCSETN
                    142: #endif /* not VMS */
                    143: #endif /* not HAVE_TERMIO */
                    144: 
                    145: #ifdef USG
                    146: #include <sys/utsname.h>
                    147: #include <memory.h>
                    148: #include <string.h>
                    149: #ifdef TIOCGWINSZ
                    150: #ifndef IRIS_4D
                    151: #ifndef mips
                    152: /* Some USG systems with TIOCGWINSZ need this file; some don't have it.
                    153:    We don't know how to distinguish them.
                    154:    If this #include gets an error, just delete it.  */
                    155: #include <sys/sioctl.h>
                    156: #endif
                    157: #endif
                    158: #endif
                    159: #ifdef HAVE_TIMEVAL
                    160: #ifdef HPUX
                    161: #include <time.h>
                    162: #else
                    163: #include <sys/time.h>
                    164: #endif
                    165: #endif /* HAVE_TIMEVAL */
                    166: #endif /* USG */
                    167: 
                    168: #ifdef VMS
                    169: #include "window.h"
                    170: #endif
                    171:   
                    172: #ifdef NEED_BSDTTY
                    173: #include <sys/bsdtty.h>
                    174: #endif 
                    175: 
                    176: #include "termhooks.h"
                    177: #include "termchar.h"
                    178: #include "termopts.h"
                    179: #include "dispextern.h"
                    180: 
                    181: #ifdef NONSYSTEM_DIR_LIBRARY
                    182: #include "ndir.h"
                    183: #endif /* NONSYSTEM_DIR_LIBRARY */
                    184: 
                    185: #ifndef sigmask
                    186: #define sigmask(no) (1L << ((no) - 1))
                    187: #endif
                    188: 
                    189: /* Define SIGCHLD as an alias for SIGCLD.  There are many conditionals
                    190:    testing SIGCHLD.  */
                    191: 
                    192: #ifndef VMS
                    193: #ifdef SIGCLD
                    194: #ifndef SIGCHLD
                    195: #define SIGCHLD SIGCLD
                    196: #endif /* not SIGCHLD */
                    197: #endif /* SIGCLD */
                    198: #endif /* not VMS */
                    199: 
                    200: static int baud_convert[] =
                    201: #ifdef BAUD_CONVERT
                    202:   BAUD_CONVERT;
                    203: #else
                    204:   {
                    205:     0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
                    206:     1800, 2400, 4800, 9600, 19200, 38400
                    207:   };
                    208: #endif
                    209: 
                    210: extern short ospeed;
                    211: 
                    212: #ifdef VMS
                    213: static struct iosb
                    214: {
                    215:   short status;
                    216:   short offset;
                    217:   short termlen;
                    218:   short term;
                    219: } input_iosb;
                    220: 
                    221: int kbd_input_ast ();
                    222: 
                    223: int waiting_for_ast;
                    224: int stop_input;
                    225: int input_ef = 0;
                    226: int timer_ef = 0;
                    227: int process_ef = 0;
                    228: int input_eflist;
                    229: int timer_eflist;
                    230: 
                    231: static int input_chan;
                    232: static $DESCRIPTOR (input_dsc, "TT");
                    233: static int terminator_mask[2] = { 0, 0 };
                    234: 
                    235: static struct sensemode {
                    236:   short status;
                    237:   unsigned char xmit_baud;
                    238:   unsigned char rcv_baud;
                    239:   unsigned char crfill;
                    240:   unsigned char lffill;
                    241:   unsigned char parity;
                    242:   unsigned char unused;
                    243:   char class;
                    244:   char type;
                    245:   short scr_wid;
                    246:   unsigned long tt_char : 24, scr_len : 8;
                    247:   unsigned long tt2_char;
                    248: } sensemode_iosb;
                    249: #define TERMINAL struct sensemode
                    250: #define OSPEED(str) (str.xmit_baud)
                    251: #define TABS_OK(str) ((str.tt_char & TT$M_MECHTAB) != 0)
                    252: #endif /* VMS */
                    253: 
                    254: discard_tty_input ()
                    255: {
                    256:   TERMINAL buf;
                    257: 
                    258:   if (noninteractive)
                    259:     return;
                    260: 
                    261: #ifdef VMS
                    262:   end_kbd_input ();
                    263:   SYS$QIOW (0, input_chan, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
                    264:            &buf, 0, 0, terminator_mask, 0, 0);
                    265:   queue_kbd_input ();
                    266: #else /* not VMS */
                    267:   ioctl (0, TIOCGETP, &buf);
                    268:   ioctl (0, TIOCSETP, &buf);
                    269: #endif /* not VMS */
                    270: }
                    271: 
                    272: #ifdef SIGTSTP
                    273: 
                    274: stuff_char (c)
                    275:      char c;
                    276: {
                    277: /* Should perhaps error if in batch mode */
                    278: #ifdef TIOCSTI
                    279:   ioctl (0, TIOCSTI, &c);
                    280: #else /* no TIOCSTI */
                    281:   error ("Cannot stuff terminal input characters in this version of Unix.");
                    282: #endif /* no TIOCSTI */
                    283: }
                    284: 
                    285: #endif /* SIGTSTP */
                    286: 
                    287: init_baud_rate ()
                    288: {
                    289:   TERMINAL sg;
                    290: 
                    291:   if (noninteractive)
                    292:     ospeed = 0;
                    293:   else
                    294:     {
                    295: #ifdef VMS
                    296:       SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
                    297:                &sg.class, 12, 0, 0, 0, 0 );
                    298: #else
                    299:       SETOSPEED (sg, B9600);
                    300:       ioctl (0, TIOCGETP, &sg);
                    301: #endif /* not VMS */
                    302:       ospeed = OSPEED (sg);
                    303:     }
                    304:   baud_rate = ospeed == 0 ? 1200
                    305:     : ospeed < sizeof baud_convert / sizeof baud_convert[0]
                    306:       ? baud_convert[ospeed] : 9600;
                    307: }
                    308: 
                    309: /*ARGSUSED*/
                    310: set_exclusive_use (fd)
                    311:      int fd;
                    312: {
                    313: #ifdef FIOCLEX
                    314:   ioctl (fd, FIOCLEX, 0);
                    315: #endif
                    316:   /* Ok to do nothing if this feature does not exist */
                    317: }
                    318: 
                    319: #ifndef subprocesses
                    320: 
                    321: wait_without_blocking ()
                    322: {
                    323: #ifdef BSD
                    324:   wait3 (0, WNOHANG | WUNTRACED, 0);
                    325: #else
                    326:   croak ("wait_without_blocking");
                    327: #endif
                    328: }
                    329: 
                    330: #endif /* not subprocesses */
                    331: 
                    332: int wait_debugging;   /* Set nonzero to make following function work under dbx
                    333:                         (at least for bsd).  */
                    334: 
                    335: /* Wait for subprocess with process id `pid' to terminate and
                    336:    make sure it will get eliminated (not remain forever as a zombie) */
                    337: 
                    338: wait_for_termination (pid)
                    339:      int pid;
                    340: {
                    341:   while (1)
                    342:     {
                    343: #ifdef subprocesses
                    344: #if defined(BSD) || (defined(HPUX) && !defined(HPUX_5))
                    345:       /* Note that kill returns -1 even if the process is just a zombie now.
                    346:         But inevitably a SIGCHLD interrupt should be generated
                    347:         and child_sig will do wait3 and make the process go away. */
                    348:       /* There is some indication that there is a bug involved with
                    349:         termination of subprocesses, perhaps involving a kernel bug too,
                    350:         but no idea what it is.  Just as a hunch we signal SIGCHLD to see
                    351:         if that causes the problem to go away or get worse.  */
                    352: #ifdef BSD4_1
                    353:       extern int synch_process_pid;
                    354:       sighold (SIGCHLD);
                    355:       if (synch_process_pid == 0)
                    356:        {
                    357:           sigrelse (SIGCHLD);
                    358:          break;
                    359:        }
                    360:       if (wait_debugging)
                    361:        sleep (1);
                    362:       else
                    363:        sigpause (SIGCHLD);
                    364: #else /* not BSD4_1 */
                    365:       sigsetmask (1 << (SIGCHLD - 1));
                    366:       if (0 > kill (pid, 0))
                    367:         {
                    368:          sigsetmask (0);
                    369:          kill (getpid (), SIGCHLD);
                    370:          break;
                    371:        }
                    372:       if (wait_debugging)
                    373:        sleep (1);
                    374:       else
                    375:        sigpause (0);
                    376: #endif /* not BSD4_1 */
                    377: #else /* not BSD, and not HPUX version >= 6 */
                    378: #ifdef UNIPLUS
                    379:       if (0 > kill (pid, 0))
                    380:        break;
                    381:       wait (0);
                    382: #else /* neither BSD nor UNIPLUS: random sysV */
                    383:       if (0 > kill (pid, 0))
                    384:        break;
                    385:       pause ();
                    386: #endif /* not UNIPLUS */
                    387: #endif /* not BSD, and not HPUX version >= 6 */
                    388: #else /* not subprocesses */
                    389: #ifndef BSD4_1
                    390:       if (0 > kill (pid, 0))
                    391:        break;
                    392:       wait (0);
                    393: #else /* BSD4_1 */
                    394:       int status;
                    395:       status = wait (0);
                    396:       if (status == pid || status == -1)
                    397:        break;
                    398: #endif /* BSD4_1 */
                    399: #endif /* not subprocesses */
                    400:     }
                    401: }
                    402: 
                    403: #ifdef subprocesses
                    404: 
                    405: /*
                    406:  *     flush any pending output
                    407:  *      (may flush input as well; it does not matter the way we use it)
                    408:  */
                    409:  
                    410: flush_pending_output (channel)
                    411:      int channel;
                    412: {
                    413: #ifdef TCFLSH
                    414:   ioctl (channel, TCFLSH, 1);
                    415: #else
                    416: #ifdef TIOCFLUSH
                    417:   int zero = 0;
                    418:   /* 3rd arg should be ignored
                    419:      but some 4.2 kernels actually want the address of an int
                    420:      and nonzero means something different.  */
                    421:   ioctl (channel, TIOCFLUSH, &zero);
                    422: #endif
                    423: #endif
                    424: }
                    425: 
                    426: /*  Set up the terminal at the other end of a pseudo-terminal that
                    427:     we will be controlling an inferior through.
                    428:     It should not echo or do line-editing, since that is done
                    429:     in Emacs.  No padding needed for insertion into an Emacs buffer.  */
                    430: 
                    431: child_setup_tty (out)
                    432:      int out;
                    433: {
                    434:   TERMINAL s;
                    435: 
                    436:   ioctl (out, TIOCGETP, &s);
                    437: #ifdef HAVE_TERMIO
                    438:   s.c_oflag |= OPOST;          /* Enable output postprocessing */
                    439:   s.c_oflag &= ~ONLCR;         /* Disable map of NL to CR-NL on output */
                    440:   s.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);        /* No output delays */
                    441:   s.c_lflag &= ~ECHO;          /* Disable echo */
                    442:   s.c_lflag |= ISIG;           /* Enable signals */
                    443:   s.c_iflag &= ~IUCLC;         /* Disable map of upper case to lower on input */
                    444:   s.c_oflag &= ~OLCUC;         /* Disable map of lower case to upper on output */
                    445: /* said to be unnecesary
                    446:   s.c_cc[VMIN] = 1;            /* minimum number of characters to accept
                    447:   s.c_cc[VTIME] = 0;           /* wait forever for at least 1 character
                    448: */
                    449:   s.c_lflag |= ICANON;         /* Enable erase/kill and eof processing */
                    450:   s.c_cc[VEOF] = 04;           /* insure that EOF is Control-D */
                    451:   s.c_cc[VERASE] = 0377;       /* disable erase processing */
                    452:   s.c_cc[VKILL] = 0377;                /* disable kill processing */
                    453: #ifdef HPUX
                    454:   s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
                    455: #endif HPUX
                    456: #ifdef IBMRTAIX
                    457: /* AIX enhanced edit loses NULs, so disable it */
                    458:   s.c_line = 0;
                    459:   s.c_iflag &= ~ASCEDIT;
                    460:   /* Also, PTY overloads NUL and BREAK.
                    461:      don't ignore break, but don't signal either, so it looks like NUL.  */
                    462:   s.c_iflag &= ~IGNBRK;
                    463:   s.c_iflag &= ~BRKINT;
                    464: /* QUIT and INTR work better as signals, so disable character forms */
                    465:   s.c_cc[VQUIT] = 0377;
                    466:   s.c_cc[VINTR] = 0377;
                    467:   s.c_cc[VEOL] = 0377;
                    468:   s.c_lflag &= ~ISIG;
                    469:   s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
                    470: #endif /* IBMRTAIX */
                    471: 
                    472: #else /* not HAVE_TERMIO */
                    473:   s.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);
                    474: #endif /* not HAVE_TERMIO */
                    475: 
                    476:   ioctl (out, TIOCSETN, &s);
                    477: 
                    478: #ifdef BSD4_1
                    479:   if (interrupt_input)
                    480:     reset_sigio ();
                    481: #endif /* BSD4_1 */
                    482: #ifdef RTU
                    483:   {
                    484:     int zero = 0;
                    485:     ioctl (out, FIOASYNC, &zero);
                    486:   }
                    487: #endif /* RTU */
                    488: }
                    489: 
                    490: #endif /* subprocesses */
                    491: 
                    492: /*ARGSUSED*/
                    493: setpgrp_of_tty (pid)
                    494:      int pid;
                    495: {
                    496: #ifdef TIOCSPGRP
                    497:   ioctl (0, TIOCSPGRP, &pid);
                    498: #else
                    499:   /* Just ignore this for now and hope for the best */
                    500: #endif
                    501: }
                    502: 
                    503: /* Suspend the Emacs process; give terminal to its superior.  */
                    504: 
                    505: sys_suspend ()
                    506: {
                    507: #ifdef VMS
                    508:   unsigned long parent_id;
                    509: 
                    510:   parent_id = getppid ();
                    511:   if (parent_id && parent_id != 0xffffffff)
                    512:     {
                    513:       int oldsig = signal (SIGINT, SIG_IGN);
                    514:       int status = LIB$ATTACH (&parent_id) & 1;
                    515:       signal (SIGINT, oldsig);
                    516:       return status;
                    517:     }
                    518:   return -1;
                    519: #else
                    520: #ifdef SIGTSTP
                    521: #ifdef BSD
                    522:   killpg (getpgrp (0), SIGTSTP);
                    523: #else
                    524:   kill (-getpgrp (0), SIGTSTP);
                    525: #endif
                    526: 
                    527: #else
                    528: #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
                    529:   ptrace (0, 0, 0, 0);         /* set for ptrace - caught by csh */
                    530:   kill (getpid (), SIGQUIT);
                    531: 
                    532: #else
                    533: 
                    534: /* On a system where suspending is not implemented,
                    535:    instead fork a subshell and let it talk directly to the terminal
                    536:    while we wait.  */
                    537:   int pid = fork ();
                    538:   int (*interrupt) ();
                    539:   int (*quit) ();
                    540:   int (*term) ();
                    541: #ifdef SIGIO
                    542:   int (*sigio) ();
                    543: #endif SIGIO
                    544: 
                    545:   if (pid == -1)
                    546:     error ("Can't spawn subshell");
                    547:   if (pid == 0)
                    548:     {
                    549:       char *sh;
                    550: 
                    551:       sh = (char *) egetenv ("SHELL");
                    552:       if (sh == 0)
                    553:        sh = "sh";
                    554:       /* Use our buffer's default directory for the subshell.  */
                    555:       {
                    556:        Lisp_Object dir;
                    557:        unsigned char *str;
                    558:        int len;
                    559: 
                    560:        /* mentioning bf_cur->buffer would mean including buffer.h,
                    561:           which somehow wedges the hp compiler.  So instead... */
                    562: 
                    563:        dir = intern ("default-directory");
                    564:        /* Can't use NULL */
                    565:        if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
                    566:          goto xyzzy;
                    567:        dir = Fsymbol_value (dir);
                    568:        if (XTYPE (dir) != Lisp_String)
                    569:          goto xyzzy;
                    570: 
                    571:        str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
                    572:        len = XSTRING (dir)->size;
                    573:        bcopy (XSTRING (dir)->data, str, len);
                    574:        if (str[len - 1] != '/') str[len++] = '/';
                    575:        str[len] = 0;
                    576:        chdir (str);
                    577:       }
                    578:     xyzzy:
                    579: #ifdef subprocesses
                    580:       close_process_descs ();  /* Close Emacs's pipes/ptys */
                    581: #endif
                    582:       execlp (sh, sh, 0);
                    583:       write (1, "Can't execute subshell", 22);
                    584:       _exit (1);
                    585:     }
                    586:   interrupt = (int (*)()) signal (SIGINT, SIG_IGN);
                    587:   quit = (int (*)()) signal (SIGQUIT, SIG_IGN);
                    588:   term = (int (*)()) signal (SIGTERM, SIG_IGN);
                    589: #ifdef SIGIO
                    590:   sigio = (int (*)()) signal (SIGIO, SIG_IGN);
                    591: #endif /* SIGIO */
                    592:   wait_for_termination (pid);
                    593:   signal (SIGINT, interrupt);
                    594:   signal (SIGQUIT, quit);
                    595:   signal (SIGTERM, term);
                    596: #ifdef SIGIO
                    597:   signal (SIGIO, sigio);
                    598: #endif /* SIGIO */
                    599: #endif /* no USG_JOBCTRL */
                    600: #endif /* no SIGTSTP */
                    601: #endif /* not VMS */
                    602: }
                    603: 
                    604: #ifdef F_SETFL
                    605: 
                    606: int old_fcntl_flags;
                    607: 
                    608: init_sigio ()
                    609: {
                    610: #ifdef FASYNC
                    611:   old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
                    612: #endif
                    613:   request_sigio ();
                    614: }
                    615: 
                    616: reset_sigio ()
                    617: {
                    618:   unrequest_sigio ();
                    619: }
                    620: 
                    621: #ifdef FASYNC          /* F_SETFL does not imply existance of FASYNC */
                    622: 
                    623: request_sigio ()
                    624: {
                    625: #ifdef SIGWINCH
                    626:   int omask = sigblock (0);
                    627:   sigsetmask (omask & ~sigmask (SIGWINCH));
                    628: #endif
                    629:   fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
                    630: 
                    631:   interrupts_deferred = 0;
                    632: }
                    633: 
                    634: unrequest_sigio ()
                    635: {
                    636: #ifdef SIGWINCH
                    637:   sigblock (sigmask (SIGWINCH));
                    638: #endif
                    639:   fcntl (0, F_SETFL, old_fcntl_flags);
                    640:   interrupts_deferred = 1;
                    641: }
                    642: 
                    643: #else /* no FASYNC */
                    644: #ifdef STRIDE          /* Stride doesn't have FASYNC - use FIOASYNC */
                    645: 
                    646: request_sigio ()
                    647: {
                    648:   int on = 1;
                    649:   ioctl (0, FIOASYNC, &on);
                    650:   interrupts_deferred = 0;
                    651: }
                    652: 
                    653: unrequest_sigio ()
                    654: {
                    655:   int off = 0;
                    656: 
                    657:   ioctl (0, FIOASYNC, &off);
                    658:   interrupts_deferred = 1;
                    659: }
                    660: 
                    661: #else /* not FASYNC, not STRIDE */
                    662:  
                    663: request_sigio ()
                    664: {
                    665:   croak ("request_sigio");
                    666: }
                    667:  
                    668: unrequest_sigio ()
                    669: {
                    670:   croak ("unrequest_sigio");
                    671: }
                    672:  
                    673: #endif /* STRIDE */
                    674: #endif /* FASYNC */
                    675: #endif /* F_SETFL */
                    676: 
                    677: TERMINAL old_gtty;             /* The initial tty mode bits */
                    678: 
                    679: int term_initted;              /* 1 if outer tty status has been recorded */
                    680: 
                    681: #ifdef F_SETOWN
                    682: int old_fcntl_owner;
                    683: #endif /* F_SETOWN */
                    684: 
                    685: #ifdef TIOCGLTC
                    686: struct ltchars old_ltchars;
                    687: #endif /* TIOCGLTC */
                    688: 
                    689: #ifdef TIOCGETC
                    690: struct tchars old_tchars;
                    691: int old_lmode;
                    692: 
                    693: int lmode;                     /* Current lmode value. */
                    694:                                /* Needed as global for 4.1 */
                    695: #endif /* TIOCGETC */
                    696: 
                    697: /* This may also be defined in stdio,
                    698:    but if so, this does no harm,
                    699:    and using the same name avoids wasting the other one's space.  */
                    700: 
                    701: #ifdef USG
                    702: unsigned char _sobuf[BUFSIZ+8];
                    703: #else
                    704: char _sobuf[BUFSIZ];
                    705: #endif
                    706:  
                    707: #ifdef TIOCGLTC
                    708: static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
                    709: #endif
                    710: #ifdef TIOCGETC
                    711:   static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
                    712: #endif 
                    713: 
                    714: init_sys_modes ()
                    715: {
                    716:   TERMINAL sg;
                    717: #ifdef TIOCGETC
                    718:   struct tchars tchars;
                    719: #endif
                    720: #ifdef VMS
                    721: #if 0
                    722:   static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
                    723:   extern int (*interrupt_signal) ();
                    724: #endif
                    725: #endif
                    726: 
                    727:   if (noninteractive)
                    728:     return;
                    729: 
                    730: #ifdef VMS
                    731:   if (!input_ef)
                    732:     LIB$GET_EF (&input_ef);
                    733:   SYS$CLREF (input_ef);
                    734:   waiting_for_ast = 0;
                    735:   if (!timer_ef)
                    736:     LIB$GET_EF (&timer_ef);
                    737:   SYS$CLREF (timer_ef);
                    738:   if (!process_ef)
                    739:     LIB$GET_EF (&process_ef);
                    740:   SYS$CLREF (process_ef);
                    741:   if (input_ef / 32 != process_ef / 32)
                    742:     croak ("Input and process event flags in different clusters.");
                    743:   if (input_ef / 32 != timer_ef / 32)
                    744:     croak ("Input and process event flags in different clusters.");
                    745:   input_eflist = ((unsigned) 1 << (input_ef % 32)) |
                    746:     ((unsigned) 1 << (process_ef % 32));
                    747:   timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
                    748:     ((unsigned) 1 << (timer_ef % 32));
                    749:   SYS$QIOW (0, input_chan, IO$_SENSEMODE, &old_gtty, 0, 0,
                    750:            &old_gtty.class, 12, 0, 0, 0, 0);
                    751: #ifndef VMS4_4
                    752:   sys_access_reinit ();
                    753: #endif
                    754: #else /* not VMS */
                    755:   ioctl (0, TIOCGETP, &old_gtty);
                    756: #endif /* not VMS */
                    757:   if (!read_socket_hook)
                    758:     {
                    759:       sg = old_gtty;
                    760: 
                    761: #ifdef HAVE_TERMIO
                    762:       sg.c_iflag |= (IGNBRK);  /* Ignore break condition */
                    763:       sg.c_iflag &= ~ICRNL;    /* Disable map of CR to NL on input */
                    764: #ifdef ISTRIP
                    765:       sg.c_iflag &= ~ISTRIP;   /* don't strip 8th bit on input */
                    766: #endif
                    767:       sg.c_lflag &= ~ECHO;     /* Disable echo */
                    768:       sg.c_lflag &= ~ICANON;   /* Disable erase/kill processing */
                    769:       sg.c_lflag |= ISIG;      /* Enable signals */
                    770:       if (flow_control)
                    771:        {
                    772:          sg.c_iflag |= IXON;   /* Enable start/stop output control */
                    773: #ifdef IXANY
                    774:          sg.c_iflag &= ~IXANY;
                    775: #endif /* IXANY */
                    776:        }
                    777:       else
                    778:        sg.c_iflag &= ~IXON;    /* Disable start/stop output control */
                    779:       sg.c_oflag &= ~ONLCR;    /* Disable map of NL to CR-NL on output */
                    780:       sg.c_oflag &= ~TAB3;     /* Disable tab expansion */
                    781: #ifdef CS8
                    782:       sg.c_cflag |= CS8;       /* allow 8th bit on input */
                    783:       sg.c_cflag &= ~PARENB;   /* Don't check parity */
                    784: #endif
                    785:       sg.c_cc[VINTR] = '\007'; /* ^G gives SIGINT */
                    786:       /* Set up C-g for both SIGQUIT and SIGINT.
                    787:         We don't know which we will get, but we handle both alike
                    788:         so which one it really gives us does not matter.  */
                    789:       sg.c_cc[VQUIT] = '\007';
                    790:       sg.c_cc[VMIN] = 1;       /* Input should wait for at least 1 char */
                    791:       sg.c_cc[VTIME] = 0;      /* no matter how long that takes.  */
                    792: #ifdef VSWTCH
                    793:       sg.c_cc[VSWTCH] = CDEL;  /* Turn off shell layering use of C-z */
                    794: #endif /* VSWTCH */
                    795: #ifdef IBMRTAIX
                    796:       /* AIX enhanced edit loses NULs, so disable it */
                    797:       sg.c_line = 0;
                    798:       sg.c_iflag &= ~ASCEDIT;
                    799:       /* Also, PTY overloads NUL and BREAK.
                    800:         don't ignore break, but don't signal either, so it looks like NUL.
                    801:         This really serves a purpose only if running in an XTERM window
                    802:         or via TELNET or the like, but does no harm elsewhere.  */
                    803:       sg.c_iflag &= ~IGNBRK;
                    804:       sg.c_iflag &= ~BRKINT;
                    805: #endif
                    806: #else /* if not HAVE_TERMIO */
                    807: #ifdef VMS
                    808:       sg.tt_char |= TT$M_NOECHO | TT$M_EIGHTBIT;
                    809:       if (flow_control)
                    810:        sg.tt_char |= TT$M_TTSYNC;
                    811:       else
                    812:        sg.tt_char &= ~TT$M_TTSYNC;
                    813:       sg.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
                    814: #else /* not VMS (BSD, that is) */
                    815:       sg.sg_flags &= ~(ECHO | CRMOD | XTABS);
                    816:       sg.sg_flags |= ANYP;
                    817:       sg.sg_flags |= interrupt_input ? RAW : CBREAK;
                    818: #endif /* not VMS (BSD, that is) */
                    819: #endif /* not HAVE_TERMIO */
                    820: 
                    821: #ifdef VMS
                    822:       SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
                    823:                &sg.class, 12, 0, 0, 0, 0);
                    824: #else
                    825:       ioctl (0, TIOCSETN, &sg);
                    826: #endif /* not VMS */
                    827: 
                    828:       /* This code added to insure that, if flow-control is not to be used,
                    829:         we have an unlocked screen at the start. */
                    830: #ifdef TCXONC
                    831:       if (!flow_control) ioctl (0, TCXONC, 1);
                    832: #endif
                    833: #ifdef TIOCSTART
                    834:       if (!flow_control) ioctl (0, TIOCSTART, 0);
                    835: #endif
                    836: 
                    837: #ifdef AIX
                    838:       hft_init ();
                    839: #endif
                    840: 
                    841: #ifdef F_SETFL
                    842: #ifdef F_GETOWN                /* F_SETFL does not imply existance of F_GETOWN */
                    843:       if (interrupt_input)
                    844:        {
                    845:          old_fcntl_owner = fcntl (0, F_GETOWN, 0);
                    846:          fcntl (0, F_SETOWN, getpid ());
                    847:          init_sigio ();
                    848:        }
                    849: #endif /* F_GETOWN */
                    850: #endif /* F_SETFL */
                    851: 
                    852:       /* If going to use CBREAK mode, we must request C-g to interrupt
                    853:           and turn off start and stop chars, etc.
                    854:           If not going to use CBREAK mode, do this anyway
                    855:           so as to turn off local flow control for user coming over
                    856:           network on 4.2; in this case, only t_stopc and t_startc really matter.  */
                    857: #ifdef TIOCGLTC
                    858:       ioctl (0, TIOCGLTC, &old_ltchars);
                    859: #endif /* TIOCGLTC */
                    860: #ifndef HAVE_TERMIO
                    861: #ifdef TIOCGETC
                    862:       ioctl (0, TIOCGETC, &old_tchars);
                    863:       ioctl (0, TIOCLGET, &old_lmode);
                    864: 
                    865:       /* Note: if not using CBREAK mode, it makes no difference how we set this */
                    866:       tchars = new_tchars;
                    867:       tchars.t_intrc = 07;
                    868:       if (flow_control)
                    869:        {
                    870:          tchars.t_startc = '\021';
                    871:          tchars.t_stopc = '\023';
                    872:        }
                    873: /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
                    874: #ifndef LPASS8
                    875: #define LPASS8 0
                    876: #endif
                    877: 
                    878: #ifdef BSD4_1
                    879: #define LNOFLSH 0100000
                    880: #endif
                    881: 
                    882:       lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_lmode;
                    883: 
                    884:       ioctl (0, TIOCSETC, &tchars);
                    885:       ioctl (0, TIOCLSET, &lmode);
                    886: #endif /* TIOCGETC */
                    887: #endif /* not HAVE_TERMIO */
                    888: #ifdef TIOCGLTC
                    889:       ioctl (0, TIOCSLTC, &new_ltchars);
                    890: #endif /* TIOCGLTC */
                    891: 
                    892: #ifdef BSD4_1
                    893:       if (interrupt_input)
                    894:        init_sigio ();
                    895: #endif
                    896: #ifdef VMS
                    897: /*  Appears to do nothing when in PASTHRU mode.
                    898:       SYS$QIOW (0, input_chan, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
                    899:                interrupt_signal, oob_chars, 0, 0, 0, 0);
                    900: */
                    901:       queue_kbd_input (0);
                    902: #endif /* VMS */
                    903:     }
                    904: #ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
                    905: #undef _IOFBF
                    906: #endif
                    907: #ifdef _IOFBF
                    908:   /* This symbol is defined on recent USG systems.
                    909:      Someone says without this call USG won't really buffer the file
                    910:      even with a call to setbuf(). */
                    911:   setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
                    912: #else
                    913:   setbuf (stdout, _sobuf);
                    914: #endif
                    915:   set_terminal_modes ();
                    916:   if (term_initted && no_redraw_on_reenter)
                    917:     {
                    918:       if (display_completed)
                    919:        direct_output_forward_char (0);
                    920:     }
                    921:   else
                    922:     screen_garbaged = 1;
                    923:   term_initted = 1;
                    924: }
                    925: 
                    926: /* Return nonzero if safe to use tabs in output.
                    927:    At the time this is called, init_sys_modes has not been done yet.  */
                    928:    
                    929: tabs_safe_p ()
                    930: {
                    931:   TERMINAL sg;
                    932:   if (noninteractive)
                    933:     return 1;
                    934: #ifdef VMS
                    935:   SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
                    936:            &sg.class, 12, 0, 0, 0, 0);
                    937: #else
                    938:   ioctl (0, TIOCGETP, &sg);
                    939: #endif /* not VMS */
                    940:   return (TABS_OK(sg));
                    941: }
                    942: 
                    943: /* Get terminal size from system.
                    944:    Store number of lines into *heightp and width into *widthp.
                    945:    If zero or a negative number is stored, the value is not valid.  */
                    946: 
                    947: get_screen_size (widthp, heightp)
                    948:      int *widthp, *heightp;
                    949: {
                    950: /* Define the 4.3 names in terms of the Sun names
                    951:    if the latter exist and the former do not.  */
                    952: #ifdef TIOCGSIZE
                    953: #ifndef TIOCGWINSZ
                    954: #define TIOCGWINSZ TIOCGSIZE
                    955: #define winsize ttysize
                    956: #define ws_row ts_lines
                    957: #define ws_col ts_cols
                    958: #endif
                    959: #endif /* Sun */
                    960: 
                    961: /* Do it using the 4.3 names if possible.  */
                    962: #ifdef TIOCGWINSZ
                    963:   struct winsize size;
                    964:   *widthp = 0;
                    965:   *heightp = 0;
                    966:   if (ioctl (0, TIOCGWINSZ, &size) < 0)
                    967:     return;
                    968:   if ((unsigned) size.ws_col > MScreenWidth
                    969:       || (unsigned) size.ws_row > MScreenLength)
                    970:     return;
                    971:   *widthp = size.ws_col;
                    972:   *heightp = size.ws_row;
                    973: #else /* not TIOCGWNSIZ */
                    974: #ifdef VMS
                    975:   TERMINAL sg;
                    976:   SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
                    977:            &sg.class, 12, 0, 0, 0, 0);
                    978:   *widthp = sg.scr_wid;
                    979:   *heightp = sg.scr_len;
                    980: #else /* system doesn't know size */
                    981:   *widthp = 0;
                    982:   *heightp = 0;
                    983: #endif /* system does not know size */
                    984: #endif /* not TIOCGWINSZ */
                    985: }
                    986: 
                    987: reset_sys_modes ()
                    988: {
                    989:   if (noninteractive)
                    990:     {
                    991:       fflush (stdout);
                    992:       return;
                    993:     }
                    994:   if (!term_initted)
                    995:     return;
                    996:   if (read_socket_hook)
                    997:     return;
                    998:   topos (screen_height - 1, 0);
                    999:   clear_end_of_line (screen_width);
                   1000:   /* clear_end_of_line may move the cursor */
                   1001:   topos (screen_height - 1, 0);
                   1002:   /* Output raw CR so kernel can track the cursor hpos.  */
                   1003:   cmputc ('\r');
                   1004:   reset_terminal_modes ();
                   1005:   fflush (stdout);
                   1006: #ifdef BSD
                   1007: #ifndef BSD4_1
                   1008:   /* Avoid possible loss of output when changing terminal modes.  */
                   1009:   fsync (fileno (stdout));
                   1010: #endif
                   1011: #endif
                   1012: #ifdef TIOCGLTC
                   1013:   ioctl (0, TIOCSLTC, &old_ltchars);
                   1014: #endif /* TIOCGLTC */
                   1015: #ifndef HAVE_TERMIO
                   1016: #ifdef TIOCGETC
                   1017:   ioctl (0, TIOCSETC, &old_tchars);
                   1018:   ioctl (0, TIOCLSET, &old_lmode);
                   1019: #endif /* TIOCGETC */
                   1020: #endif /* not HAVE_TERMIO */
                   1021: #ifdef F_SETFL
                   1022: #ifdef F_SETOWN                /* F_SETFL does not imply existance of F_SETOWN */
                   1023:   if (interrupt_input)
                   1024:     {
                   1025:       reset_sigio ();
                   1026:       fcntl (0, F_SETOWN, old_fcntl_owner);
                   1027:     }
                   1028: #endif /* F_SETOWN */
                   1029: #endif /* F_SETFL */
                   1030: #ifdef BSD4_1
                   1031:   if (interrupt_input)
                   1032:     reset_sigio ();
                   1033: #endif /* BSD4_1 */
                   1034: #ifdef VMS
                   1035:   end_kbd_input ();
                   1036:   SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
                   1037:            &old_gtty.class, 12, 0, 0, 0, 0);
                   1038: #else /* not VMS */
                   1039:   while (ioctl (0, TCSETAW, &old_gtty) < 0 && errno == EINTR);
                   1040: #endif /* not VMS */
                   1041: 
                   1042: #ifdef AIX
                   1043:   hft_reset ();
                   1044: #endif
                   1045: }
                   1046: 
                   1047: #ifdef VMS
                   1048: 
                   1049: /* Assigning an input channel is done at the start of Emacs execution.
                   1050:    This is called each time Emacs is resumed, also, but does nothing
                   1051:    because input_chain is no longer zero.  */
                   1052: 
                   1053: init_vms_input()
                   1054: {
                   1055:   int status;
                   1056:   
                   1057:   if (input_chan == 0)
                   1058:     {
                   1059:       status = SYS$ASSIGN (&input_dsc, &input_chan, 0, 0);
                   1060:       if (! (status & 1))
                   1061:        LIB$STOP (status);
                   1062:     }
                   1063: }
                   1064: 
                   1065: /* Deassigning the input channel is done before exiting.  */
                   1066: 
                   1067: stop_vms_input ()
                   1068: {
                   1069:   return SYS$DASSGN (input_chan);
                   1070: }
                   1071: 
                   1072: short input_buffer;
                   1073: 
                   1074: /* Request reading one character into the keyboard buffer.
                   1075:    This is done as soon as the buffer becomes empty.  */
                   1076: 
                   1077: queue_kbd_input ()
                   1078: {
                   1079:   int status;
                   1080:   waiting_for_ast = 0;
                   1081:   stop_input = 0;
                   1082:   status = SYS$QIO (0, input_chan, IO$_READVBLK,
                   1083:                    &input_iosb, kbd_input_ast, 1,
                   1084:                    &input_buffer, 1, 0, terminator_mask, 0, 0);
                   1085: }
                   1086: 
                   1087: int input_count;
                   1088: 
                   1089: /* Ast routine that is called when keyboard input comes in
                   1090:    in accord with the SYS$QIO above.  */
                   1091: 
                   1092: kbd_input_ast ()
                   1093: {
                   1094:   register int c = -1;
                   1095:   int old_errno = errno;
                   1096: 
                   1097:   if (waiting_for_ast)
                   1098:     SYS$SETEF (input_ef);
                   1099:   waiting_for_ast = 0;
                   1100:   input_count++;
                   1101: #ifdef ASTDEBUG
                   1102:   if (input_count == 25)
                   1103:     exit (1);
                   1104:   printf ("Ast # %d,", input_count);
                   1105:   printf (" iosb = %x, %x, %x, %x",
                   1106:          input_iosb.offset, input_iosb.status, input_iosb.termlen,
                   1107:          input_iosb.term);
                   1108: #endif
                   1109:   if (input_iosb.offset)
                   1110:     {
                   1111:       c = input_buffer;
                   1112: #ifdef ASTDEBUG
                   1113:       printf (", char = 0%o", c);
                   1114: #endif
                   1115:     }
                   1116: #ifdef ASTDEBUG
                   1117:   printf ("\n");
                   1118:   fflush (stdout);
                   1119:   sleep (1);
                   1120: #endif
                   1121:   if (! stop_input)
                   1122:     queue_kbd_input ();
                   1123:   if (c >= 0)
                   1124:     kbd_buffer_store_char (c);
                   1125: 
                   1126:   errno = old_errno;
                   1127: }
                   1128: 
                   1129: /* Wait until there is something in kbd_buffer.  */
                   1130: 
                   1131: wait_for_kbd_input ()
                   1132: {
                   1133:   extern int have_process_input, process_exited;
                   1134: 
                   1135:   /* If already something, avoid doing system calls.  */
                   1136:   if (detect_input_pending ())
                   1137:     {
                   1138:       return;
                   1139:     }
                   1140:   /* Clear a flag, and tell ast routine above to set it.  */
                   1141:   SYS$CLREF (input_ef);
                   1142:   waiting_for_ast = 1;
                   1143:   /* Check for timing error: ast happened while we were doing that.  */
                   1144:   if (!detect_input_pending ())
                   1145:     {
                   1146:       /* No timing error: wait for flag to be set.  */
                   1147:       SYS$WFLOR (input_ef, input_eflist);
                   1148:       if (!detect_input_pending ())
                   1149:        /* Check for subprocess input availability */
                   1150:        {
                   1151:          int dsp = have_process_input || process_exited;
                   1152: 
                   1153:          if (have_process_input)
                   1154:            process_command_input ();
                   1155:          if (process_exited)
                   1156:            process_exit ();
                   1157:          if (dsp)
                   1158:            {
                   1159:              RedoModes++;
                   1160:              DoDsp (1);
                   1161:            }
                   1162:        }
                   1163:     }
                   1164:   waiting_for_ast = 0;
                   1165: }
                   1166: 
                   1167: /* Get rid of any pending QIO, when we are about to suspend
                   1168:    or when we want to throw away pending input.
                   1169:    We wait for a positive sign that the AST routine has run
                   1170:    and therefore there is no I/O request queued when we return.
                   1171:    SYS$SETAST is used to avoid a timing error.  */
                   1172: 
                   1173: end_kbd_input()
                   1174: {
                   1175: #ifdef ASTDEBUG
                   1176:   printf ("At end_kbd_input.\n");
                   1177:   fflush (stdout);
                   1178:   sleep (1);
                   1179: #endif
                   1180:   if (LIB$AST_IN_PROG ())  /* Don't wait if suspending from kbd_buffer_store_char! */
                   1181:     {
                   1182:       SYS$CANCEL (input_chan);
                   1183:       return;
                   1184:     }
                   1185: 
                   1186:   SYS$SETAST (0);
                   1187:   /* Clear a flag, and tell ast routine above to set it.  */
                   1188:   SYS$CLREF (input_ef);
                   1189:   waiting_for_ast = 1;
                   1190:   stop_input = 1;
                   1191:   SYS$CANCEL (input_chan);
                   1192:   SYS$SETAST (1);
                   1193:   SYS$WAITFR (input_ef);
                   1194:   waiting_for_ast = 0;
                   1195: }
                   1196: 
                   1197: /* Wait for either input available or time interval expiry.  */
                   1198: 
                   1199: input_wait_timeout (timeval)
                   1200:      int timeval;              /* Time to wait, in seconds */
                   1201: {
                   1202:   int time [2];
                   1203:   
                   1204:   LIB$EMUL (&timeval, &-10000000, &0, time);     /* Convert to VMS format */
                   1205: 
                   1206:   /* If already something, avoid doing system calls.  */
                   1207:   if (detect_input_pending ())
                   1208:     {
                   1209:       return;
                   1210:     }
                   1211:   /* Clear a flag, and tell ast routine above to set it.  */
                   1212:   SYS$CLREF (input_ef);
                   1213:   waiting_for_ast = 1;
                   1214:   /* Check for timing error: ast happened while we were doing that.  */
                   1215:   if (!detect_input_pending ())
                   1216:     {
                   1217:       /* No timing error: wait for flag to be set.  */
                   1218:       SYS$CANTIM (1, 0);
                   1219:       if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
                   1220:        SYS$WFLOR (timer_ef, timer_eflist);       /* Wait for timer expiry or input */
                   1221:     }
                   1222:   waiting_for_ast = 0;
                   1223: }
                   1224: 
                   1225: /* The standard `sleep' routine works some other way
                   1226:    and it stops working if you have ever quit out of it.
                   1227:    This one continues to work.  */
                   1228: 
                   1229: sys_sleep (timeval)
                   1230:      int timeval;
                   1231: {
                   1232:   int time [2];
                   1233:   
                   1234:   LIB$EMUL (&timeval, &-10000000, &0, time);     /* Convert to VMS format */
                   1235: 
                   1236:   SYS$CANTIM (1, 0);
                   1237:   if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
                   1238:     SYS$WAITFR (timer_ef);       /* Wait for timer expiry only */
                   1239: }
                   1240: 
                   1241: init_sigio ()
                   1242: {
                   1243:   request_sigio ();
                   1244: }
                   1245: 
                   1246: reset_sigio ()
                   1247: {
                   1248:   unrequest_sigio ();
                   1249: }
                   1250: 
                   1251: request_sigio ()
                   1252: {
                   1253:   croak ("request sigio");
                   1254: }
                   1255: 
                   1256: unrequest_sigio ()
                   1257: {
                   1258:   croak ("unrequest sigio");
                   1259: }
                   1260: 
                   1261: #endif /* VMS */
                   1262: 
                   1263: /* Note that VMS compiler won't accept defined (CANNOT_DUMP).  */
                   1264: #ifndef CANNOT_DUMP
                   1265: #define NEED_STARTS
                   1266: #endif
                   1267: 
                   1268: #ifndef SYSTEM_MALLOC
                   1269: #ifndef NEED_STARTS
                   1270: #define NEED_STARTS
                   1271: #endif
                   1272: #endif
                   1273: 
                   1274: #ifdef NEED_STARTS
                   1275: /* Some systems that cannot dump also cannot implement these.  */
                   1276: 
                   1277: /*
                   1278:  *     Return the address of the start of the text segment prior to
                   1279:  *     doing an unexec().  After unexec() the return value is undefined.
                   1280:  *     See crt0.c for further explanation and _start().
                   1281:  *
                   1282:  */
                   1283: 
                   1284: #ifndef CANNOT_UNEXEC
                   1285: char *
                   1286: start_of_text ()
                   1287: {
                   1288: #ifdef TEXT_START
                   1289:   return ((char *) TEXT_START);
                   1290: #else
                   1291: #ifdef GOULD
                   1292:   extern csrt();
                   1293:   return ((char *) csrt);
                   1294: #else /* not GOULD */
                   1295:   extern int _start ();
                   1296:   return ((char *) _start);
                   1297: #endif /* GOULD */
                   1298: #endif /* TEXT_START */
                   1299: }
                   1300: #endif /* not CANNOT_UNEXEC */
                   1301: 
                   1302: /*
                   1303:  *     Return the address of the start of the data segment prior to
                   1304:  *     doing an unexec().  After unexec() the return value is undefined.
                   1305:  *     See crt0.c for further information and definition of data_start.
                   1306:  *
                   1307:  *     Apparently, on BSD systems this is etext at startup.  On
                   1308:  *     USG systems (swapping) this is highly mmu dependent and
                   1309:  *     is also dependent on whether or not the program is running
                   1310:  *     with shared text.  Generally there is a (possibly large)
                   1311:  *     gap between end of text and start of data with shared text.
                   1312:  *
                   1313:  *     On Uniplus+ systems with shared text, data starts at a
                   1314:  *     fixed address.  Each port (from a given oem) is generally
                   1315:  *     different, and the specific value of the start of data can
                   1316:  *     be obtained via the UniPlus+ specific "uvar(2)" system call,
                   1317:  *     however the method outlined in crt0.c seems to be more portable.
                   1318:  *
                   1319:  *     Probably what will have to happen when a USG unexec is available,
                   1320:  *     at least on UniPlus, is temacs will have to be made unshared so
                   1321:  *     that text and data are contiguous.  Then once loadup is complete,
                   1322:  *     unexec will produce a shared executable where the data can be
                   1323:  *     at the normal shared text boundry and the startofdata variable
                   1324:  *     will be patched by unexec to the correct value.
                   1325:  *
                   1326:  */
                   1327:  
                   1328: char *
                   1329: start_of_data ()
                   1330: {
                   1331: #ifdef DATA_START
                   1332:   return ((char *) DATA_START);
                   1333: #else
                   1334:   extern int data_start;
                   1335:   return ((char *) &data_start);
                   1336: #endif
                   1337: }
                   1338: #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
                   1339: 
                   1340: #ifndef CANNOT_DUMP
                   1341: /* Some systems that cannot dump also cannot implement these.  */
                   1342: 
                   1343: /*
                   1344:  *     Return the address of the end of the text segment prior to
                   1345:  *     doing an unexec().  After unexec() the return value is undefined.
                   1346:  */
                   1347:  
                   1348: char *
                   1349: end_of_text ()
                   1350: {
                   1351: #ifdef TEXT_END
                   1352:   return ((char *) TEXT_END);
                   1353: #else
                   1354:   extern int etext;
                   1355:   return ((char *) &etext);
                   1356: #endif
                   1357: }
                   1358:  
                   1359: /*
                   1360:  *     Return the address of the end of the data segment prior to
                   1361:  *     doing an unexec().  After unexec() the return value is undefined.
                   1362:  */
                   1363: 
                   1364: char *
                   1365: end_of_data ()
                   1366: {
                   1367: #ifdef DATA_END
                   1368:   return ((char *) DATA_END);
                   1369: #else
                   1370:   extern int edata;
                   1371:   return ((char *) &edata);
                   1372: #endif
                   1373: }
                   1374: 
                   1375: #endif /* not CANNOT_DUMP */
                   1376: 
                   1377: /* Get_system_name returns as its value
                   1378:  a string for the Lisp function system-name to return. */
                   1379: 
                   1380: #ifdef BSD4_1
                   1381: #include <whoami.h>
                   1382: #endif
                   1383: 
                   1384: #ifdef USG
                   1385: /* Can't have this within the function since `static' is #defined to nothing */
                   1386: static struct utsname get_system_name_name;
                   1387: #endif
                   1388: 
                   1389: char *
                   1390: get_system_name ()
                   1391: {
                   1392: #ifdef USG
                   1393:   uname (&get_system_name_name);
                   1394:   return (get_system_name_name.nodename);
                   1395: #else /* Not USG */
                   1396: #ifdef BSD4_1
                   1397:   return sysname;
                   1398: #else /* not USG, not 4.1 */
                   1399:   static char system_name_saved[32];
                   1400: #ifdef VMS
                   1401:   char *sp;
                   1402:   if ((sp = egetenv("SYS$NODE")) == 0)
                   1403:     sp = "vax-vms";
                   1404:   else
                   1405:     {
                   1406:       char *end;
                   1407: 
                   1408:       if ((end = index (sp, ':')) != 0)
                   1409:        *end = '\0';
                   1410:     }
                   1411:   strcpy (system_name_saved, sp);
                   1412: #else /* not VMS */
                   1413:   gethostname (system_name_saved, sizeof (system_name_saved));
                   1414: #endif /* not VMS */
                   1415:   return system_name_saved;
                   1416: #endif /* not USG, not 4.1 */
                   1417: #endif /* not USG */
                   1418: }
                   1419: 
                   1420: #ifndef HAVE_SELECT
                   1421: 
                   1422: /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
                   1423:  * Only checks read descriptors.
                   1424:  */
                   1425: /* How long to wait between checking fds in select */
                   1426: #define SELECT_PAUSE 1
                   1427: int select_alarmed;
                   1428: 
                   1429: /* For longjmp'ing back to read_input_waiting.  */
                   1430: 
                   1431: jmp_buf read_alarm_throw;
                   1432: 
                   1433: /* Nonzero if the alarm signal should throw back to read_input_waiting.
                   1434:    The read_socket_hook function sets this to 1 while it is waiting.  */
                   1435: 
                   1436: int read_alarm_should_throw;
                   1437: 
                   1438: select_alarm ()
                   1439: {
                   1440:   select_alarmed = 1;
                   1441: #ifdef BSD4_1
                   1442:   sigrelse (SIGALRM);
                   1443: #else /* not BSD4_1 */
                   1444:   signal (SIGALRM, SIG_IGN);
                   1445: #endif /* not BSD4_1 */
                   1446:   if (read_alarm_should_throw)
                   1447:     longjmp (read_alarm_throw, 1);
                   1448: }
                   1449: 
                   1450: /* Only rfds are checked and timeout must point somewhere */
                   1451: int
                   1452: select (nfds, rfds, wfds, efds, timeout)
                   1453:      int nfds;
                   1454:      int *rfds, *wfds, *efds, *timeout;
                   1455: {
                   1456:   int ravail = 0, orfds = 0, old_alarm;
                   1457:   extern int kbd_count;
                   1458:   extern int proc_buffered_char[];
                   1459: #ifndef subprocesses
                   1460:   int child_changed = 0;
                   1461: #else
                   1462:   extern int child_changed;
                   1463: #endif
                   1464:   int (*old_trap) ();
                   1465:   char buf;
                   1466: 
                   1467:   if (rfds)
                   1468:     {
                   1469:       orfds = *rfds;
                   1470:       *rfds = 0;
                   1471:     }
                   1472:   if (wfds)
                   1473:     *wfds = 0;
                   1474:   if (efds)
                   1475:     *efds = 0;
                   1476: 
                   1477:   /* If we are looking only for the terminal, with no timeout,
                   1478:      just read it and wait -- that's more efficient.  */
                   1479:   if (orfds == 1 && *timeout == 100000 && !child_changed)
                   1480:     {
                   1481:       if (!kbd_count)
                   1482:        read_input_waiting ();
                   1483:       *rfds = 1;
                   1484:       return 1;
                   1485:     }
                   1486: 
                   1487:   /* Once a second, till the timer expires, check all the flagged read
                   1488:    * descriptors to see if any input is available.  If there is some then
                   1489:    * set the corresponding bit in the return copy of rfds.
                   1490:    */ 
                   1491:   while (1)
                   1492:     {
                   1493:       register int to_check, bit, fd;
                   1494: 
                   1495:       if (rfds)
                   1496:        {
                   1497:          for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
                   1498:            {
                   1499:              if (orfds & bit)
                   1500:                {
                   1501:                  int avail = 0, status = 0;
                   1502: 
                   1503:                  if (bit == 1)
                   1504:                    avail = detect_input_pending(); /* Special keyboard handler */
                   1505:                  else
                   1506:                    {
                   1507: #ifdef FIONREAD
                   1508:                      status = ioctl (fd, FIONREAD, &avail);
                   1509: #else /* no FIONREAD */
                   1510:                      /* Hoping it will return -1 if nothing available
                   1511:                         or 0 if all 0 chars requested are read.  */
                   1512:                      if (proc_buffered_char[fd] >= 0)
                   1513:                        avail = 1;
                   1514:                      else
                   1515:                        {
                   1516:                          avail = read (fd, &buf, 1);
                   1517:                          if (avail > 0)
                   1518:                            proc_buffered_char[fd] = buf;
                   1519:                        }
                   1520: #endif /* no FIONREAD */
                   1521:                    }
                   1522:                  if (status >= 0 && avail > 0)
                   1523:                    {
                   1524:                      (*rfds) |= bit;
                   1525:                      ravail++;
                   1526:                    }
                   1527:                }
                   1528:            }
                   1529:        }
                   1530:       if (*timeout == 0 || ravail != 0 || child_changed)
                   1531:        break;
                   1532:       old_alarm = alarm (0);
                   1533:       old_trap = (int (*)()) signal (SIGALRM, select_alarm);
                   1534:       select_alarmed = 0;
                   1535:       alarm (SELECT_PAUSE);
                   1536:       /* Wait for a SIGALRM (or maybe a SIGTINT) */
                   1537:       while (select_alarmed == 0 && *timeout != 0 && child_changed == 0)
                   1538:        {
                   1539:          /* If we are interested in terminal input,
                   1540:             wait by reading the terminal.
                   1541:             That makes instant wakeup for terminal input at least.  */
                   1542:          if (orfds & 1)
                   1543:            {
                   1544:              read_input_waiting ();
                   1545:              if (kbd_count)
                   1546:                select_alarmed = 1;
                   1547:            }
                   1548:          else
                   1549:            pause();
                   1550:        }
                   1551:       (*timeout) -= SELECT_PAUSE;
                   1552:       /* Reset the old alarm if there was one */
                   1553:       alarm (0);
                   1554:       signal (SIGALRM, old_trap);
                   1555:       if (old_alarm != 0)
                   1556:        {
                   1557:          /* Reset or forge an interrupt for the original handler. */
                   1558:          old_alarm -= SELECT_PAUSE;
                   1559:          if (old_alarm <= 0)
                   1560:            kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
                   1561:          else
                   1562:            alarm (old_alarm);
                   1563:        }
                   1564:       if (*timeout == 0)  /* Stop on timer being cleared */
                   1565:        break;
                   1566:     }
                   1567:   return ravail;
                   1568: }
                   1569: 
                   1570: /* Read keyboard input into the standard buffer,
                   1571:    waiting for at least one character.  */
                   1572: 
                   1573: /* Make all keyboard buffers much bigger when using X windows.  */
                   1574: #ifdef HAVE_X_WINDOWS
                   1575: #define BUFFER_SIZE_FACTOR 16
                   1576: #else
                   1577: #define BUFFER_SIZE_FACTOR 1
                   1578: #endif
                   1579: 
                   1580: read_input_waiting ()
                   1581: {
                   1582:   extern int kbd_count;
                   1583:   extern unsigned char kbd_buffer[];
                   1584:   extern unsigned char *kbd_ptr;
                   1585:   int val;
                   1586: 
                   1587:   if (read_socket_hook)
                   1588:     {
                   1589:       read_alarm_should_throw = 0;
                   1590:       if (! setjmp (read_alarm_throw))
                   1591:        val = (*read_socket_hook) (0, kbd_buffer, 256 * BUFFER_SIZE_FACTOR);
                   1592:       else
                   1593:        val = -1;
                   1594:     }
                   1595:   else
                   1596:     val = read (fileno (stdin), kbd_buffer, 1);
                   1597: 
                   1598:   if (val > 0)
                   1599:     {
                   1600:       kbd_ptr = kbd_buffer;
                   1601:       kbd_count = val;
                   1602:     }
                   1603: }
                   1604: 
                   1605: #endif /* not HAVE_SELECT */
                   1606: 
                   1607: #ifdef BSD4_1
                   1608: /* VARARGS */
                   1609: setpriority ()
                   1610: {
                   1611:   return 0;
                   1612: }
                   1613: 
                   1614: /*
                   1615:  * Partially emulate 4.2 open call.
                   1616:  * open is defined as this in 4.1.
                   1617:  *
                   1618:  * - added by Michael Bloom @ Citicorp/TTI
                   1619:  *
                   1620:  */
                   1621: 
                   1622: int
                   1623: sys_open (path, oflag, mode)
                   1624:      char *path;
                   1625:      int oflag, mode;
                   1626: {
                   1627:   if (oflag & O_CREAT) 
                   1628:     return creat (path, mode);
                   1629:   else
                   1630:     return open (path, oflag);
                   1631: }
                   1632: 
                   1633: init_sigio ()
                   1634: {
                   1635:   if (noninteractive)
                   1636:     return;
                   1637:   lmode = LINTRUP | lmode;
                   1638:   ioctl (0, TIOCLSET, &lmode);
                   1639: }
                   1640: 
                   1641: reset_sigio ()
                   1642: {
                   1643:   if (noninteractive)
                   1644:     return;
                   1645:   lmode = ~LINTRUP & lmode;
                   1646:   ioctl (0, TIOCLSET, &lmode);
                   1647: }
                   1648: 
                   1649: request_sigio ()
                   1650: {
                   1651:   sigrelse (SIGTINT);
                   1652: 
                   1653:   interrupts_deferred = 0;
                   1654: }
                   1655: 
                   1656: unrequest_sigio ()
                   1657: {
                   1658:   sighold (SIGTINT);
                   1659: 
                   1660:   interrupts_deferred = 1;
                   1661: }
                   1662: 
                   1663: /* still inside #ifdef BSD4_1 */
                   1664: #ifdef subprocesses
                   1665: 
                   1666: int sigheld; /* Mask of held signals */
                   1667: 
                   1668: sigholdx (signum)
                   1669:      int signum;
                   1670: {
                   1671:   sigheld |= sigbit (signum);
                   1672:   sighold (signum);
                   1673: }
                   1674: 
                   1675: sigisheld (signum)
                   1676:      int signum;
                   1677: {
                   1678:   sigheld |= sigbit (signum);
                   1679: }
                   1680: 
                   1681: sigunhold (signum)
                   1682:      int signum;
                   1683: {
                   1684:   sigheld &= ~sigbit (signum);
                   1685:   sigrelse (signum);
                   1686: }
                   1687: 
                   1688: sigfree ()    /* Free all held signals */
                   1689: {
                   1690:   int i;
                   1691:   for (i = 0; i < NSIG; i++)
                   1692:     if (sigheld & sigbit (i))
                   1693:       sigrelse (i);
                   1694:   sigheld = 0;
                   1695: }
                   1696: 
                   1697: sigbit (i)
                   1698: {
                   1699:   return 1 << (i - 1);
                   1700: }
                   1701: #endif /* subprocesses */
                   1702: #endif /* BSD4_1 */
                   1703: 
                   1704: #ifndef BSTRING
                   1705: 
                   1706: void
                   1707: bzero (b, length)
                   1708:      register char *b;
                   1709:      register int length;
                   1710: {
                   1711: #ifdef VMS
                   1712:   short zero = 0;
                   1713:   long max_str = 65535;
                   1714: 
                   1715:   while (length > max_str) {
                   1716:     (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
                   1717:     length -= max_str;
                   1718:     b += max_str;
                   1719:   }
                   1720:   (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);
                   1721: #else
                   1722:   while (length-- > 0)
                   1723:     *b++ = 0;
                   1724: #endif /* not VMS */
                   1725: }
                   1726: 
                   1727: /* Saying `void' requires a declaration, above, where bcopy is used
                   1728:    and that declaration causes pain for systems where bcopy is a macro.  */
                   1729: bcopy (b1, b2, length)
                   1730:      register char *b1;
                   1731:      register char *b2;
                   1732:      register int length;
                   1733: {
                   1734: #ifdef VMS
                   1735:   long max_str = 65535;
                   1736: 
                   1737:   while (length > max_str) {
                   1738:     (void) LIB$MOVC3 (&max_str, b1, b2);
                   1739:     length -= max_str;
                   1740:     b1 += max_str;
                   1741:     b2 += max_str;
                   1742:   }
                   1743:   (void) LIB$MOVC3 (&length, b1, b2);
                   1744: #else
                   1745:   while (length-- > 0)
                   1746:     *b2++ = *b1++;
                   1747: #endif /* not VMS */
                   1748: }
                   1749: 
                   1750: int
                   1751: bcmp (b1, b2, length)  /* This could be a macro! */
                   1752:      register char *b1;
                   1753:      register char *b2;
                   1754:      register int length;
                   1755: {
                   1756: #ifdef VMS
                   1757:   struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
                   1758:   struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
                   1759: 
                   1760:   return STR$COMPARE (&src1, &src2);
                   1761: #else
                   1762:   while (length-- > 0)
                   1763:     if (*b1++ != *b2++)
                   1764:       return 1;
                   1765: 
                   1766:   return 0;
                   1767: #endif /* not VMS */
                   1768: }
                   1769: #endif /* not BSTRING */
                   1770: 
                   1771: #ifdef BSD4_1
                   1772: long random ()
                   1773: {
                   1774:   return (rand ());
                   1775: }
                   1776: 
                   1777: srandom (arg)
                   1778:      int arg;
                   1779: {
                   1780:   srand (arg);
                   1781: }
                   1782: #endif BSD4_1
                   1783: 
                   1784: #ifdef USG
                   1785: /*
                   1786:  *     The BSD random(3) returns numbers in the range of
                   1787:  *     0 to 2e31 - 1.  The USG rand(3C) returns numbers in the
                   1788:  *     range of 0 to 2e15 - 1.  This is probably not significant
                   1789:  *     in this usage.
                   1790:  */
                   1791:   
                   1792: long
                   1793: random ()
                   1794: {
                   1795:   /* Arrange to return a range centered on zero.  */
                   1796:   return rand () - (1 << 14);
                   1797: }
                   1798: 
                   1799: srandom (arg)
                   1800:      int arg;
                   1801: {
                   1802:   srand (arg);
                   1803: }
                   1804: 
                   1805: #endif /* USG */
                   1806: 
                   1807: 
                   1808: #ifdef VMS
                   1809: 
                   1810: #ifdef getenv
                   1811: /* If any place else asks for the TERM variable,
                   1812:    allow it to be overridden with the EMACS_TERM variable
                   1813:    before attempting to translate the logical name TERM.  As a last
                   1814:    resort, ask for VAX C's special idea of the TERM variable.  */
                   1815: #undef getenv
                   1816: char *
                   1817: sys_getenv (name)
                   1818:      char *name;
                   1819: {
                   1820:   register char *val;
                   1821:   static char buf[256];
                   1822:   static struct dsc$descriptor_s equiv
                   1823:     = {sizeof(buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
                   1824:   static struct dsc$descriptor_s d_name
                   1825:     = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
                   1826:   short eqlen;
                   1827: 
                   1828:   if (!strcmp (name, "TERM"))
                   1829:     {
                   1830:       val = (char *) getenv ("EMACS_TERM");
                   1831:       if (val)
                   1832:        return val;
                   1833:     }
                   1834: 
                   1835:   d_name.dsc$w_length = strlen (name);
                   1836:   d_name.dsc$a_pointer = name;
                   1837:   if (lib$sys_trnlog (&d_name, &eqlen, &equiv) == 1)
                   1838:     {
                   1839:       char *str = (char *) xmalloc (eqlen + 1);
                   1840:       bcopy (buf, str, eqlen);
                   1841:       str[eqlen] = '\0';
                   1842:       /* This is a storage leak, but a pain to fix.  With luck,
                   1843:         no one will ever notice.  */
                   1844:       return str;
                   1845:     }
                   1846:   return (char *) getenv (name);
                   1847: }
                   1848: #endif /* getenv */
                   1849: 
                   1850: #ifdef abort
                   1851: /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
                   1852:    to force a call on the debugger from within the image. */
                   1853: #undef abort
                   1854: sys_abort ()
                   1855: {
                   1856:   reset_sys_modes ();
                   1857:   LIB$SIGNAL (SS$_DEBUG);
                   1858: }
                   1859: #endif /* abort */
                   1860: #endif /* VMS */
                   1861: 
                   1862: #ifdef VMS
                   1863: #ifdef LINK_CRTL_SHARE
                   1864: #ifdef SHAREABLE_LIB_BUG
                   1865: /* Variables declared noshare and initialized in shareable libraries
                   1866:    cannot be shared.  The VMS linker incorrectly forces you to use a private
                   1867:    version which is uninitialized... If not for this "feature", we
                   1868:    could use the C library definition of sys_nerr and sys_errlist. */
                   1869: int sys_nerr = 35;
                   1870: char *sys_errlist[] =
                   1871:   {
                   1872:     "error 0",
                   1873:     "not owner",
                   1874:     "no such file or directory",
                   1875:     "no such process",
                   1876:     "interrupted system call",
                   1877:     "i/o error",
                   1878:     "no such device or address",
                   1879:     "argument list too long",
                   1880:     "exec format error",
                   1881:     "bad file number",
                   1882:     "no child process",
                   1883:     "no more processes",
                   1884:     "not enough memory",
                   1885:     "permission denied",
                   1886:     "bad address",
                   1887:     "block device required",
                   1888:     "mount devices busy",
                   1889:     "file exists",
                   1890:     "cross-device link",
                   1891:     "no such device",
                   1892:     "not a directory",
                   1893:     "is a directory",
                   1894:     "invalid argument",
                   1895:     "file table overflow",
                   1896:     "too many open files",
                   1897:     "not a typewriter",
                   1898:     "text file busy",
                   1899:     "file too big",
                   1900:     "no space left on device",
                   1901:     "illegal seek",
                   1902:     "read-only file system",
                   1903:     "too many links",
                   1904:     "broken pipe",
                   1905:     "math argument",
                   1906:     "result too large",
                   1907:     "I/O stream empty",
                   1908:     "vax/vms specific error code nontranslatable error"
                   1909:   };
                   1910: #endif /* SHAREABLE_LIB_BUG */
                   1911: #endif /* LINK_CRTL_SHARE */
                   1912: #endif /* VMS */
                   1913: 
                   1914: #ifdef INTERRUPTABLE_OPEN
                   1915: 
                   1916: int
                   1917: /* VARARGS 2 */
                   1918: sys_open (path, oflag, mode)
                   1919:      char *path;
                   1920:      int oflag, mode;
                   1921: {
                   1922:   register int rtnval;
                   1923:   
                   1924:   while ((rtnval = open (path, oflag, mode)) == -1 && errno == EINTR);
                   1925:   return (rtnval);
                   1926: }
                   1927: 
                   1928: #endif /* INTERRUPTABLE_OPEN */
                   1929: 
                   1930: #ifdef INTERRUPTABLE_CLOSE
                   1931: 
                   1932: sys_close (fd)
                   1933:      int fd;
                   1934: {
                   1935:   register int rtnval;
                   1936: 
                   1937:   while ((rtnval = close(fd)) == -1 && errno == EINTR);
                   1938:   return rtnval;
                   1939: }
                   1940: 
                   1941: #endif /* INTERRUPTABLE_CLOSE */
                   1942: 
                   1943: #ifdef INTERRUPTABLE_IO
                   1944: 
                   1945: int
                   1946: sys_read (fildes, buf, nbyte)
                   1947:      int fildes;
                   1948:      char *buf;
                   1949:      unsigned int nbyte;
                   1950: {
                   1951:   register int rtnval;
                   1952:   
                   1953:   while ((rtnval = read (fildes, buf, nbyte)) == -1 && errno == EINTR);
                   1954:   return (rtnval);
                   1955: }
                   1956: 
                   1957: int
                   1958: sys_write (fildes, buf, nbyte)
                   1959:      int fildes;
                   1960:      char *buf;
                   1961:      unsigned int nbyte;
                   1962: {
                   1963:   register int rtnval;
                   1964: 
                   1965:   while ((rtnval = write (fildes, buf, nbyte)) == -1 && errno == EINTR);
                   1966:   return (rtnval);
                   1967: }
                   1968: 
                   1969: #endif /* INTERRUPTABLE_IO */
                   1970: 
                   1971: #ifdef USG
                   1972: /*
                   1973:  *     All of the following are for USG.
                   1974:  *
                   1975:  *     On USG systems the system calls are interruptable by signals
                   1976:  *     that the user program has elected to catch.  Thus the system call
                   1977:  *     must be retried in these cases.  To handle this without massive
                   1978:  *     changes in the source code, we remap the standard system call names
                   1979:  *     to names for our own functions in sysdep.c that do the system call
                   1980:  *     with retries.  Actually, for portability reasons, it is good
                   1981:  *     programming practice, as this example shows, to limit all actual
                   1982:  *     system calls to a single occurance in the source.  Sure, this
                   1983:  *     adds an extra level of function call overhead but it is almost
                   1984:  *     always negligible.   Fred Fish, Unisoft Systems Inc.
                   1985:  */
                   1986: 
                   1987: char *sys_siglist[NSIG + 1] =
                   1988: {
                   1989: #ifdef IBMRTAIX
                   1990: /* AIX has changed the signals a bit */
                   1991:   "bogus signal",                      /* 0 */
                   1992:   "hangup",                            /* 1  SIGHUP */
                   1993:   "interrupt",                         /* 2  SIGINT */
                   1994:   "quit",                              /* 3  SIGQUIT */
                   1995:   "illegal instruction",               /* 4  SIGILL */
                   1996:   "trace trap",                                /* 5  SIGTRAP */
                   1997:   "IOT instruction",                   /* 6  SIGIOT */
                   1998:   "crash likely",                      /* 7  SIGDANGER */
                   1999:   "floating point exception",          /* 8  SIGFPE */
                   2000:   "kill",                              /* 9  SIGKILL */
                   2001:   "bus error",                         /* 10 SIGBUS */
                   2002:   "segmentation violation",            /* 11 SIGSEGV */
                   2003:   "bad argument to system call",       /* 12 SIGSYS */
                   2004:   "write on a pipe with no one to read it", /* 13 SIGPIPE */
                   2005:   "alarm clock",                       /* 14 SIGALRM */
                   2006:   "software termination signum",       /* 15 SIGTERM */
                   2007:   "user defined signal 1",             /* 16 SIGUSR1 */
                   2008:   "user defined signal 2",             /* 17 SIGUSR2 */
                   2009:   "death of a child",                  /* 18 SIGCLD */
                   2010:   "power-fail restart",                        /* 19 SIGPWR */
                   2011:   "bogus signal",                      /* 20 */
                   2012:   "bogus signal",                      /* 21 */
                   2013:   "bogus signal",                      /* 22 */
                   2014:   "bogus signal",                      /* 23 */
                   2015:   "bogus signal",                      /* 24 */
                   2016:   "LAN I/O interrupt",                 /* 25 SIGAIO */
                   2017:   "PTY I/O interrupt",                 /* 26 SIGPTY */
                   2018:   "I/O intervention required",         /* 27 SIGIOINT */
                   2019:   "HFT grant",                         /* 28 SIGGRANT */
                   2020:   "HFT retract",                       /* 29 SIGRETRACT */
                   2021:   "HFT sound done",                    /* 30 SIGSOUND */
                   2022:   "HFT input ready",                   /* 31 SIGMSG */
                   2023: #else /* not IBMRTAIX */
                   2024:   "bogus signal",                      /* 0 */
                   2025:   "hangup",                            /* 1  SIGHUP */
                   2026:   "interrupt",                         /* 2  SIGINT */
                   2027:   "quit",                              /* 3  SIGQUIT */
                   2028:   "illegal instruction",               /* 4  SIGILL */
                   2029:   "trace trap",                                /* 5  SIGTRAP */
                   2030:   "IOT instruction",                   /* 6  SIGIOT */
                   2031:   "EMT instruction",                   /* 7  SIGEMT */
                   2032:   "floating point exception",          /* 8  SIGFPE */
                   2033:   "kill",                              /* 9  SIGKILL */
                   2034:   "bus error",                         /* 10 SIGBUS */
                   2035:   "segmentation violation",            /* 11 SIGSEGV */
                   2036:   "bad argument to system call",       /* 12 SIGSYS */
                   2037:   "write on a pipe with no one to read it", /* 13 SIGPIPE */
                   2038:   "alarm clock",                       /* 14 SIGALRM */
                   2039:   "software termination signum",       /* 15 SIGTERM */
                   2040:   "user defined signal 1",             /* 16 SIGUSR1 */
                   2041:   "user defined signal 2",             /* 17 SIGUSR2 */
                   2042:   "death of a child",                  /* 18 SIGCLD */
                   2043:   "power-fail restart",                        /* 19 SIGPWR */
                   2044: #endif /* not IBMRTAIX */
                   2045:   0
                   2046:   };
                   2047: 
                   2048: /*
                   2049:  *     Warning, this function may not duplicate 4.2 action properly
                   2050:  *     under error conditions.
                   2051:  */
                   2052: 
                   2053: #ifndef MAXPATHLEN
                   2054: /* In 4.1, param.h fails to define this.  */
                   2055: #define MAXPATHLEN 1024
                   2056: #endif
                   2057: 
                   2058: #ifndef HAVE_GETWD
                   2059: 
                   2060: char *
                   2061: getwd (pathname)
                   2062:      char *pathname;
                   2063: {
                   2064:   char *npath, *spath;
                   2065:   extern char *getcwd ();
                   2066: 
                   2067:   spath = npath = getcwd ((char *) 0, MAXPATHLEN);
                   2068:   /* On Altos 3068, getcwd can return @hostname/dir, so discard
                   2069:      up to first slash.  Should be harmless on other systems.  */
                   2070:   while (*npath && *npath != '/')
                   2071:     npath++;
                   2072:   strcpy (pathname, npath);
                   2073:   free (spath);                        /* getcwd uses malloc */
                   2074:   return pathname;
                   2075: }
                   2076: 
                   2077: #endif HAVE_GETWD
                   2078: 
                   2079: /*
                   2080:  *     Emulate rename using unlink/link.  Note that this is
                   2081:  *     only partially correct.  Also, doesn't enforce restriction
                   2082:  *     that files be of same type (regular->regular, dir->dir, etc).
                   2083:  */
                   2084: 
                   2085: rename (from, to)
                   2086:      char *from;
                   2087:      char *to;
                   2088: {
                   2089:   if (access (from, 0) == 0)
                   2090:     {
                   2091:       unlink (to);
                   2092:       if (link (from, to) == 0)
                   2093:        if (unlink (from) == 0)
                   2094:          return (0);
                   2095:     }
                   2096:   return (-1);
                   2097: }
                   2098: 
                   2099: /* VARARGS */
                   2100: setpriority ()
                   2101: {
                   2102:   return (0);
                   2103: }
                   2104: 
                   2105: #ifndef HAVE_VFORK
                   2106: 
                   2107: /*
                   2108:  *     Substitute fork(2) for vfork(2) on USG flavors.
                   2109:  */
                   2110: 
                   2111: vfork ()
                   2112: {
                   2113:   return (fork ());
                   2114: }
                   2115: 
                   2116: #endif /* not HAVE_VFORK */
                   2117: 
                   2118: #ifdef MISSING_UTIMES
                   2119: 
                   2120: /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes.  */
                   2121: 
                   2122: utimes ()
                   2123: {
                   2124: }
                   2125: #endif
                   2126: 
                   2127: #ifdef IRIS_UTIME
                   2128: 
                   2129: /* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
                   2130:    utimbuf structure defined anywhere but in the man page. */
                   2131: 
                   2132: struct utimbuf
                   2133:  {
                   2134:    long actime;
                   2135:    long modtime;
                   2136:  };
                   2137: 
                   2138: utimes (name, tvp)
                   2139:      char *name;
                   2140:      struct timeval tvp[];
                   2141: {
                   2142:   struct utimbuf utb;
                   2143:   utb.actime  = tvp[0].tv_sec;
                   2144:   utb.modtime = tvp[1].tv_sec;
                   2145:   utime (name, &utb);
                   2146: }
                   2147: #endif /* IRIS_UTIME */
                   2148: 
                   2149: 
                   2150: #ifdef HPUX
                   2151: 
                   2152: /* HPUX curses library references perror, but as far as we know
                   2153:    it won't be called.  Anyway this definition will do for now.  */
                   2154: 
                   2155: perror ()
                   2156: {
                   2157: }
                   2158: 
                   2159: #endif /* HPUX */
                   2160: 
                   2161: #ifndef HAVE_DUP2
                   2162: 
                   2163: /*
                   2164:  *     Emulate BSD dup2(2).  First close newd if it already exists.
                   2165:  *     Then, attempt to dup oldd.  If not successful, call dup2 recursively
                   2166:  *     until we are, then close the unsuccessful ones.
                   2167:  */
                   2168: 
                   2169: dup2 (oldd, newd)
                   2170:      int oldd;
                   2171:      int newd;
                   2172: {
                   2173:   register int fd;
                   2174:   
                   2175:   sys_close (newd);
                   2176: 
                   2177: #ifdef F_DUPFD
                   2178:   fd = fcntl (oldd, F_DUPFD, newd);
                   2179:   if (fd != newd)
                   2180:     error ("cant dup2(%i,%i) : %s", oldd, newd, sys_errlist[errno]);
                   2181: #else
                   2182:   while ((fd = dup (oldd)) != newd)
                   2183:     {
                   2184:       dup2 (oldd, newd);
                   2185:       sys_close (fd);
                   2186:     }
                   2187: #endif
                   2188: }
                   2189: 
                   2190: #endif /* not HAVE_DUP2 */
                   2191: 
                   2192: /*
                   2193:  *     Gettimeofday.  Simulate as much as possible.  Only accurate
                   2194:  *     to nearest second.  Emacs doesn't use tzp so ignore it for now.
                   2195:  *     Only needed when subprocesses are defined.
                   2196:  */
                   2197: 
                   2198: #ifdef subprocesses
                   2199: #ifndef HAVE_GETTIMEOFDAY
                   2200: #ifdef HAVE_TIMEVAL
                   2201:  
                   2202: /* ARGSUSED */
                   2203: gettimeofday (tp, tzp)
                   2204:      struct timeval *tp;
                   2205:      struct timezone *tzp;
                   2206: {
                   2207:   extern long time ();
                   2208: 
                   2209:   tp->tv_sec = time ((long *)0);    
                   2210:   tp->tv_usec = 0;
                   2211: }
                   2212:  
                   2213: #endif
                   2214: #endif
                   2215: #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
                   2216:   
                   2217: /*
                   2218:  *     This function will go away as soon as all the stubs fixed. (fnf)
                   2219:  */
                   2220: 
                   2221: croak (badfunc)
                   2222:      char *badfunc;
                   2223: {
                   2224:   printf ("%s not yet implemented\r\n", badfunc);
                   2225:   reset_sys_modes ();
                   2226:   exit (1);
                   2227: }
                   2228: 
                   2229: #endif /* USG */
                   2230: 
                   2231: /* Directory routines for systems that don't have them. */
                   2232: 
                   2233: #ifdef SYSV_SYSTEM_DIR
                   2234: 
                   2235: #include <dirent.h>
                   2236: 
                   2237: #ifndef HAVE_CLOSEDIR
                   2238: int
                   2239: closedir (dirp)
                   2240:      register DIR *dirp;              /* stream from opendir() */
                   2241: {
                   2242:   sys_close (dirp->dd_fd);
                   2243:   free ((char *) dirp->dd_buf);       /* directory block defined in <dirent.h> */
                   2244:   free ((char *) dirp);
                   2245: }
                   2246: #endif /* not HAVE_CLOSEDIR */
                   2247: 
                   2248: #endif /* SYSV_SYSTEM_DIR */
                   2249: 
                   2250: #ifdef NONSYSTEM_DIR_LIBRARY
                   2251: 
                   2252: DIR *
                   2253: opendir (filename)
                   2254:      char *filename;   /* name of directory */
                   2255: {
                   2256:   register DIR *dirp;          /* -> malloc'ed storage */
                   2257:   register int fd;             /* file descriptor for read */
                   2258:   struct stat sbuf;            /* result of fstat() */
                   2259: 
                   2260:   fd = sys_open (filename, 0);
                   2261:   if (fd < 0)
                   2262:     return 0;
                   2263: 
                   2264:   if (fstat (fd, &sbuf) < 0
                   2265:       || (sbuf.st_mode & S_IFMT) != S_IFDIR
                   2266:       || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
                   2267:     {
                   2268:       sys_close (fd);
                   2269:       return 0;                /* bad luck today */
                   2270:     }
                   2271: 
                   2272:   dirp->dd_fd = fd;
                   2273:   dirp->dd_loc = dirp->dd_size = 0;    /* refill needed */
                   2274: 
                   2275:   return dirp;
                   2276: }
                   2277: 
                   2278: void
                   2279: closedir (dirp)
                   2280:      register DIR *dirp;               /* stream from opendir() */
                   2281: {
                   2282:   sys_close (dirp->dd_fd);
                   2283:   free ((char *) dirp);
                   2284: }
                   2285: 
                   2286: 
                   2287: #ifndef VMS
                   2288: #define DIRSIZ 14
                   2289: struct olddir
                   2290:   {
                   2291:     ino_t od_ino;              /* inode */
                   2292:     char od_name[DIRSIZ];      /* filename */
                   2293:   };
                   2294: #endif /* not VMS */
                   2295: 
                   2296: struct direct dir_static;      /* simulated directory contents */
                   2297: 
                   2298: /* ARGUSED */
                   2299: struct direct *
                   2300: readdir (dirp)
                   2301:      register DIR *dirp;       /* stream from opendir() */
                   2302: {
                   2303: #ifndef VMS
                   2304:   register struct olddir *dp;  /* -> directory data */
                   2305: #else /* VMS */
                   2306:   register struct dir$_name *dp; /* -> directory data */
                   2307:   register struct dir$_version *dv; /* -> version data */
                   2308: #endif /* VMS */
                   2309: 
                   2310:   for (; ;)
                   2311:     {
                   2312:       if (dirp->dd_loc >= dirp->dd_size)
                   2313:        dirp->dd_loc = dirp->dd_size = 0;
                   2314: 
                   2315:       if (dirp->dd_size == 0   /* refill buffer */
                   2316:          && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
                   2317:        return 0;
                   2318: 
                   2319: #ifndef VMS
                   2320:       dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
                   2321:       dirp->dd_loc += sizeof (struct olddir);
                   2322: 
                   2323:       if (dp->od_ino != 0)     /* not deleted entry */
                   2324:        {
                   2325:          dir_static.d_ino = dp->od_ino;
                   2326:          strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
                   2327:          dir_static.d_name[DIRSIZ] = '\0';
                   2328:          dir_static.d_namlen = strlen (dir_static.d_name);
                   2329:          dir_static.d_reclen = sizeof (struct direct)
                   2330:            - MAXNAMLEN + 3
                   2331:              + dir_static.d_namlen - dir_static.d_namlen % 4;
                   2332:          return &dir_static;   /* -> simulated structure */
                   2333:        }
                   2334: #else /* VMS */
                   2335:       dp = (struct dir$_name *) dirp->dd_buf;
                   2336:       if (dirp->dd_loc == 0)
                   2337:        dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
                   2338:          : dp->dir$b_namecount;
                   2339:       dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
                   2340:       dir_static.d_ino = dv->dir$w_fid_num;
                   2341:       dir_static.d_namlen = dp->dir$b_namecount;
                   2342:       dir_static.d_reclen = sizeof (struct direct)
                   2343:        - MAXNAMLEN + 3
                   2344:          + dir_static.d_namlen - dir_static.d_namlen % 4;
                   2345:       strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
                   2346:       dir_static.d_name[dir_static.d_namlen] = '\0';
                   2347:       dirp->dd_loc = dirp->dd_size; /* only one record at a time */
                   2348:       return &dir_static;
                   2349: #endif /* VMS */
                   2350:     }
                   2351: }
                   2352: 
                   2353: #ifdef VMS
                   2354: /* readdirver is just like readdir except it returns all versions of a file
                   2355:    as separate entries.  */
                   2356: 
                   2357: /* ARGUSED */
                   2358: struct direct *
                   2359: readdirver (dirp)
                   2360:      register DIR *dirp;       /* stream from opendir() */
                   2361: {
                   2362:   register struct dir$_name *dp; /* -> directory data */
                   2363:   register struct dir$_version *dv; /* -> version data */
                   2364: 
                   2365:   if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
                   2366:     dirp->dd_loc = dirp->dd_size = 0;
                   2367: 
                   2368:   if (dirp->dd_size == 0       /* refill buffer */
                   2369:       && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
                   2370:     return 0;
                   2371: 
                   2372:   dp = (struct dir$_name *) dirp->dd_buf;
                   2373:   if (dirp->dd_loc == 0)
                   2374:     dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
                   2375:                   : dp->dir$b_namecount;
                   2376:   dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
                   2377:   strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
                   2378:   sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
                   2379:   dir_static.d_namlen = strlen (dir_static.d_name);
                   2380:   dir_static.d_ino = dv->dir$w_fid_num;
                   2381:   dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
                   2382:                        + dir_static.d_namlen - dir_static.d_namlen % 4;
                   2383:   dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
                   2384:   return &dir_static;
                   2385: }
                   2386: 
                   2387: #endif /* VMS */
                   2388: 
                   2389: #endif /* NONSYSTEM_DIR_LIBRARY */
                   2390: 
                   2391: /* Functions for VMS */
                   2392: #ifdef VMS
                   2393: #include <pwd.h>
                   2394: #include <acldef.h>
                   2395: #include <chpdef.h>
                   2396: #include <jpidef.h>
                   2397: 
                   2398: /* Return as a string the VMS error string pertaining to STATUS.
                   2399:    Reuses the same static buffer each time it is called.  */
                   2400: 
                   2401: char *
                   2402: vmserrstr (status)
                   2403:      int status;               /* VMS status code */
                   2404: {
                   2405:   int bufadr[2];
                   2406:   short len;
                   2407:   static char buf[257];
                   2408: 
                   2409:   bufadr[0] = sizeof buf - 1;
                   2410:   bufadr[1] = buf;
                   2411:   if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
                   2412:     return "untranslatable VMS error status";
                   2413:   buf[len] = '\0';
                   2414:   return buf;
                   2415: }
                   2416: 
                   2417: #ifdef access
                   2418: #undef access
                   2419:   
                   2420: /* The following is necessary because 'access' emulation by VMS C (2.0) does
                   2421:  * not work correctly.  (It also doesn't work well in version 2.3.)
                   2422:  */
                   2423: 
                   2424: #ifdef VMS4_4
                   2425: 
                   2426: #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
                   2427:        { strlen(string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
                   2428: 
                   2429: typedef union {
                   2430:     struct {
                   2431:        unsigned short s_buflen;
                   2432:        unsigned short s_code;
                   2433:        char *s_bufadr;
                   2434:        unsigned short *s_retlenadr;
                   2435:     } s;
                   2436:     int end;
                   2437: } item;
                   2438: #define buflen s.s_buflen
                   2439: #define code s.s_code
                   2440: #define bufadr s.s_bufadr
                   2441: #define retlenadr s.s_retlenadr
                   2442: 
                   2443: #define R_OK 4 /* test for read permission */
                   2444: #define W_OK 2 /* test for write permission */
                   2445: #define X_OK 1 /* test for execute (search) permission */
                   2446: #define F_OK 0 /* test for presence of file */
                   2447: 
                   2448: int
                   2449: sys_access (path, mode)
                   2450:      char *path;
                   2451:      int mode;
                   2452: {
                   2453:   static char *user = NULL;
                   2454:   char dir_fn[512];
                   2455: 
                   2456:   /* translate possible directory spec into .DIR file name, so brain-dead
                   2457:    * access() can treat the directory like a file.  */
                   2458:   if (directory_file_name (path, dir_fn))
                   2459:     path = dir_fn;
                   2460:   
                   2461:   if (mode == F_OK)
                   2462:     return access (path, mode);
                   2463:   if (user == NULL && (user = getenv ("USER")) == NULL)
                   2464:     return -1;
                   2465:   {
                   2466:        int stat;
                   2467:        int flags;
                   2468:        int acces;
                   2469:        int dummy;
                   2470:        item itemlst[3];
                   2471:        DESCRIPTOR(path_desc, path);
                   2472:        DESCRIPTOR(user_desc, user);
                   2473:  
                   2474:        flags = 0;
                   2475:        acces = 0;
                   2476:        if ((mode & X_OK) && ((stat = access(path, mode)) < 0 || mode == X_OK))
                   2477:            return stat;
                   2478:        if (mode & R_OK)
                   2479:            acces |= CHP$M_READ;
                   2480:        if (mode & W_OK)
                   2481:            acces |= CHP$M_WRITE;
                   2482:        itemlst[0].buflen = sizeof (int);
                   2483:        itemlst[0].code = CHP$_FLAGS;
                   2484:        itemlst[0].bufadr = &flags;
                   2485:        itemlst[0].retlenadr = &dummy;
                   2486:        itemlst[1].buflen = sizeof (int);
                   2487:        itemlst[1].code = CHP$_ACCESS;
                   2488:        itemlst[1].bufadr = &acces;
                   2489:        itemlst[1].retlenadr = &dummy;
                   2490:        itemlst[2].end = CHP$_END;
                   2491:        stat = SYS$CHECK_ACCESS(&ACL$C_FILE, &path_desc, &user_desc, itemlst);
                   2492:        return stat == SS$_NORMAL ? 0 : -1;
                   2493:     }
                   2494: }
                   2495: 
                   2496: #else /* not VMS4_4 */
                   2497: 
                   2498: #include <prvdef.h>
                   2499: #define        ACE$M_WRITE     2
                   2500: #define        ACE$C_KEYID     1
                   2501: 
                   2502: static unsigned short memid, grpid;
                   2503: static unsigned int uic;
                   2504: 
                   2505: /* Called from init_sys_modes, so it happens not very often
                   2506:    but at least each time Emacs is loaded.  */
                   2507: sys_access_reinit ()
                   2508: {
                   2509:   uic = 0;
                   2510: }
                   2511: 
                   2512: int
                   2513: sys_access (filename, type)
                   2514:      char * filename;
                   2515:      int type;
                   2516: {
                   2517:   struct FAB fab;
                   2518:   struct XABPRO xab;
                   2519:   int status, prvmask[2], size, i, typecode, acl_controlled;
                   2520:   unsigned int *aclptr, *aclend, aclbuf[60];
                   2521: 
                   2522:   /* Get UIC and GRP values for protection checking.  */
                   2523:   if (uic == 0)
                   2524:     {
                   2525:       status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
                   2526:       if (! (status & 1))
                   2527:        return -1;
                   2528:       memid = uic & 0xFFFF;
                   2529:       grpid = uic >> 16;
                   2530:     }
                   2531: 
                   2532:   if (type != 2)               /* not checking write access */
                   2533:     return access (filename, type);
                   2534: 
                   2535:   /* Check write protection. */
                   2536:     
                   2537: #define        CHECKPRIV(bit)    (prvmask[bit / 32] & (1 << (bit % 32)))
                   2538: #define        WRITEABLE(field)  (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
                   2539: 
                   2540:   /* Find privilege bits */
                   2541:   status = sys$setprv (0, 0, 0, prvmask);
                   2542:   if (! (status & 1))
                   2543:     error ("Unable to find privileges: %s", vmserrstr (status));
                   2544:   if (CHECKPRIV (PRV$V_BYPASS))
                   2545:     return 0;                  /* BYPASS enabled */
                   2546:   fab = cc$rms_fab;
                   2547:   fab.fab$b_fac = FAB$M_GET;
                   2548:   fab.fab$l_fna = filename;
                   2549:   fab.fab$b_fns = strlen (filename);
                   2550:   fab.fab$l_xab = &xab;
                   2551:   xab = cc$rms_xabpro;
                   2552:   xab.xab$l_aclbuf = aclbuf;
                   2553:   xab.xab$w_aclsiz = sizeof (aclbuf);
                   2554:   status = sys$open (&fab, 0, 0);
                   2555:   if (! (status & 1))
                   2556:     return -1;
                   2557:   sys$close (&fab, 0, 0);
                   2558:   /* Check system access */
                   2559:   if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
                   2560:     return 0;
                   2561:   /* Check ACL entries, if any */
                   2562:   acl_controlled = 0;
                   2563:   if (xab.xab$w_acllen > 0)
                   2564:     {
                   2565:       aclptr = aclbuf;
                   2566:       aclend = &aclbuf[xab.xab$w_acllen / 4];
                   2567:       while (*aclptr && aclptr < aclend)
                   2568:        {
                   2569:          size = (*aclptr & 0xff) / 4;
                   2570:          typecode = (*aclptr >> 8) & 0xff;
                   2571:          if (typecode == ACE$C_KEYID)
                   2572:            for (i = size - 1; i > 1; i--)
                   2573:              if (aclptr[i] == uic)
                   2574:                {
                   2575:                  acl_controlled = 1;
                   2576:                  if (aclptr[1] & ACE$M_WRITE)
                   2577:                    return 0;   /* Write access through ACL */
                   2578:                }
                   2579:          aclptr = &aclptr[size];
                   2580:        }
                   2581:       if (acl_controlled)      /* ACL specified, prohibits write access */
                   2582:        return -1;
                   2583:     }
                   2584:   /* No ACL entries specified, check normal protection */
                   2585:   if (WRITEABLE (XAB$V_WLD))   /* World writeable */
                   2586:     return 0;
                   2587:   if (WRITEABLE (XAB$V_GRP) &&
                   2588:       (unsigned short) (xab.xab$l_uic >> 16) == grpid)
                   2589:     return 0;                  /* Group writeable */
                   2590:   if (WRITEABLE (XAB$V_OWN) &&
                   2591:       (xab.xab$l_uic & 0xFFFF) == memid)
                   2592:     return 0;                  /* Owner writeable */
                   2593: 
                   2594:   return -1;   /* Not writeable */
                   2595: }
                   2596: #endif /* not VMS4_4 */
                   2597: #endif /* access */
                   2598:   
                   2599: static char vtbuf[NAM$C_MAXRSS+1];
                   2600: 
                   2601: /* translate a vms file spec to a unix path */
                   2602: char *
                   2603: sys_translate_vms (vfile)
                   2604:      char * vfile;
                   2605: {
                   2606:   char * p;
                   2607:   char * targ;
                   2608: 
                   2609:   if (!vfile)
                   2610:     return 0;
                   2611: 
                   2612:   targ = vtbuf;
                   2613: 
                   2614:   /* leading device or logical name is a root directory */
                   2615:   if (p = strchr (vfile, ':'))
                   2616:     {
                   2617:       *targ++ = '/';
                   2618:       while (vfile < p)
                   2619:        *targ++ = *vfile++;
                   2620:       vfile++;
                   2621:       *targ++ = '/';
                   2622:     }
                   2623:   p = vfile;
                   2624:   if (*p == '[' || *p == '<')
                   2625:     {
                   2626:       while (*++vfile != *p + 2)
                   2627:        switch (*vfile)
                   2628:          {
                   2629:          case '.':
                   2630:            if (vfile[-1] == *p)
                   2631:              *targ++ = '.';
                   2632:            *targ++ = '/';
                   2633:            break;
                   2634: 
                   2635:          case '-':
                   2636:            *targ++ = '.';
                   2637:            *targ++ = '.';
                   2638:            break;
                   2639:            
                   2640:          default:
                   2641:            *targ++ = *vfile;
                   2642:            break;
                   2643:          }
                   2644:       vfile++;
                   2645:       *targ++ = '/';
                   2646:     }
                   2647:   while (*vfile)
                   2648:     *targ++ = *vfile++;
                   2649: 
                   2650:   return vtbuf;
                   2651: }
                   2652: 
                   2653: static char utbuf[NAM$C_MAXRSS+1];
                   2654: 
                   2655: /* translate a unix path to a VMS file spec */
                   2656: char *
                   2657: sys_translate_unix (ufile)
                   2658:      char * ufile;
                   2659: {
                   2660:   int slash_seen = 0;
                   2661:   char *p;
                   2662:   char * targ;
                   2663: 
                   2664:   if (!ufile)
                   2665:     return 0;
                   2666: 
                   2667:   targ = utbuf;
                   2668: 
                   2669:   if (*ufile == '/')
                   2670:     {
                   2671:       ufile++;
                   2672:     }
                   2673: 
                   2674:   while (*ufile)
                   2675:     {
                   2676:       switch (*ufile)
                   2677:        {
                   2678:        case '/':
                   2679:          if (slash_seen)
                   2680:            if (index (&ufile[1], '/'))
                   2681:              *targ++ = '.';
                   2682:            else
                   2683:              *targ++ = ']';
                   2684:          else
                   2685:            {
                   2686:              *targ++ = ':';
                   2687:              if (index (&ufile[1], '/'))
                   2688:                *targ++ = '[';
                   2689:              slash_seen = 1;
                   2690:            }
                   2691:          break;
                   2692: 
                   2693:        case '.':
                   2694:          if (strncmp (ufile, "./", 2) == 0)
                   2695:            {
                   2696:              if (!slash_seen)
                   2697:                {
                   2698:                  *targ++ = '[';
                   2699:                  slash_seen = 1;
                   2700:                }
                   2701:              ufile++;          /* skip the dot */
                   2702:              if (index (&ufile[1], '/'))
                   2703:                *targ++ = '.';
                   2704:              else
                   2705:                *targ++ = ']';
                   2706:            }
                   2707:          else if (strncmp (ufile, "../", 3) == 0)
                   2708:            {
                   2709:              if (!slash_seen)
                   2710:                {
                   2711:                  *targ++ = '[';
                   2712:                  slash_seen = 1;
                   2713:                }
                   2714:              *targ++ = '-';
                   2715:              ufile += 2;       /* skip the dots */
                   2716:              if (index (&ufile[1], '/'))
                   2717:                *targ++ = '.';
                   2718:              else
                   2719:                *targ++ = ']';
                   2720:            }
                   2721:          else
                   2722:            *targ++ = *ufile;
                   2723:          break;
                   2724: 
                   2725:        default:
                   2726:          *targ++ = *ufile;
                   2727:          break;
                   2728:        }
                   2729:       ufile++;
                   2730:     }
                   2731:   *targ = '\0';
                   2732:   
                   2733:   return utbuf;
                   2734: }
                   2735: 
                   2736: char *
                   2737: getwd (pathname)
                   2738:      char *pathname;
                   2739: {
                   2740:   char *ptr;
                   2741:   strcpy (pathname, egetenv ("PATH"));
                   2742: 
                   2743:   ptr = pathname;
                   2744:   while (*ptr)
                   2745:     {
                   2746:       if ('a' <= *ptr && *ptr <= 'z')
                   2747:        *ptr -= 040;
                   2748:       ptr++;
                   2749:     }
                   2750:   return pathname;
                   2751: }
                   2752: 
                   2753: getppid ()
                   2754: {
                   2755:   long item_code = JPI$_OWNER;
                   2756:   unsigned long parent_id;
                   2757:   int status;
                   2758: 
                   2759:   if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
                   2760:     {
                   2761:       errno = EVMSERR;
                   2762:       vaxc$errno = status;
                   2763:       return -1;
                   2764:     }
                   2765:   return parent_id;
                   2766: }
                   2767: 
                   2768: #undef getuid
                   2769: unsigned
                   2770: sys_getuid ()
                   2771: {
                   2772:   return (getgid () << 16) | getuid ();
                   2773: }
                   2774: 
                   2775: int
                   2776: sys_read (fildes, buf, nbyte)
                   2777:      int fildes;
                   2778:      char *buf;
                   2779:      unsigned int nbyte;
                   2780: {
                   2781:   return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
                   2782: }
                   2783: 
                   2784: #if 0
                   2785: int
                   2786: sys_write (fildes, buf, nbyte)
                   2787:      int fildes;
                   2788:      char *buf;
                   2789:      unsigned int nbyte;
                   2790: {
                   2791:   register int nwrote, rtnval = 0;
                   2792: 
                   2793:   while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
                   2794:     nbyte -= nwrote;
                   2795:     buf += nwrote;
                   2796:     rtnval += nwrote;
                   2797:   }
                   2798:   if (nwrote < 0)
                   2799:     return rtnval ? rtnval : -1;
                   2800:   if ((nwrote = write (fildes, buf, nbyte)) < 0)
                   2801:     return rtnval ? rtnval : -1;
                   2802:   return (rtnval + nwrote);
                   2803: }
                   2804: #endif /* 0 */
                   2805: 
                   2806: /*
                   2807:  *     VAX/VMS VAX C RTL really loses. It insists that records
                   2808:  *      end with a newline (carriage return) character, and if they
                   2809:  *     don't it adds one (nice of it isn't it!)
                   2810:  *
                   2811:  *     Thus we do this stupidity below.
                   2812:  */
                   2813: 
                   2814: int
                   2815: sys_write (fildes, buf, nbytes)
                   2816:      int fildes;
                   2817:      char *buf;
                   2818:      unsigned int nbytes;
                   2819: {
                   2820:   register char *p;
                   2821:   register char *e;
                   2822:   int retval, sum;
                   2823:   p = buf;
                   2824:   sum = 0;
                   2825:   while (nbytes > 0)
                   2826:     {
                   2827:       e =  p + min (MAXIOSIZE, nbytes) - 1;
                   2828:       while (*e != '\n' && e > p) e--;
                   2829:       if (p == e)              /* Ok.. so here we add a newline... sigh. */
                   2830:        e = p + min (MAXIOSIZE, nbytes) - 1;
                   2831:       retval = write (fildes, p, e - p + 1);
                   2832:       if (retval != e - p + 1) return -1;
                   2833:       p = e + 1;
                   2834:       sum = sum + retval;
                   2835:       nbytes -= retval;
                   2836:     }
                   2837:   return sum;
                   2838: }
                   2839: 
                   2840: /* Create file NEW copying its attributes from file OLD.  If
                   2841:    OLD is 0 or does not exist, create based on the value of
                   2842:    vms_stmlf_recfm. */
                   2843: 
                   2844: int
                   2845: creat_copy_attrs (old, new)
                   2846:      char *old, *new;
                   2847: {
                   2848:   struct FAB fab = cc$rms_fab;
                   2849:   struct XABPRO xabpro;
                   2850:   char aclbuf[256];    /* Choice of size is arbitrary.  See below. */
                   2851:   extern int vms_stmlf_recfm;
                   2852: 
                   2853:   if (old)
                   2854:     {
                   2855:       fab.fab$b_fac = FAB$M_GET;
                   2856:       fab.fab$l_fna = old;
                   2857:       fab.fab$b_fns = strlen (old);
                   2858:       fab.fab$l_xab = &xabpro;
                   2859:       xabpro = cc$rms_xabpro;
                   2860:       xabpro.xab$l_aclbuf = aclbuf;
                   2861:       xabpro.xab$w_aclsiz = sizeof aclbuf;
                   2862:       /* Call $OPEN to fill in the fab & xabpro fields. */
                   2863:       if (sys$open (&fab, 0, 0) & 1)
                   2864:        {
                   2865:          sys$close (&fab, 0, 0);
                   2866:          fab.fab$l_alq = 0;    /* zero the allocation quantity */
                   2867:          if (xabpro.xab$w_acllen > 0)
                   2868:            {
                   2869:              if (xabpro.xab$w_acllen > sizeof aclbuf)
                   2870:                /* If the acl buffer was too short, redo open with longer one.
                   2871:                   Wouldn't need to do this if there were some system imposed
                   2872:                   limit on the size of an ACL, but I can't find any such. */
                   2873:                {
                   2874:                  xabpro.xab$l_aclbuf = alloca (xabpro.xab$w_acllen);
                   2875:                  xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
                   2876:                  if (sys$open (&fab, 0, 0) & 1)
                   2877:                    sys$close (&fab, 0, 0);
                   2878:                  else
                   2879:                    old = 0;
                   2880:                }
                   2881:            }
                   2882:          else
                   2883:            xabpro.xab$l_aclbuf = 0;
                   2884:        }
                   2885:       else
                   2886:        old = 0;
                   2887:     }
                   2888:   fab.fab$l_fna = new;
                   2889:   fab.fab$b_fns = strlen (new);
                   2890:   if (!old)
                   2891:     {
                   2892:       fab.fab$l_xab = 0;
                   2893:       fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
                   2894:       fab.fab$b_rat = FAB$M_CR;
                   2895:     }
                   2896:   /* Create the new file with either default attrs or attrs copied
                   2897:      from old file. */
                   2898:   if (!(SYS$CREATE (&fab, 0, 0) & 1))
                   2899:     return -1;
                   2900:   sys$close (&fab, 0, 0);
                   2901:   /* As this is a "replacement" for creat, return a file descriptor
                   2902:      opened for writing. */
                   2903:   return open (new, O_WRONLY);
                   2904: }
                   2905: 
                   2906: #ifdef creat
                   2907: #undef creat
                   2908: #include <varargs.h>
                   2909: 
                   2910: sys_creat (va_alist)
                   2911:      va_dcl
                   2912: {
                   2913:   va_list list_incrementor;
                   2914:   char *name;
                   2915:   int mode;
                   2916:   int rfd;                     /* related file descriptor */
                   2917:   int fd;                      /* Our new file descriptor */
                   2918:   int count;
                   2919:   struct stat st_buf;
                   2920:   char rfm[12];
                   2921:   char rat[15];
                   2922:   char mrs[13];
                   2923:   char fsz[13];
                   2924:   extern int vms_stmlf_recfm;
                   2925: 
                   2926:   va_count (count);
                   2927:   va_start (list_incrementor);
                   2928:   name = va_arg (list_incrementor, char *);
                   2929:   mode = va_arg (list_incrementor, int);
                   2930:   if (count > 2)
                   2931:     rfd = va_arg (list_incrementor, int);
                   2932:   va_end (list_incrementor);
                   2933:   if (count > 2)
                   2934:     {
                   2935:       /* Use information from the related file descriptor to set record
                   2936:         format of the newly created file. */
                   2937:       fstat (rfd, &st_buf);
                   2938:       switch (st_buf.st_fab_rfm)
                   2939:        {
                   2940:        case FAB$C_FIX:
                   2941:          strcpy (rfm, "rfm = fix");
                   2942:          sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
                   2943:          strcpy (rat, "rat = ");
                   2944:          if (st_buf.st_fab_rat & FAB$M_CR)
                   2945:            strcat (rat, "cr");
                   2946:          else if (st_buf.st_fab_rat & FAB$M_FTN)
                   2947:            strcat (rat, "ftn");
                   2948:          else if (st_buf.st_fab_rat & FAB$M_PRN)
                   2949:            strcat (rat, "prn");
                   2950:          if (st_buf.st_fab_rat & FAB$M_BLK)
                   2951:            if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
                   2952:              strcat (rat, ", blk");
                   2953:            else
                   2954:              strcat (rat, "blk");
                   2955:          return creat (name, 0, rfm, rat, mrs);
                   2956: 
                   2957:        case FAB$C_VFC:
                   2958:          strcpy (rfm, "rfm = vfc");
                   2959:          sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
                   2960:          strcpy (rat, "rat = ");
                   2961:          if (st_buf.st_fab_rat & FAB$M_CR)
                   2962:            strcat (rat, "cr");
                   2963:          else if (st_buf.st_fab_rat & FAB$M_FTN)
                   2964:            strcat (rat, "ftn");
                   2965:          else if (st_buf.st_fab_rat & FAB$M_PRN)
                   2966:            strcat (rat, "prn");
                   2967:          if (st_buf.st_fab_rat & FAB$M_BLK)
                   2968:            if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
                   2969:              strcat (rat, ", blk");
                   2970:            else
                   2971:              strcat (rat, "blk");
                   2972:          return creat (name, 0, rfm, rat, fsz);
                   2973: 
                   2974:        case FAB$C_STM:
                   2975:          strcpy (rfm, "rfm = stm");
                   2976:          break;
                   2977: 
                   2978:        case FAB$C_STMCR:
                   2979:          strcpy (rfm, "rfm = stmcr");
                   2980:          break;
                   2981: 
                   2982:        case FAB$C_STMLF:
                   2983:          strcpy (rfm, "rfm = stmlf");
                   2984:          break;
                   2985: 
                   2986:        case FAB$C_UDF:
                   2987:          strcpy (rfm, "rfm = udf");
                   2988:          break;
                   2989: 
                   2990:        case FAB$C_VAR:
                   2991:          strcpy (rfm, "rfm = var");
                   2992:          break;
                   2993:        }
                   2994:       strcpy (rat, "rat = ");
                   2995:       if (st_buf.st_fab_rat & FAB$M_CR)
                   2996:        strcat (rat, "cr");
                   2997:       else if (st_buf.st_fab_rat & FAB$M_FTN)
                   2998:        strcat (rat, "ftn");
                   2999:       else if (st_buf.st_fab_rat & FAB$M_PRN)
                   3000:        strcat (rat, "prn");
                   3001:       if (st_buf.st_fab_rat & FAB$M_BLK)
                   3002:        if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
                   3003:          strcat (rat, ", blk");
                   3004:        else
                   3005:          strcat (rat, "blk");
                   3006:     }
                   3007:   else
                   3008:     {
                   3009:       strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
                   3010:       strcpy (rat, "rat=cr");
                   3011:     }
                   3012:   /* Until the VAX C RTL fixes the many bugs with modes, always use
                   3013:      mode 0 to get the user's default protection. */
                   3014:   fd = creat (name, 0, rfm, rat);
                   3015:   if (fd < 0 && errno == EEXIST)
                   3016:     {
                   3017:       if (unlink (name) < 0)
                   3018:        report_file_error ("delete", build_string (name));
                   3019:       fd = creat (name, 0, rfm, rat);
                   3020:     }
                   3021:   return fd;
                   3022: }
                   3023: #endif /* creat */
                   3024: 
                   3025: /* fwrite to stdout is S L O W.  Speed it up by using fputc...*/
                   3026: sys_fwrite (ptr, size, num, fp)
                   3027:      register char * ptr;
                   3028:      FILE * fp;
                   3029: {
                   3030:   register int tot = num * size;
                   3031: 
                   3032:   while (tot--)
                   3033:     fputc (*ptr++, fp);
                   3034: }
                   3035: 
                   3036: /*
                   3037:  * The VMS C library routine creat() actually creates a new version of an
                   3038:  * existing file rather than truncating the old version.  There are times
                   3039:  * when this is not the desired behavior, for instance, when writing an
                   3040:  * auto save file (you only want one version), or when you don't have
                   3041:  * write permission in the directory containing the file (but the file
                   3042:  * itself is writable).  Hence this routine, which is equivalent to 
                   3043:  * "close (creat (fn, 0));" on Unix if fn already exists.
                   3044:  */
                   3045: int
                   3046: vms_truncate (fn)
                   3047:      char *fn;
                   3048: {
                   3049:   struct FAB xfab = cc$rms_fab;
                   3050:   struct RAB xrab = cc$rms_rab;
                   3051:   int status;
                   3052: 
                   3053:   xfab.fab$l_fop = FAB$M_TEF;  /* free allocated but unused blocks on close */
                   3054:   xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
                   3055:   xfab.fab$b_shr = FAB$M_NIL;  /* allow no sharing - file must be locked */
                   3056:   xfab.fab$l_fna = fn;
                   3057:   xfab.fab$b_fns = strlen (fn);
                   3058:   xfab.fab$l_dna = ";0";       /* default to latest version of the file */
                   3059:   xfab.fab$b_dns = 2;
                   3060:   xrab.rab$l_fab = &xfab;
                   3061: 
                   3062:   /* This gibberish opens the file, positions to the first record, and
                   3063:      deletes all records from there until the end of file. */
                   3064:   if ((sys$open (&xfab) & 01) == 01)
                   3065:     {
                   3066:       if ((sys$connect (&xrab) & 01) == 01 &&
                   3067:          (sys$find (&xrab) & 01) == 01 &&
                   3068:          (sys$truncate (&xrab) & 01) == 01)
                   3069:        status = 0;
                   3070:       else
                   3071:        status = -1;
                   3072:     }
                   3073:   else
                   3074:     status = -1;
                   3075:   sys$close (&xfab);
                   3076:   return status;
                   3077: }
                   3078: 
                   3079: /* Define this symbol to actually read SYSUAF.DAT.  This requires either
                   3080:    SYSPRV or a readable SYSUAF.DAT. */
                   3081: 
                   3082: #ifdef READ_SYSUAF
                   3083: /*
                   3084:  * getuaf.c
                   3085:  *
                   3086:  * Routine to read the VMS User Authorization File and return
                   3087:  * a specific user's record.
                   3088:  */
                   3089: 
                   3090: static struct UAF retuaf;
                   3091: 
                   3092: struct UAF *
                   3093: get_uaf_name(uname)
                   3094:      char * uname;
                   3095: {
                   3096:   register status;
                   3097:   struct FAB uaf_fab;
                   3098:   struct RAB uaf_rab;
                   3099:   
                   3100:   uaf_fab = cc$rms_fab;
                   3101:   uaf_rab = cc$rms_rab;
                   3102:   /* initialize fab fields */
                   3103:   uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
                   3104:   uaf_fab.fab$b_fns = 21;
                   3105:   uaf_fab.fab$b_fac = FAB$M_GET;
                   3106:   uaf_fab.fab$b_org = FAB$C_IDX;
                   3107:   uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
                   3108:   /* initialize rab fields */
                   3109:   uaf_rab.rab$l_fab = &uaf_fab;
                   3110:   /* open the User Authorization File */
                   3111:   status = sys$open(&uaf_fab);
                   3112:   if (!(status&1))
                   3113:     {
                   3114:       errno = EVMSERR;
                   3115:       vaxc$errno = status;
                   3116:       return 0;
                   3117:     }
                   3118:   status = sys$connect(&uaf_rab);
                   3119:   if (!(status&1))
                   3120:     {
                   3121:       errno = EVMSERR;
                   3122:       vaxc$errno = status;
                   3123:       return 0;
                   3124:     }
                   3125:   /* read the requested record - index is in uname */
                   3126:   uaf_rab.rab$l_kbf = uname;
                   3127:   uaf_rab.rab$b_ksz = strlen (uname);
                   3128:   uaf_rab.rab$b_rac = RAB$C_KEY;
                   3129:   uaf_rab.rab$l_ubf = (char *)&retuaf;
                   3130:   uaf_rab.rab$w_usz = sizeof retuaf;
                   3131:   status = sys$get(&uaf_rab);
                   3132:   if (!(status&1))
                   3133:     {
                   3134:       errno = EVMSERR;
                   3135:       vaxc$errno = status;
                   3136:       return 0;
                   3137:     }
                   3138:   /* close the User Authorization File */
                   3139:   status = sys$disconnect(&uaf_rab);
                   3140:   if (!(status&1))
                   3141:     {
                   3142:       errno = EVMSERR;
                   3143:       vaxc$errno = status;
                   3144:       return 0;
                   3145:     }
                   3146:   status = sys$close(&uaf_fab);
                   3147:   if (!(status&1))
                   3148:     {
                   3149:       errno = EVMSERR;
                   3150:       vaxc$errno = status;
                   3151:       return 0;
                   3152:     }
                   3153:   return &retuaf;
                   3154: }
                   3155: 
                   3156: struct UAF *
                   3157: get_uaf_uic(uic)
                   3158:      unsigned long uic;
                   3159: {
                   3160:   register status;
                   3161:   struct FAB uaf_fab;
                   3162:   struct RAB uaf_rab;
                   3163:   
                   3164:   uaf_fab = cc$rms_fab;
                   3165:   uaf_rab = cc$rms_rab;
                   3166:   /* initialize fab fields */
                   3167:   uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
                   3168:   uaf_fab.fab$b_fns = 21;
                   3169:   uaf_fab.fab$b_fac = FAB$M_GET;
                   3170:   uaf_fab.fab$b_org = FAB$C_IDX;
                   3171:   uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
                   3172:   /* initialize rab fields */
                   3173:   uaf_rab.rab$l_fab = &uaf_fab;
                   3174:   /* open the User Authorization File */
                   3175:   status = sys$open(&uaf_fab);
                   3176:   if (!(status&1))
                   3177:     {
                   3178:       errno = EVMSERR;
                   3179:       vaxc$errno = status;
                   3180:       return 0;
                   3181:     }
                   3182:   status = sys$connect(&uaf_rab);
                   3183:   if (!(status&1))
                   3184:     {
                   3185:       errno = EVMSERR;
                   3186:       vaxc$errno = status;
                   3187:       return 0;
                   3188:     }
                   3189:   /* read the requested record - index is in uic */
                   3190:   uaf_rab.rab$b_krf = 1;       /* 1st alternate key */
                   3191:   uaf_rab.rab$l_kbf = (char *) &uic;
                   3192:   uaf_rab.rab$b_ksz = sizeof uic;
                   3193:   uaf_rab.rab$b_rac = RAB$C_KEY;
                   3194:   uaf_rab.rab$l_ubf = (char *)&retuaf;
                   3195:   uaf_rab.rab$w_usz = sizeof retuaf;
                   3196:   status = sys$get(&uaf_rab);
                   3197:   if (!(status&1))
                   3198:     {
                   3199:       errno = EVMSERR;
                   3200:       vaxc$errno = status;
                   3201:       return 0;
                   3202:     }
                   3203:   /* close the User Authorization File */
                   3204:   status = sys$disconnect(&uaf_rab);
                   3205:   if (!(status&1))
                   3206:     {
                   3207:       errno = EVMSERR;
                   3208:       vaxc$errno = status;
                   3209:       return 0;
                   3210:     }
                   3211:   status = sys$close(&uaf_fab);
                   3212:   if (!(status&1))
                   3213:     {
                   3214:       errno = EVMSERR;
                   3215:       vaxc$errno = status;
                   3216:       return 0;
                   3217:     }
                   3218:   return &retuaf;
                   3219: }
                   3220: 
                   3221: static struct passwd retpw;
                   3222: 
                   3223: struct passwd *
                   3224: cnv_uaf_pw (up)
                   3225:      struct UAF * up;
                   3226: {
                   3227:   char * ptr;
                   3228: 
                   3229:   /* copy these out first because if the username is 32 chars, the next
                   3230:      section will overwrite the first byte of the UIC */
                   3231:   retpw.pw_uid = up->uaf$w_mem;
                   3232:   retpw.pw_gid = up->uaf$w_grp;
                   3233: 
                   3234:   /* I suppose this is not the best sytle, to possibly overwrite one
                   3235:      byte beyond the end of the field, but what the heck... */
                   3236:   ptr = &up->uaf$t_username[UAF$S_USERNAME];
                   3237:   while (ptr[-1] == ' ')
                   3238:     ptr--;
                   3239:   *ptr = '\0';
                   3240:   strcpy (retpw.pw_name, up->uaf$t_username);
                   3241: 
                   3242:   /* the rest of these are counted ascii strings */
                   3243:   strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
                   3244:   retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
                   3245:   strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
                   3246:   retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
                   3247:   strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
                   3248:   retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
                   3249:   strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
                   3250:   retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
                   3251: 
                   3252:   return &retpw;
                   3253: }
                   3254: #else /* not READ_SYSUAF */
                   3255: static struct passwd retpw;
                   3256: #endif /* not READ_SYSUAF */
                   3257: 
                   3258: struct passwd *
                   3259: getpwnam (name)
                   3260:      char * name;
                   3261: {
                   3262: #ifdef READ_SYSUAF
                   3263:   struct UAF *up;
                   3264: #else
                   3265:   char * user;
                   3266:   char * dir;
                   3267:   char * full;
                   3268: #endif /* READ_SYSUAF */
                   3269:   char *ptr = name;
                   3270: 
                   3271:   while (*ptr)
                   3272:     {
                   3273:       if ('a' <= *ptr && *ptr <= 'z')
                   3274:        *ptr -= 040;
                   3275:       ptr++;
                   3276:     }
                   3277: #ifdef READ_SYSUAF
                   3278:   if (!(up = get_uaf_name (name)))
                   3279:     return 0;
                   3280:   return cnv_uaf_pw (up);
                   3281: #else
                   3282:   if (strcmp (name, getenv ("USER")) == 0)
                   3283:     {
                   3284:       retpw.pw_uid = getuid ();
                   3285:       retpw.pw_gid = getgid ();
                   3286:       strcpy (retpw.pw_name, name);
                   3287:       if (full = egetenv ("FULLNAME"))
                   3288:        strcpy (retpw.pw_gecos, full);
                   3289:       else
                   3290:        *retpw.pw_gecos = '\0';
                   3291:       strcpy (retpw.pw_dir, egetenv ("HOME"));
                   3292:       *retpw.pw_shell = '\0';
                   3293:       return &retpw;
                   3294:     }
                   3295:   else
                   3296:     return 0;
                   3297: #endif /* not READ_SYSUAF */
                   3298: }
                   3299: 
                   3300: struct passwd *
                   3301: getpwuid (uid)
                   3302:      unsigned long uid;
                   3303: {
                   3304: #ifdef READ_SYSUAF
                   3305:   struct UAF * up;
                   3306: 
                   3307:   if (!(up = get_uaf_uic (uid)))
                   3308:     return 0;
                   3309:   return cnv_uaf_pw (up);
                   3310: #else
                   3311:   if (uid == sys_getuid ())
                   3312:     return getpwnam (egetenv ("USER"));
                   3313:   else
                   3314:     return 0;
                   3315: #endif /* not READ_SYSUAF */
                   3316: }
                   3317: 
                   3318: /* return total address space available to the current process.  This is
                   3319:    the sum of the current p0 size, p1 size and free page table entries
                   3320:    available. */
                   3321: vlimit ()
                   3322: {
                   3323:   int item_code;
                   3324:   unsigned long free_pages;
                   3325:   unsigned long frep0va;
                   3326:   unsigned long frep1va;
                   3327:   register status;
                   3328: 
                   3329:   item_code = JPI$_FREPTECNT;
                   3330:   if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
                   3331:     {
                   3332:       errno = EVMSERR;
                   3333:       vaxc$errno = status;
                   3334:       return -1;
                   3335:     }
                   3336:   free_pages *= 512;
                   3337: 
                   3338:   item_code = JPI$_FREP0VA;
                   3339:   if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
                   3340:     {
                   3341:       errno = EVMSERR;
                   3342:       vaxc$errno = status;
                   3343:       return -1;
                   3344:     }
                   3345:   item_code = JPI$_FREP1VA;
                   3346:   if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
                   3347:     {
                   3348:       errno = EVMSERR;
                   3349:       vaxc$errno = status;
                   3350:       return -1;
                   3351:     }
                   3352: 
                   3353:   return free_pages + frep0va + (0x7fffffff - frep1va);
                   3354: }
                   3355: 
                   3356: define_logical_name (varname, string)
                   3357:      char *varname;
                   3358:      char *string;
                   3359: {
                   3360:   struct dsc$descriptor_s strdsc =
                   3361:     {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
                   3362:   struct dsc$descriptor_s envdsc =
                   3363:     {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
                   3364:   struct dsc$descriptor_s lnmdsc =
                   3365:     {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
                   3366: 
                   3367:   return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
                   3368: }
                   3369: 
                   3370: delete_logical_name (varname)
                   3371:      char *varname;
                   3372: {
                   3373:   struct dsc$descriptor_s envdsc =
                   3374:     {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
                   3375:   struct dsc$descriptor_s lnmdsc =
                   3376:     {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
                   3377: 
                   3378:   return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
                   3379: }
                   3380: 
                   3381: ulimit()
                   3382: {}
                   3383: 
                   3384: setpriority()
                   3385: {}
                   3386: 
                   3387: setpgrp()
                   3388: {}
                   3389: 
                   3390: execvp()
                   3391: {
                   3392:   error ("execvp system call not implemented");
                   3393: }
                   3394: 
                   3395: int
                   3396: rename (from, to)
                   3397:      char *from, *to;
                   3398: {
                   3399:   int status;
                   3400:   struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
                   3401:   struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
                   3402:   char from_esn[NAM$C_MAXRSS];
                   3403:   char to_esn[NAM$C_MAXRSS];
                   3404: 
                   3405:   from_fab.fab$l_fna = from;
                   3406:   from_fab.fab$b_fns = strlen (from);
                   3407:   from_fab.fab$l_nam = &from_nam;
                   3408:   from_fab.fab$l_fop = FAB$M_NAM;
                   3409: 
                   3410:   from_nam.nam$l_esa = from_esn;
                   3411:   from_nam.nam$b_ess = sizeof from_esn;
                   3412: 
                   3413:   to_fab.fab$l_fna = to;
                   3414:   to_fab.fab$b_fns = strlen (to);
                   3415:   to_fab.fab$l_nam = &to_nam;
                   3416:   to_fab.fab$l_fop = FAB$M_NAM;
                   3417: 
                   3418:   to_nam.nam$l_esa = to_esn;
                   3419:   to_nam.nam$b_ess = sizeof to_esn;
                   3420: 
                   3421:   status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
                   3422: 
                   3423:   if (status & 1)
                   3424:     return 0;
                   3425:   else
                   3426:     {
                   3427:       if (status == RMS$_DEV)
                   3428:        errno = EXDEV;
                   3429:       else
                   3430:        errno = EVMSERR;
                   3431:       vaxc$errno = status;
                   3432:       return -1;
                   3433:     }
                   3434: }
                   3435: 
                   3436: link (file, new)
                   3437:      char * file, * new;
                   3438: {
                   3439:   register status;
                   3440:   struct FAB fab;
                   3441:   struct NAM nam;
                   3442:   unsigned short fid[3];
                   3443:   char esa[NAM$C_MAXRSS];
                   3444: 
                   3445:   fab = cc$rms_fab;
                   3446:   fab.fab$l_fop = FAB$M_OFP;
                   3447:   fab.fab$l_fna = file;
                   3448:   fab.fab$b_fns = strlen (file);
                   3449:   fab.fab$l_nam = &nam;
                   3450: 
                   3451:   nam = cc$rms_nam;
                   3452:   nam.nam$l_esa = esa;
                   3453:   nam.nam$b_ess = NAM$C_MAXRSS;
                   3454: 
                   3455:   status = SYS$PARSE (&fab);
                   3456:   if ((status & 1) == 0)
                   3457:     {
                   3458:       errno = EVMSERR;
                   3459:       vaxc$errno = status;
                   3460:       return -1;
                   3461:     }
                   3462:   status = SYS$SEARCH (&fab);
                   3463:   if ((status & 1) == 0)
                   3464:     {
                   3465:       errno = EVMSERR;
                   3466:       vaxc$errno = status;
                   3467:       return -1;
                   3468:     }
                   3469: 
                   3470:   fid[0] = nam.nam$w_fid[0];
                   3471:   fid[1] = nam.nam$w_fid[1];
                   3472:   fid[2] = nam.nam$w_fid[2];
                   3473: 
                   3474:   fab.fab$l_fna = new;
                   3475:   fab.fab$b_fns = strlen (new);
                   3476: 
                   3477:   status = SYS$PARSE (&fab);
                   3478:   if ((status & 1) == 0)
                   3479:     {
                   3480:       errno = EVMSERR;
                   3481:       vaxc$errno = status;
                   3482:       return -1;
                   3483:     }
                   3484: 
                   3485:   nam.nam$w_fid[0] = fid[0];
                   3486:   nam.nam$w_fid[1] = fid[1];
                   3487:   nam.nam$w_fid[2] = fid[2];
                   3488: 
                   3489:   nam.nam$l_esa = nam.nam$l_name;
                   3490:   nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
                   3491: 
                   3492:   status = SYS$ENTER (&fab);
                   3493:   if ((status & 1) == 0)
                   3494:     {
                   3495:       errno = EVMSERR;
                   3496:       vaxc$errno = status;
                   3497:       return -1;
                   3498:     }
                   3499: 
                   3500:   return 0;
                   3501: }
                   3502: 
                   3503: croak (badfunc)
                   3504:      char *badfunc;
                   3505: {
                   3506:   printf ("%s not yet implemented\r\n", badfunc);
                   3507:   reset_sys_modes ();
                   3508:   exit (1);
                   3509: }
                   3510: 
                   3511: long
                   3512: random ()
                   3513: {
                   3514:   /* Arrange to return a range centered on zero.  */
                   3515:   return rand () - (1 << 30);
                   3516: }
                   3517: 
                   3518: srandom (seed)
                   3519: {
                   3520:   srand (seed);
                   3521: }
                   3522: #endif /* VMS */
                   3523: 
                   3524: #ifdef AIX
                   3525: 
                   3526: /* Get files for keyboard remapping */
                   3527: #define HFNKEYS 2
                   3528: #include <sys/hft.h>
                   3529: #include <sys/devinfo.h>
                   3530: 
                   3531: /* Called from init_sys_modes.  */
                   3532: hft_init ()
                   3533: {
                   3534:   /* On AIX the default hft keyboard mapping uses backspace rather than delete
                   3535:      as the rubout key's ASCII code.  Here this is changed.  The bug is that
                   3536:      there's no way to determine the old mapping, so in reset_sys_modes
                   3537:      we need to assume that the normal map had been present.  Of course, this
                   3538:      code also doesn't help if on a terminal emulator which doesn't understand
                   3539:      HFT VTD's. */
                   3540:   {
                   3541:     struct hfbuf buf;
                   3542:     struct hfkeymap keymap;
                   3543: 
                   3544:     buf.hf_bufp = (char *)&keymap;
                   3545:     buf.hf_buflen = sizeof (keymap);
                   3546:     keymap.hf_nkeys = 2;
                   3547:     keymap.hfkey[0].hf_kpos = 15;
                   3548:     keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
                   3549:     keymap.hfkey[0].hf_page = '<';
                   3550:     keymap.hfkey[0].hf_char = 127;
                   3551:     keymap.hfkey[1].hf_kpos = 15;
                   3552:     keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
                   3553:     keymap.hfkey[1].hf_page = '<';
                   3554:     keymap.hfkey[1].hf_char = 127;
                   3555:     hftctl (0, HFSKBD, &buf);
                   3556:   }
                   3557:   /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
                   3558:      at times.  Here we determine if we are on an HFT by trying to get an
                   3559:      HFT error code.  If this call works, we must be on an HFT. */
                   3560:   if (ioctl (0, HFQEIO, 0) != -1)
                   3561:     line_ins_del_ok = char_ins_del_ok = 0;
                   3562: }
                   3563: 
                   3564: /* Reset the rubout key to backspace. */
                   3565: 
                   3566: hft_reset ()
                   3567: {
                   3568:   struct hfbuf buf;
                   3569:   struct hfkeymap keymap;
                   3570: 
                   3571:   buf.hf_bufp = (char *)&keymap;
                   3572:   buf.hf_buflen = sizeof(keymap);
                   3573:   keymap.hf_nkeys = 2;
                   3574:   keymap.hfkey[0].hf_kpos = 15;
                   3575:   keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
                   3576:   keymap.hfkey[0].hf_page = '<';
                   3577:   keymap.hfkey[0].hf_char = 8;
                   3578:   keymap.hfkey[1].hf_kpos = 15;
                   3579:   keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
                   3580:   keymap.hfkey[1].hf_page = '<';
                   3581:   keymap.hfkey[1].hf_char = 8;
                   3582:   hftctl (0, HFSKBD, &buf);
                   3583: }
                   3584: 
                   3585: #endif /* AIX */

unix.superglobalmegacorp.com

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