home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / emacs-15.0.3 / src / sysdep.c-orig < prev    next >
Text File  |  1990-07-19  |  82KB  |  3,556 lines

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