1/* Interfaces to system-dependent kernel and library entries.
2   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
3                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING.  If not, write to
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.  */
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
26#include <signal.h>
27#include <stdio.h>
28#include <setjmp.h>
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
32#include "lisp.h"
33/* Including stdlib.h isn't necessarily enough to get srandom
34   declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2.  */
35#ifdef HAVE_RANDOM
36#if 0 /* It turns out that defining _OSF_SOURCE in osf5-0.h gets
37	 random prototyped as returning `int'.  It looks to me as
38	 though the best way to DTRT is to prefer the rand48 functions
39	 (per libc.info).  -- fx */
40extern long int random P_ ((void));
41#endif
42#if 0 /* Don't prototype srandom; it takes an unsigned argument on
43	 some systems, and an unsigned long on others, like FreeBSD
44	 4.1.  */
45extern void srandom P_ ((unsigned int));
46#endif
47#endif
48
49#include "blockinput.h"
50
51#ifdef MAC_OS8
52#include <sys/param.h>
53
54#ifndef subprocesses
55/* Nonzero means delete a process right away if it exits (process.c).  */
56static int delete_exited_processes;
57#endif
58#endif  /* MAC_OS8 */
59
60#ifdef WINDOWSNT
61#define read sys_read
62#define write sys_write
63#include <windows.h>
64#ifndef NULL
65#define NULL 0
66#endif
67#endif /* not WINDOWSNT */
68
69/* Does anyone other than VMS need this? */
70#ifndef fwrite
71#define sys_fwrite fwrite
72#else
73#undef fwrite
74#endif
75
76#include <sys/types.h>
77#include <sys/stat.h>
78#include <errno.h>
79
80#ifdef HAVE_SETPGID
81#if !defined (USG) || defined (BSD_PGRPS)
82#undef setpgrp
83#define setpgrp setpgid
84#endif
85#endif
86
87/* Get SI_SRPC_DOMAIN, if it is available.  */
88#ifdef HAVE_SYS_SYSTEMINFO_H
89#include <sys/systeminfo.h>
90#endif
91
92#ifdef MSDOS	/* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
93#include <dos.h>
94#include "dosfns.h"
95#include "msdos.h"
96#include <sys/param.h>
97
98#if __DJGPP__ > 1
99extern int etext;
100extern unsigned start __asm__ ("start");
101#endif
102#endif
103
104#ifndef USE_CRT_DLL
105#ifndef errno
106extern int errno;
107#endif
108#endif
109
110#ifdef VMS
111#include <rms.h>
112#include <ttdef.h>
113#include <tt2def.h>
114#include <iodef.h>
115#include <ssdef.h>
116#include <descrip.h>
117#include <fibdef.h>
118#include <atrdef.h>
119#include <ctype.h>
120#include <string.h>
121#ifdef __GNUC__
122#include <sys/file.h>
123#else
124#include <file.h>
125#endif
126#undef F_SETFL
127#ifndef RAB$C_BID
128#include <rab.h>
129#endif
130#define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
131#endif /* VMS */
132
133#ifndef VMS
134#include <sys/file.h>
135#endif /* not VMS */
136
137#ifdef HAVE_FCNTL_H
138#include <fcntl.h>
139#endif
140
141#ifndef MSDOS
142#include <sys/ioctl.h>
143#endif
144
145#include "systty.h"
146#include "syswait.h"
147
148#ifdef BROKEN_TIOCGWINSZ
149#undef TIOCGWINSZ
150#undef TIOCSWINSZ
151#endif
152
153#if defined (USG) || defined (DGUX)
154#include <sys/utsname.h>
155#ifndef MEMORY_IN_STRING_H
156#include <memory.h>
157#endif
158#if defined (TIOCGWINSZ) || defined (ISC4_0)
159#ifdef NEED_SIOCTL
160#include <sys/sioctl.h>
161#endif
162#ifdef NEED_PTEM_H
163#include <sys/stream.h>
164#include <sys/ptem.h>
165#endif
166#endif /* TIOCGWINSZ or ISC4_0 */
167#endif /* USG or DGUX */
168
169extern int quit_char;
170
171#include "keyboard.h"
172#include "frame.h"
173#include "window.h"
174#include "termhooks.h"
175#include "termchar.h"
176#include "termopts.h"
177#include "dispextern.h"
178#include "process.h"
179
180#ifdef WINDOWSNT
181#include <direct.h>
182/* In process.h which conflicts with the local copy.  */
183#define _P_WAIT 0
184int _CRTAPI1 _spawnlp (int, const char *, const char *, ...);
185int _CRTAPI1 _getpid (void);
186extern char *getwd (char *);
187#endif
188
189#ifdef NONSYSTEM_DIR_LIBRARY
190#include "ndir.h"
191#endif /* NONSYSTEM_DIR_LIBRARY */
192
193#include "syssignal.h"
194#include "systime.h"
195#ifdef HAVE_UTIME_H
196#include <utime.h>
197#endif
198
199#ifndef HAVE_UTIMES
200#ifndef HAVE_STRUCT_UTIMBUF
201/* We want to use utime rather than utimes, but we couldn't find the
202   structure declaration.  We'll use the traditional one.  */
203struct utimbuf {
204  long actime;
205  long modtime;
206};
207#endif
208#endif
209
210/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
211#ifndef LPASS8
212#define LPASS8 0
213#endif
214
215#ifdef BSD4_1
216#define LNOFLSH 0100000
217#endif
218
219static int baud_convert[] =
220#ifdef BAUD_CONVERT
221  BAUD_CONVERT;
222#else
223  {
224    0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
225    1800, 2400, 4800, 9600, 19200, 38400
226  };
227#endif
228
229#ifdef HAVE_SPEED_T
230#include <termios.h>
231#else
232#if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
233#else
234#if defined (HAVE_TERMIOS_H) && defined (GNU_LINUX)
235#include <termios.h>
236#endif
237#endif
238#endif
239
240int emacs_ospeed;
241
242/* The file descriptor for Emacs's input terminal.
243   Under Unix, this is normally zero except when using X;
244   under VMS, we place the input channel number here.  */
245int input_fd;
246
247void croak P_ ((char *)) NO_RETURN;
248
249#ifdef AIXHFT
250void hft_init ();
251void hft_reset ();
252#endif
253
254/* Temporary used by `sigblock' when defined in terms of signprocmask.  */
255
256SIGMASKTYPE sigprocmask_set;
257
258
259#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
260
261/* Return the current working directory.  Returns NULL on errors.
262   Any other returned value must be freed with free. This is used
263   only when get_current_dir_name is not defined on the system.  */
264char*
265get_current_dir_name ()
266{
267  char *buf;
268  char *pwd;
269  struct stat dotstat, pwdstat;
270  /* If PWD is accurate, use it instead of calling getwd.  PWD is
271     sometimes a nicer name, and using it may avoid a fatal error if a
272     parent directory is searchable but not readable.  */
273    if ((pwd = getenv ("PWD")) != 0
274      && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
275      && stat (pwd, &pwdstat) == 0
276      && stat (".", &dotstat) == 0
277      && dotstat.st_ino == pwdstat.st_ino
278      && dotstat.st_dev == pwdstat.st_dev
279#ifdef MAXPATHLEN
280      && strlen (pwd) < MAXPATHLEN
281#endif
282      )
283    {
284      buf = (char *) malloc (strlen (pwd) + 1);
285      if (!buf)
286        return NULL;
287      strcpy (buf, pwd);
288    }
289#ifdef HAVE_GETCWD
290  else
291    {
292      size_t buf_size = 1024;
293      buf = (char *) malloc (buf_size);
294      if (!buf)
295        return NULL;
296      for (;;)
297        {
298          if (getcwd (buf, buf_size) == buf)
299            break;
300          if (errno != ERANGE)
301            {
302              int tmp_errno = errno;
303              free (buf);
304              errno = tmp_errno;
305              return NULL;
306            }
307          buf_size *= 2;
308          buf = (char *) realloc (buf, buf_size);
309          if (!buf)
310            return NULL;
311        }
312    }
313#else
314  else
315    {
316      /* We need MAXPATHLEN here.  */
317      buf = (char *) malloc (MAXPATHLEN + 1);
318      if (!buf)
319        return NULL;
320      if (getwd (buf) == NULL)
321        {
322          int tmp_errno = errno;
323          free (buf);
324          errno = tmp_errno;
325          return NULL;
326        }
327    }
328#endif
329  return buf;
330}
331#endif
332
333
334/* Specify a different file descriptor for further input operations.  */
335
336void
337change_input_fd (fd)
338     int fd;
339{
340  input_fd = fd;
341}
342
343/* Discard pending input on descriptor input_fd.  */
344
345void
346discard_tty_input ()
347{
348#ifndef WINDOWSNT
349  struct emacs_tty buf;
350
351  if (noninteractive)
352    return;
353
354  /* Discarding input is not safe when the input could contain
355     replies from the X server.  So don't do it.  */
356  if (read_socket_hook)
357    return;
358
359#ifdef VMS
360  end_kbd_input ();
361  SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
362	    &buf.main, 0, 0, terminator_mask, 0, 0);
363  queue_kbd_input ();
364#else /* not VMS */
365#ifdef APOLLO
366  {
367    int zero = 0;
368    ioctl (input_fd, TIOCFLUSH, &zero);
369  }
370#else /* not Apollo */
371#ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
372  while (dos_keyread () != -1)
373    ;
374#else /* not MSDOS */
375  EMACS_GET_TTY (input_fd, &buf);
376  EMACS_SET_TTY (input_fd, &buf, 0);
377#endif /* not MSDOS */
378#endif /* not Apollo */
379#endif /* not VMS */
380#endif /* not WINDOWSNT */
381}
382
383#ifdef SIGTSTP
384
385/* Arrange for character C to be read as the next input from
386   the terminal.  */
387
388void
389#ifdef PROTOTYPES
390stuff_char (char c)
391#else
392stuff_char (c)
393     char c;
394#endif
395{
396  if (read_socket_hook)
397    return;
398
399/* Should perhaps error if in batch mode */
400#ifdef TIOCSTI
401  ioctl (input_fd, TIOCSTI, &c);
402#else /* no TIOCSTI */
403  error ("Cannot stuff terminal input characters in this version of Unix");
404#endif /* no TIOCSTI */
405}
406
407#endif /* SIGTSTP */
408
409void
410init_baud_rate ()
411{
412  if (noninteractive)
413    emacs_ospeed = 0;
414  else
415    {
416#ifdef INIT_BAUD_RATE
417      INIT_BAUD_RATE ();
418#else
419#ifdef DOS_NT
420    emacs_ospeed = 15;
421#else  /* not DOS_NT */
422#ifdef VMS
423      struct sensemode sg;
424
425      SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
426		&sg.class, 12, 0, 0, 0, 0 );
427      emacs_ospeed = sg.xmit_baud;
428#else /* not VMS */
429#ifdef HAVE_TERMIOS
430      struct termios sg;
431
432      sg.c_cflag = B9600;
433      tcgetattr (input_fd, &sg);
434      emacs_ospeed = cfgetospeed (&sg);
435#if defined (USE_GETOBAUD) && defined (getobaud)
436      /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
437      if (emacs_ospeed == 0)
438        emacs_ospeed = getobaud (sg.c_cflag);
439#endif
440#else /* neither VMS nor TERMIOS */
441#ifdef HAVE_TERMIO
442      struct termio sg;
443
444      sg.c_cflag = B9600;
445#ifdef HAVE_TCATTR
446      tcgetattr (input_fd, &sg);
447#else
448      ioctl (input_fd, TCGETA, &sg);
449#endif
450      emacs_ospeed = sg.c_cflag & CBAUD;
451#else /* neither VMS nor TERMIOS nor TERMIO */
452      struct sgttyb sg;
453
454      sg.sg_ospeed = B9600;
455      if (ioctl (input_fd, TIOCGETP, &sg) < 0)
456	abort ();
457      emacs_ospeed = sg.sg_ospeed;
458#endif /* not HAVE_TERMIO */
459#endif /* not HAVE_TERMIOS */
460#endif /* not VMS */
461#endif /* not DOS_NT */
462#endif /* not INIT_BAUD_RATE */
463    }
464
465  baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
466	       ? baud_convert[emacs_ospeed] : 9600);
467  if (baud_rate == 0)
468    baud_rate = 1200;
469}
470
471/*ARGSUSED*/
472void
473set_exclusive_use (fd)
474     int fd;
475{
476#ifdef FIOCLEX
477  ioctl (fd, FIOCLEX, 0);
478#endif
479  /* Ok to do nothing if this feature does not exist */
480}
481
482#ifndef subprocesses
483
484wait_without_blocking ()
485{
486#ifdef BSD_SYSTEM
487  wait3 (0, WNOHANG | WUNTRACED, 0);
488#else
489  croak ("wait_without_blocking");
490#endif
491  synch_process_alive = 0;
492}
493
494#endif /* not subprocesses */
495
496int wait_debugging;   /* Set nonzero to make following function work under dbx
497			 (at least for bsd).  */
498
499SIGTYPE
500wait_for_termination_signal ()
501{}
502
503/* Wait for subprocess with process id `pid' to terminate and
504   make sure it will get eliminated (not remain forever as a zombie) */
505
506void
507wait_for_termination (pid)
508     int pid;
509{
510  while (1)
511    {
512#ifdef subprocesses
513#ifdef VMS
514      int status;
515
516      status = SYS$FORCEX (&pid, 0, 0);
517      break;
518#else /* not VMS */
519#if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
520      /* Note that kill returns -1 even if the process is just a zombie now.
521	 But inevitably a SIGCHLD interrupt should be generated
522	 and child_sig will do wait3 and make the process go away. */
523      /* There is some indication that there is a bug involved with
524	 termination of subprocesses, perhaps involving a kernel bug too,
525	 but no idea what it is.  Just as a hunch we signal SIGCHLD to see
526	 if that causes the problem to go away or get worse.  */
527      sigsetmask (sigmask (SIGCHLD));
528      if (0 > kill (pid, 0))
529	{
530	  sigsetmask (SIGEMPTYMASK);
531	  kill (getpid (), SIGCHLD);
532	  break;
533	}
534      if (wait_debugging)
535	sleep (1);
536      else
537	sigpause (SIGEMPTYMASK);
538#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
539#if defined (UNIPLUS)
540      if (0 > kill (pid, 0))
541	break;
542      wait (0);
543#else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
544#ifdef POSIX_SIGNALS    /* would this work for GNU/Linux as well? */
545      sigblock (sigmask (SIGCHLD));
546      errno = 0;
547      if (kill (pid, 0) == -1 && errno == ESRCH)
548	{
549	  sigunblock (sigmask (SIGCHLD));
550	  break;
551	}
552
553      sigsuspend (&empty_mask);
554#else /* not POSIX_SIGNALS */
555#ifdef HAVE_SYSV_SIGPAUSE
556      sighold (SIGCHLD);
557      if (0 > kill (pid, 0))
558	{
559	  sigrelse (SIGCHLD);
560	  break;
561	}
562      sigpause (SIGCHLD);
563#else /* not HAVE_SYSV_SIGPAUSE */
564#ifdef WINDOWSNT
565      wait (0);
566      break;
567#else /* not WINDOWSNT */
568      if (0 > kill (pid, 0))
569	break;
570      /* Using sleep instead of pause avoids timing error.
571	 If the inferior dies just before the sleep,
572	 we lose just one second.  */
573      sleep (1);
574#endif /* not WINDOWSNT */
575#endif /* not HAVE_SYSV_SIGPAUSE */
576#endif /* not POSIX_SIGNALS */
577#endif /* not UNIPLUS */
578#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
579#endif /* not VMS */
580#else /* not subprocesses */
581#if __DJGPP__ > 1
582      break;
583#else /* not __DJGPP__ > 1 */
584#ifndef BSD4_1
585      if (kill (pid, 0) < 0)
586	break;
587      wait (0);
588#else /* BSD4_1 */
589      int status;
590      status = wait (0);
591      if (status == pid || status == -1)
592	break;
593#endif /* BSD4_1 */
594#endif /* not __DJGPP__ > 1*/
595#endif /* not subprocesses */
596    }
597}
598
599#ifdef subprocesses
600
601/*
602 *	flush any pending output
603 *      (may flush input as well; it does not matter the way we use it)
604 */
605
606void
607flush_pending_output (channel)
608     int channel;
609{
610#ifdef HAVE_TERMIOS
611  /* If we try this, we get hit with SIGTTIN, because
612     the child's tty belongs to the child's pgrp. */
613#else
614#ifdef TCFLSH
615  ioctl (channel, TCFLSH, 1);
616#else
617#ifdef TIOCFLUSH
618  int zero = 0;
619  /* 3rd arg should be ignored
620     but some 4.2 kernels actually want the address of an int
621     and nonzero means something different.  */
622  ioctl (channel, TIOCFLUSH, &zero);
623#endif
624#endif
625#endif
626}
627
628#ifndef VMS
629/*  Set up the terminal at the other end of a pseudo-terminal that
630    we will be controlling an inferior through.
631    It should not echo or do line-editing, since that is done
632    in Emacs.  No padding needed for insertion into an Emacs buffer.  */
633
634void
635child_setup_tty (out)
636     int out;
637{
638#ifndef DOS_NT
639  struct emacs_tty s;
640
641  EMACS_GET_TTY (out, &s);
642
643#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
644  s.main.c_oflag |= OPOST;	/* Enable output postprocessing */
645  s.main.c_oflag &= ~ONLCR;	/* Disable map of NL to CR-NL on output */
646#ifdef NLDLY
647  s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
648  				/* No output delays */
649#endif
650  s.main.c_lflag &= ~ECHO;	/* Disable echo */
651  s.main.c_lflag |= ISIG;	/* Enable signals */
652#if 0  /* This causes bugs in (for instance) telnet to certain sites.  */
653  s.main.c_iflag &= ~ICRNL;	/* Disable map of CR to NL on input */
654#ifdef INLCR  /* Just being cautious, since I can't check how
655		 widespread INLCR is--rms.  */
656  s.main.c_iflag &= ~INLCR;	/* Disable map of NL to CR on input */
657#endif
658#endif
659#ifdef IUCLC
660  s.main.c_iflag &= ~IUCLC;	/* Disable downcasing on input.  */
661#endif
662#ifdef ISTRIP
663  s.main.c_iflag &= ~ISTRIP;	/* don't strip 8th bit on input */
664#endif
665#ifdef OLCUC
666  s.main.c_oflag &= ~OLCUC;	/* Disable upcasing on output.  */
667#endif
668  s.main.c_oflag &= ~TAB3;	/* Disable tab expansion */
669  s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
670#if 0
671  /* Said to be unnecessary:  */
672  s.main.c_cc[VMIN] = 1;	/* minimum number of characters to accept  */
673  s.main.c_cc[VTIME] = 0;	/* wait forever for at least 1 character  */
674#endif
675
676  s.main.c_lflag |= ICANON;	/* Enable erase/kill and eof processing */
677  s.main.c_cc[VEOF] = 04;	/* insure that EOF is Control-D */
678  s.main.c_cc[VERASE] = CDISABLE;	/* disable erase processing */
679  s.main.c_cc[VKILL] = CDISABLE;	/* disable kill processing */
680
681#ifdef HPUX
682  s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
683#endif /* HPUX */
684
685#ifdef SIGNALS_VIA_CHARACTERS
686  /* the QUIT and INTR character are used in process_send_signal
687     so set them here to something useful.  */
688  if (s.main.c_cc[VQUIT] == CDISABLE)
689    s.main.c_cc[VQUIT] = '\\'&037;	/* Control-\ */
690  if (s.main.c_cc[VINTR] == CDISABLE)
691    s.main.c_cc[VINTR] = 'C'&037;	/* Control-C */
692#endif /* not SIGNALS_VIA_CHARACTERS */
693
694#ifdef AIX
695/* AIX enhanced edit loses NULs, so disable it */
696#ifndef IBMR2AIX
697  s.main.c_line = 0;
698  s.main.c_iflag &= ~ASCEDIT;
699#endif
700  /* Also, PTY overloads NUL and BREAK.
701     don't ignore break, but don't signal either, so it looks like NUL.  */
702  s.main.c_iflag &= ~IGNBRK;
703  s.main.c_iflag &= ~BRKINT;
704  /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
705     unconditionally.  Then a SIGNALS_VIA_CHARACTERS conditional
706     would force it to 0377.  That looks like duplicated code.  */
707#ifndef SIGNALS_VIA_CHARACTERS
708  /* QUIT and INTR work better as signals, so disable character forms */
709  s.main.c_cc[VQUIT] = CDISABLE;
710  s.main.c_cc[VINTR] = CDISABLE;
711  s.main.c_lflag &= ~ISIG;
712#endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
713  s.main.c_cc[VEOL] = CDISABLE;
714  s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
715#endif /* AIX */
716
717#else /* not HAVE_TERMIO */
718
719  s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
720		       | CBREAK | TANDEM);
721  s.main.sg_flags |= LPASS8;
722  s.main.sg_erase = 0377;
723  s.main.sg_kill = 0377;
724  s.lmode = LLITOUT | s.lmode;        /* Don't strip 8th bit */
725
726#endif /* not HAVE_TERMIO */
727
728  EMACS_SET_TTY (out, &s, 0);
729
730#ifdef BSD4_1
731  if (interrupt_input)
732    reset_sigio ();
733#endif /* BSD4_1 */
734#ifdef RTU
735  {
736    int zero = 0;
737    ioctl (out, FIOASYNC, &zero);
738  }
739#endif /* RTU */
740#endif /* not DOS_NT */
741}
742#endif /* not VMS */
743
744#endif /* subprocesses */
745
746/* Record a signal code and the handler for it.  */
747struct save_signal
748{
749  int code;
750  SIGTYPE (*handler) P_ ((int));
751};
752
753static void save_signal_handlers P_ ((struct save_signal *));
754static void restore_signal_handlers P_ ((struct save_signal *));
755
756/* Suspend the Emacs process; give terminal to its superior.  */
757
758void
759sys_suspend ()
760{
761#ifdef VMS
762  /* "Foster" parentage allows emacs to return to a subprocess that attached
763     to the current emacs as a cheaper than starting a whole new process.  This
764     is set up by KEPTEDITOR.COM.  */
765  unsigned long parent_id, foster_parent_id;
766  char *fpid_string;
767
768  fpid_string = getenv ("EMACS_PARENT_PID");
769  if (fpid_string != NULL)
770    {
771      sscanf (fpid_string, "%x", &foster_parent_id);
772      if (foster_parent_id != 0)
773	parent_id = foster_parent_id;
774      else
775	parent_id = getppid ();
776    }
777  else
778    parent_id = getppid ();
779
780  xfree (fpid_string);		/* On VMS, this was malloc'd */
781
782  if (parent_id && parent_id != 0xffffffff)
783    {
784      SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
785      int status = LIB$ATTACH (&parent_id) & 1;
786      signal (SIGINT, oldsig);
787      return status;
788    }
789  else
790    {
791      struct {
792	int	l;
793	char	*a;
794      } d_prompt;
795      d_prompt.l = sizeof ("Emacs: ");		/* Our special prompt */
796      d_prompt.a = "Emacs: ";			/* Just a reminder */
797      LIB$SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
798      return 1;
799    }
800  return -1;
801#else
802#if defined (SIGTSTP) && !defined (MSDOS)
803
804  {
805    int pgrp = EMACS_GETPGRP (0);
806    EMACS_KILLPG (pgrp, SIGTSTP);
807  }
808
809#else /* No SIGTSTP */
810#ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
811  ptrace (0, 0, 0, 0);		/* set for ptrace - caught by csh */
812  kill (getpid (), SIGQUIT);
813
814#else /* No SIGTSTP or USG_JOBCTRL */
815
816/* On a system where suspending is not implemented,
817   instead fork a subshell and let it talk directly to the terminal
818   while we wait.  */
819  sys_subshell ();
820
821#endif /* no USG_JOBCTRL */
822#endif /* no SIGTSTP */
823#endif /* not VMS */
824}
825
826/* Fork a subshell.  */
827
828#ifndef MAC_OS8
829void
830sys_subshell ()
831{
832#ifndef VMS
833#ifdef DOS_NT	/* Demacs 1.1.2 91/10/20 Manabu Higashida */
834  int st;
835  char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
836#endif
837  int pid;
838  struct save_signal saved_handlers[5];
839  Lisp_Object dir;
840  unsigned char *str = 0;
841  int len;
842
843  saved_handlers[0].code = SIGINT;
844  saved_handlers[1].code = SIGQUIT;
845  saved_handlers[2].code = SIGTERM;
846#ifdef SIGIO
847  saved_handlers[3].code = SIGIO;
848  saved_handlers[4].code = 0;
849#else
850  saved_handlers[3].code = 0;
851#endif
852
853  /* Mentioning current_buffer->buffer would mean including buffer.h,
854     which somehow wedges the hp compiler.  So instead...  */
855
856  dir = intern ("default-directory");
857  if (NILP (Fboundp (dir)))
858    goto xyzzy;
859  dir = Fsymbol_value (dir);
860  if (!STRINGP (dir))
861    goto xyzzy;
862
863  dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
864  str = (unsigned char *) alloca (SCHARS (dir) + 2);
865  len = SCHARS (dir);
866  bcopy (SDATA (dir), str, len);
867  if (str[len - 1] != '/') str[len++] = '/';
868  str[len] = 0;
869 xyzzy:
870
871#ifdef DOS_NT
872  pid = 0;
873#if __DJGPP__ > 1
874  save_signal_handlers (saved_handlers);
875  synch_process_alive = 1;
876#endif /* __DJGPP__ > 1 */
877#else
878  pid = vfork ();
879  if (pid == -1)
880    error ("Can't spawn subshell");
881#endif
882
883  if (pid == 0)
884    {
885      char *sh = 0;
886
887#ifdef DOS_NT    /* MW, Aug 1993 */
888      getwd (oldwd);
889      if (sh == 0)
890	sh = (char *) egetenv ("SUSPEND");	/* KFS, 1994-12-14 */
891#endif
892      if (sh == 0)
893	sh = (char *) egetenv ("SHELL");
894      if (sh == 0)
895	sh = "sh";
896
897      /* Use our buffer's default directory for the subshell.  */
898      if (str)
899	chdir ((char *) str);
900
901#ifdef subprocesses
902      close_process_descs ();	/* Close Emacs's pipes/ptys */
903#endif
904
905#ifdef SET_EMACS_PRIORITY
906      {
907	extern EMACS_INT emacs_priority;
908
909	if (emacs_priority < 0)
910	  nice (-emacs_priority);
911      }
912#endif
913
914#ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
915      {
916	char *epwd = getenv ("PWD");
917	char old_pwd[MAXPATHLEN+1+4];
918
919	/* If PWD is set, pass it with corrected value.  */
920	if (epwd)
921	  {
922	    strcpy (old_pwd, epwd);
923	    if (str[len - 1] == '/')
924	      str[len - 1] = '\0';
925	    setenv ("PWD", str, 1);
926	  }
927	st = system (sh);
928	chdir (oldwd);
929	if (epwd)
930	  putenv (old_pwd);	/* restore previous value */
931      }
932#if 0	/* This is also reported if last command executed in subshell failed, KFS */
933      if (st)
934	report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil));
935#endif
936#else /* not MSDOS */
937#ifdef  WINDOWSNT
938      /* Waits for process completion */
939      pid = _spawnlp (_P_WAIT, sh, sh, NULL);
940      chdir (oldwd);
941      if (pid == -1)
942	write (1, "Can't execute subshell", 22);
943#else   /* not WINDOWSNT */
944      execlp (sh, sh, (char *) 0);
945      write (1, "Can't execute subshell", 22);
946      _exit (1);
947#endif  /* not WINDOWSNT */
948#endif /* not MSDOS */
949    }
950
951  /* Do this now if we did not do it before.  */
952#if !defined (MSDOS) || __DJGPP__ == 1
953  save_signal_handlers (saved_handlers);
954  synch_process_alive = 1;
955#endif
956
957#ifndef DOS_NT
958  wait_for_termination (pid);
959#endif
960  restore_signal_handlers (saved_handlers);
961  synch_process_alive = 0;
962#endif /* !VMS */
963}
964#endif /* !MAC_OS8 */
965
966static void
967save_signal_handlers (saved_handlers)
968     struct save_signal *saved_handlers;
969{
970  while (saved_handlers->code)
971    {
972      saved_handlers->handler
973	= (SIGTYPE (*) P_ ((int))) signal (saved_handlers->code, SIG_IGN);
974      saved_handlers++;
975    }
976}
977
978static void
979restore_signal_handlers (saved_handlers)
980     struct save_signal *saved_handlers;
981{
982  while (saved_handlers->code)
983    {
984      signal (saved_handlers->code, saved_handlers->handler);
985      saved_handlers++;
986    }
987}
988
989#ifdef F_SETFL
990
991int old_fcntl_flags;
992
993void
994init_sigio (fd)
995     int fd;
996{
997#ifdef FASYNC
998  old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
999  fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
1000#endif
1001  interrupts_deferred = 0;
1002}
1003
1004void
1005reset_sigio ()
1006{
1007  unrequest_sigio ();
1008}
1009
1010#ifdef FASYNC		/* F_SETFL does not imply existence of FASYNC */
1011
1012void
1013request_sigio ()
1014{
1015  if (noninteractive || read_socket_hook)
1016    return;
1017
1018#ifdef SIGWINCH
1019  sigunblock (sigmask (SIGWINCH));
1020#endif
1021  fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
1022
1023  interrupts_deferred = 0;
1024}
1025
1026void
1027unrequest_sigio ()
1028{
1029  if (noninteractive || read_socket_hook)
1030    return;
1031
1032#ifdef SIGWINCH
1033  sigblock (sigmask (SIGWINCH));
1034#endif
1035  fcntl (input_fd, F_SETFL, old_fcntl_flags);
1036  interrupts_deferred = 1;
1037}
1038
1039#else /* no FASYNC */
1040#ifdef STRIDE		/* Stride doesn't have FASYNC - use FIOASYNC */
1041
1042void
1043request_sigio ()
1044{
1045  int on = 1;
1046
1047  if (noninteractive || read_socket_hook)
1048    return;
1049
1050  ioctl (input_fd, FIOASYNC, &on);
1051  interrupts_deferred = 0;
1052}
1053
1054void
1055unrequest_sigio ()
1056{
1057  int off = 0;
1058
1059  if (noninteractive || read_socket_hook)
1060    return;
1061
1062  ioctl (input_fd, FIOASYNC, &off);
1063  interrupts_deferred = 1;
1064}
1065
1066#else /* not FASYNC, not STRIDE */
1067
1068#ifdef _CX_UX
1069
1070#include <termios.h>
1071
1072void
1073request_sigio ()
1074{
1075  int on = 1;
1076  sigset_t st;
1077
1078  if (noninteractive || read_socket_hook)
1079    return;
1080
1081  sigemptyset (&st);
1082  sigaddset (&st, SIGIO);
1083  ioctl (input_fd, FIOASYNC, &on);
1084  interrupts_deferred = 0;
1085  sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
1086}
1087
1088void
1089unrequest_sigio ()
1090{
1091  int off = 0;
1092
1093  if (noninteractive || read_socket_hook)
1094    return;
1095
1096  ioctl (input_fd, FIOASYNC, &off);
1097  interrupts_deferred = 1;
1098}
1099
1100#else /* ! _CX_UX */
1101#ifndef MSDOS
1102
1103void
1104request_sigio ()
1105{
1106  if (noninteractive || read_socket_hook)
1107    return;
1108
1109  croak ("request_sigio");
1110}
1111
1112void
1113unrequest_sigio ()
1114{
1115  if (noninteractive || read_socket_hook)
1116    return;
1117
1118  croak ("unrequest_sigio");
1119}
1120
1121#endif /* MSDOS */
1122#endif /* _CX_UX */
1123#endif /* STRIDE */
1124#endif /* FASYNC */
1125#endif /* F_SETFL */
1126
1127/* Saving and restoring the process group of Emacs's terminal.  */
1128
1129#ifdef BSD_PGRPS
1130
1131/* The process group of which Emacs was a member when it initially
1132   started.
1133
1134   If Emacs was in its own process group (i.e. inherited_pgroup ==
1135   getpid ()), then we know we're running under a shell with job
1136   control (Emacs would never be run as part of a pipeline).
1137   Everything is fine.
1138
1139   If Emacs was not in its own process group, then we know we're
1140   running under a shell (or a caller) that doesn't know how to
1141   separate itself from Emacs (like sh).  Emacs must be in its own
1142   process group in order to receive SIGIO correctly.  In this
1143   situation, we put ourselves in our own pgroup, forcibly set the
1144   tty's pgroup to our pgroup, and make sure to restore and reinstate
1145   the tty's pgroup just like any other terminal setting.  If
1146   inherited_group was not the tty's pgroup, then we'll get a
1147   SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1148   it goes foreground in the future, which is what should happen.  */
1149int inherited_pgroup;
1150
1151/* Split off the foreground process group to Emacs alone.
1152   When we are in the foreground, but not started in our own process
1153   group, redirect the TTY to point to our own process group.  We need
1154   to be in our own process group to receive SIGIO properly.  */
1155void
1156narrow_foreground_group ()
1157{
1158  int me = getpid ();
1159
1160  setpgrp (0, inherited_pgroup);
1161  if (inherited_pgroup != me)
1162    EMACS_SET_TTY_PGRP (input_fd, &me);
1163  setpgrp (0, me);
1164}
1165
1166/* Set the tty to our original foreground group.  */
1167void
1168widen_foreground_group ()
1169{
1170  if (inherited_pgroup != getpid ())
1171    EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
1172  setpgrp (0, inherited_pgroup);
1173}
1174
1175#endif /* BSD_PGRPS */
1176
1177/* Getting and setting emacs_tty structures.  */
1178
1179/* Set *TC to the parameters associated with the terminal FD.
1180   Return zero if all's well, or -1 if we ran into an error we
1181   couldn't deal with.  */
1182int
1183emacs_get_tty (fd, settings)
1184     int fd;
1185     struct emacs_tty *settings;
1186{
1187  /* Retrieve the primary parameters - baud rate, character size, etcetera.  */
1188#ifdef HAVE_TCATTR
1189  /* We have those nifty POSIX tcmumbleattr functions.  */
1190  bzero (&settings->main, sizeof (settings->main));
1191  if (tcgetattr (fd, &settings->main) < 0)
1192    return -1;
1193
1194#else
1195#ifdef HAVE_TERMIO
1196  /* The SYSV-style interface?  */
1197  if (ioctl (fd, TCGETA, &settings->main) < 0)
1198    return -1;
1199
1200#else
1201#ifdef VMS
1202  /* Vehemently Monstrous System?  :-)  */
1203  if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0,
1204		   &settings->main.class, 12, 0, 0, 0, 0)
1205	 & 1))
1206    return -1;
1207
1208#else
1209#ifndef DOS_NT
1210  /* I give up - I hope you have the BSD ioctls.  */
1211  if (ioctl (fd, TIOCGETP, &settings->main) < 0)
1212    return -1;
1213#endif /* not DOS_NT */
1214#endif
1215#endif
1216#endif
1217
1218  /* Suivant - Do we have to get struct ltchars data?  */
1219#ifdef HAVE_LTCHARS
1220  if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
1221    return -1;
1222#endif
1223
1224  /* How about a struct tchars and a wordful of lmode bits?  */
1225#ifdef HAVE_TCHARS
1226  if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
1227      || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
1228    return -1;
1229#endif
1230
1231  /* We have survived the tempest.  */
1232  return 0;
1233}
1234
1235
1236/* Set the parameters of the tty on FD according to the contents of
1237   *SETTINGS.  If FLUSHP is non-zero, we discard input.
1238   Return 0 if all went well, and -1 if anything failed.  */
1239
1240int
1241emacs_set_tty (fd, settings, flushp)
1242     int fd;
1243     struct emacs_tty *settings;
1244     int flushp;
1245{
1246  /* Set the primary parameters - baud rate, character size, etcetera.  */
1247#ifdef HAVE_TCATTR
1248  int i;
1249  /* We have those nifty POSIX tcmumbleattr functions.
1250     William J. Smith <wjs@wiis.wang.com> writes:
1251     "POSIX 1003.1 defines tcsetattr to return success if it was
1252     able to perform any of the requested actions, even if some
1253     of the requested actions could not be performed.
1254     We must read settings back to ensure tty setup properly.
1255     AIX requires this to keep tty from hanging occasionally."  */
1256  /* This make sure that we don't loop indefinitely in here.  */
1257  for (i = 0 ; i < 10 ; i++)
1258    if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
1259      {
1260	if (errno == EINTR)
1261	  continue;
1262	else
1263	  return -1;
1264      }
1265    else
1266      {
1267	struct termios new;
1268
1269	bzero (&new, sizeof (new));
1270	/* Get the current settings, and see if they're what we asked for.  */
1271	tcgetattr (fd, &new);
1272	/* We cannot use memcmp on the whole structure here because under
1273	 * aix386 the termios structure has some reserved field that may
1274	 * not be filled in.
1275	 */
1276	if (   new.c_iflag == settings->main.c_iflag
1277	    && new.c_oflag == settings->main.c_oflag
1278	    && new.c_cflag == settings->main.c_cflag
1279	    && new.c_lflag == settings->main.c_lflag
1280	    && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
1281	  break;
1282	else
1283	  continue;
1284      }
1285
1286#else
1287#ifdef HAVE_TERMIO
1288  /* The SYSV-style interface?  */
1289  if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
1290    return -1;
1291
1292#else
1293#ifdef VMS
1294  /* Vehemently Monstrous System?  :-)  */
1295  if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0,
1296		   &settings->main.class, 12, 0, 0, 0, 0)
1297	 & 1))
1298    return -1;
1299
1300#else
1301#ifndef DOS_NT
1302  /* I give up - I hope you have the BSD ioctls.  */
1303  if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
1304    return -1;
1305#endif /* not DOS_NT */
1306
1307#endif
1308#endif
1309#endif
1310
1311  /* Suivant - Do we have to get struct ltchars data?  */
1312#ifdef HAVE_LTCHARS
1313  if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
1314    return -1;
1315#endif
1316
1317  /* How about a struct tchars and a wordful of lmode bits?  */
1318#ifdef HAVE_TCHARS
1319  if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
1320      || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
1321    return -1;
1322#endif
1323
1324  /* We have survived the tempest.  */
1325  return 0;
1326}
1327
1328
1329/* The initial tty mode bits */
1330struct emacs_tty old_tty;
1331
1332/* 1 if we have been through init_sys_modes.  */
1333int term_initted;
1334
1335/* 1 if outer tty status has been recorded.  */
1336int old_tty_valid;
1337
1338#ifdef BSD4_1
1339/* BSD 4.1 needs to keep track of the lmode bits in order to start
1340   sigio.  */
1341int lmode;
1342#endif
1343
1344#ifndef F_SETOWN_BUG
1345#ifdef F_SETOWN
1346int old_fcntl_owner;
1347#endif /* F_SETOWN */
1348#endif /* F_SETOWN_BUG */
1349
1350/* This may also be defined in stdio,
1351   but if so, this does no harm,
1352   and using the same name avoids wasting the other one's space.  */
1353
1354#ifdef nec_ews_svr4
1355extern char *_sobuf ;
1356#else
1357#if defined (USG) || defined (DGUX)
1358unsigned char _sobuf[BUFSIZ+8];
1359#else
1360char _sobuf[BUFSIZ];
1361#endif
1362#endif
1363
1364#ifdef HAVE_LTCHARS
1365static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
1366#endif
1367#ifdef HAVE_TCHARS
1368static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
1369#endif
1370
1371void
1372init_sys_modes ()
1373{
1374  struct emacs_tty tty;
1375
1376#ifdef VMS
1377#if 0
1378  static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
1379  extern int (*interrupt_signal) ();
1380#endif
1381#endif
1382
1383  Vtty_erase_char = Qnil;
1384
1385  if (noninteractive)
1386    return;
1387
1388#ifdef VMS
1389  if (!input_ef)
1390    input_ef = get_kbd_event_flag ();
1391    /* LIB$GET_EF (&input_ef); */
1392  SYS$CLREF (input_ef);
1393  waiting_for_ast = 0;
1394  if (!timer_ef)
1395    timer_ef = get_timer_event_flag ();
1396    /* LIB$GET_EF (&timer_ef); */
1397  SYS$CLREF (timer_ef);
1398#if 0
1399  if (!process_ef)
1400    {
1401      LIB$GET_EF (&process_ef);
1402      SYS$CLREF (process_ef);
1403    }
1404  if (input_ef / 32 != process_ef / 32)
1405    croak ("Input and process event flags in different clusters.");
1406#endif
1407  if (input_ef / 32 != timer_ef / 32)
1408    croak ("Input and timer event flags in different clusters.");
1409#if 0
1410  input_eflist = ((unsigned) 1 << (input_ef % 32)) |
1411    ((unsigned) 1 << (process_ef % 32));
1412#endif
1413  timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
1414    ((unsigned) 1 << (timer_ef % 32));
1415#ifndef VMS4_4
1416  sys_access_reinit ();
1417#endif
1418#endif /* not VMS */
1419
1420#ifdef BSD_PGRPS
1421  if (! read_socket_hook && EQ (Vwindow_system, Qnil))
1422    narrow_foreground_group ();
1423#endif
1424
1425#ifdef HAVE_WINDOW_SYSTEM
1426  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1427     needs the initialization code below.  */
1428  if (!read_socket_hook && EQ (Vwindow_system, Qnil))
1429#endif
1430    {
1431      EMACS_GET_TTY (input_fd, &old_tty);
1432
1433      old_tty_valid = 1;
1434
1435      tty = old_tty;
1436
1437#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1438      XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]);
1439
1440#ifdef DGUX
1441      /* This allows meta to be sent on 8th bit.  */
1442      tty.main.c_iflag &= ~INPCK;	/* don't check input for parity */
1443#endif
1444      tty.main.c_iflag |= (IGNBRK);	/* Ignore break condition */
1445      tty.main.c_iflag &= ~ICRNL;	/* Disable map of CR to NL on input */
1446#ifdef INLCR  /* I'm just being cautious,
1447		 since I can't check how widespread INLCR is--rms.  */
1448      tty.main.c_iflag &= ~INLCR;	/* Disable map of NL to CR on input */
1449#endif
1450#ifdef ISTRIP
1451      tty.main.c_iflag &= ~ISTRIP;	/* don't strip 8th bit on input */
1452#endif
1453      tty.main.c_lflag &= ~ECHO;	/* Disable echo */
1454      tty.main.c_lflag &= ~ICANON;	/* Disable erase/kill processing */
1455#ifdef IEXTEN
1456      tty.main.c_lflag &= ~IEXTEN;	/* Disable other editing characters.  */
1457#endif
1458      tty.main.c_lflag |= ISIG;	/* Enable signals */
1459      if (flow_control)
1460	{
1461	  tty.main.c_iflag |= IXON;	/* Enable start/stop output control */
1462#ifdef IXANY
1463	  tty.main.c_iflag &= ~IXANY;
1464#endif /* IXANY */
1465	}
1466      else
1467	tty.main.c_iflag &= ~IXON;	/* Disable start/stop output control */
1468      tty.main.c_oflag &= ~ONLCR;	/* Disable map of NL to CR-NL
1469					   on output */
1470      tty.main.c_oflag &= ~TAB3;	/* Disable tab expansion */
1471#ifdef CS8
1472      if (meta_key)
1473	{
1474	  tty.main.c_cflag |= CS8;	/* allow 8th bit on input */
1475	  tty.main.c_cflag &= ~PARENB;/* Don't check parity */
1476	}
1477#endif
1478      tty.main.c_cc[VINTR] = quit_char;	/* C-g (usually) gives SIGINT */
1479      /* Set up C-g for both SIGQUIT and SIGINT.
1480	 We don't know which we will get, but we handle both alike
1481	 so which one it really gives us does not matter.  */
1482      tty.main.c_cc[VQUIT] = quit_char;
1483      tty.main.c_cc[VMIN] = 1;	/* Input should wait for at least 1 char */
1484      tty.main.c_cc[VTIME] = 0;	/* no matter how long that takes.  */
1485#ifdef VSWTCH
1486      tty.main.c_cc[VSWTCH] = CDISABLE;	/* Turn off shell layering use
1487					   of C-z */
1488#endif /* VSWTCH */
1489
1490#if defined (mips) || defined (HAVE_TCATTR)
1491#ifdef VSUSP
1492      tty.main.c_cc[VSUSP] = CDISABLE;	/* Turn off mips handling of C-z.  */
1493#endif /* VSUSP */
1494#ifdef V_DSUSP
1495      tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y.  */
1496#endif /* V_DSUSP */
1497#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP.  */
1498      tty.main.c_cc[VDSUSP] = CDISABLE;
1499#endif /* VDSUSP */
1500#ifdef VLNEXT
1501      tty.main.c_cc[VLNEXT] = CDISABLE;
1502#endif /* VLNEXT */
1503#ifdef VREPRINT
1504      tty.main.c_cc[VREPRINT] = CDISABLE;
1505#endif /* VREPRINT */
1506#ifdef VWERASE
1507      tty.main.c_cc[VWERASE] = CDISABLE;
1508#endif /* VWERASE */
1509#ifdef VDISCARD
1510      tty.main.c_cc[VDISCARD] = CDISABLE;
1511#endif /* VDISCARD */
1512
1513      if (flow_control)
1514	{
1515#ifdef VSTART
1516	  tty.main.c_cc[VSTART] = '\021';
1517#endif /* VSTART */
1518#ifdef VSTOP
1519	  tty.main.c_cc[VSTOP] = '\023';
1520#endif /* VSTOP */
1521	}
1522      else
1523	{
1524#ifdef VSTART
1525	  tty.main.c_cc[VSTART] = CDISABLE;
1526#endif /* VSTART */
1527#ifdef VSTOP
1528	  tty.main.c_cc[VSTOP] = CDISABLE;
1529#endif /* VSTOP */
1530	}
1531#endif /* mips or HAVE_TCATTR */
1532
1533#ifdef SET_LINE_DISCIPLINE
1534      /* Need to explicitly request TERMIODISC line discipline or
1535         Ultrix's termios does not work correctly.  */
1536      tty.main.c_line = SET_LINE_DISCIPLINE;
1537#endif
1538#ifdef AIX
1539#ifndef IBMR2AIX
1540      /* AIX enhanced edit loses NULs, so disable it.  */
1541      tty.main.c_line = 0;
1542      tty.main.c_iflag &= ~ASCEDIT;
1543#else
1544      tty.main.c_cc[VSTRT] = CDISABLE;
1545      tty.main.c_cc[VSTOP] = CDISABLE;
1546      tty.main.c_cc[VSUSP] = CDISABLE;
1547      tty.main.c_cc[VDSUSP] = CDISABLE;
1548#endif /* IBMR2AIX */
1549      if (flow_control)
1550	{
1551#ifdef VSTART
1552	  tty.main.c_cc[VSTART] = '\021';
1553#endif /* VSTART */
1554#ifdef VSTOP
1555	  tty.main.c_cc[VSTOP] = '\023';
1556#endif /* VSTOP */
1557	}
1558      /* Also, PTY overloads NUL and BREAK.
1559	 don't ignore break, but don't signal either, so it looks like NUL.
1560	 This really serves a purpose only if running in an XTERM window
1561	 or via TELNET or the like, but does no harm elsewhere.  */
1562      tty.main.c_iflag &= ~IGNBRK;
1563      tty.main.c_iflag &= ~BRKINT;
1564#endif
1565#else /* if not HAVE_TERMIO */
1566#ifdef VMS
1567      tty.main.tt_char |= TT$M_NOECHO;
1568      if (meta_key)
1569	tty.main.tt_char |= TT$M_EIGHTBIT;
1570      if (flow_control)
1571	tty.main.tt_char |= TT$M_TTSYNC;
1572      else
1573	tty.main.tt_char &= ~TT$M_TTSYNC;
1574      tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
1575#else /* not VMS (BSD, that is) */
1576#ifndef DOS_NT
1577      XSETINT (Vtty_erase_char, tty.main.sg_erase);
1578      tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1579      if (meta_key)
1580	tty.main.sg_flags |= ANYP;
1581      tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
1582#endif /* not DOS_NT */
1583#endif /* not VMS (BSD, that is) */
1584#endif /* not HAVE_TERMIO */
1585
1586      /* If going to use CBREAK mode, we must request C-g to interrupt
1587	 and turn off start and stop chars, etc.  If not going to use
1588	 CBREAK mode, do this anyway so as to turn off local flow
1589	 control for user coming over network on 4.2; in this case,
1590	 only t_stopc and t_startc really matter.  */
1591#ifndef HAVE_TERMIO
1592#ifdef HAVE_TCHARS
1593      /* Note: if not using CBREAK mode, it makes no difference how we
1594	 set this */
1595      tty.tchars = new_tchars;
1596      tty.tchars.t_intrc = quit_char;
1597      if (flow_control)
1598	{
1599	  tty.tchars.t_startc = '\021';
1600	  tty.tchars.t_stopc = '\023';
1601	}
1602
1603      tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
1604#ifdef ultrix
1605      /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1606	 anything, and leaving it in breaks the meta key.  Go figure.  */
1607      tty.lmode &= ~LLITOUT;
1608#endif
1609
1610#ifdef BSD4_1
1611      lmode = tty.lmode;
1612#endif
1613
1614#endif /* HAVE_TCHARS */
1615#endif /* not HAVE_TERMIO */
1616
1617#ifdef HAVE_LTCHARS
1618      tty.ltchars = new_ltchars;
1619#endif /* HAVE_LTCHARS */
1620#ifdef MSDOS	/* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1621      if (!term_initted)
1622	internal_terminal_init ();
1623      dos_ttraw ();
1624#endif
1625
1626      EMACS_SET_TTY (input_fd, &tty, 0);
1627
1628      /* This code added to insure that, if flow-control is not to be used,
1629	 we have an unlocked terminal at the start. */
1630
1631#ifdef TCXONC
1632      if (!flow_control) ioctl (input_fd, TCXONC, 1);
1633#endif
1634#ifndef APOLLO
1635#ifdef TIOCSTART
1636      if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
1637#endif
1638#endif
1639
1640#if defined (HAVE_TERMIOS) || defined (HPUX9)
1641#ifdef TCOON
1642      if (!flow_control) tcflow (input_fd, TCOON);
1643#endif
1644#endif
1645
1646#ifdef AIXHFT
1647      hft_init ();
1648#ifdef IBMR2AIX
1649      {
1650	/* IBM's HFT device usually thinks a ^J should be LF/CR.  We need it
1651	   to be only LF.  This is the way that is done. */
1652	struct termio tty;
1653
1654	if (ioctl (1, HFTGETID, &tty) != -1)
1655	  write (1, "\033[20l", 5);
1656      }
1657#endif
1658#endif /* AIXHFT */
1659
1660#ifdef VMS
1661/*  Appears to do nothing when in PASTHRU mode.
1662      SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1663		interrupt_signal, oob_chars, 0, 0, 0, 0);
1664*/
1665      queue_kbd_input (0);
1666#endif /* VMS */
1667    }
1668
1669#ifdef F_SETFL
1670#ifndef F_SETOWN_BUG
1671#ifdef F_GETOWN		/* F_SETFL does not imply existence of F_GETOWN */
1672  if (interrupt_input
1673      && ! read_socket_hook && EQ (Vwindow_system, Qnil))
1674    {
1675      old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
1676      fcntl (input_fd, F_SETOWN, getpid ());
1677      init_sigio (input_fd);
1678    }
1679#endif /* F_GETOWN */
1680#endif /* F_SETOWN_BUG */
1681#endif /* F_SETFL */
1682
1683#ifdef BSD4_1
1684  if (interrupt_input)
1685    init_sigio (input_fd);
1686#endif
1687
1688#ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
1689#undef _IOFBF
1690#endif
1691#ifdef _IOFBF
1692  /* This symbol is defined on recent USG systems.
1693     Someone says without this call USG won't really buffer the file
1694     even with a call to setbuf. */
1695  setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf);
1696#else
1697  setbuf (stdout, (char *) _sobuf);
1698#endif
1699#ifdef HAVE_WINDOW_SYSTEM
1700  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1701     needs the initialization code below.  */
1702  if (EQ (Vwindow_system, Qnil)
1703#ifndef WINDOWSNT
1704      /* When running in tty mode on NT/Win95, we have a read_socket
1705	 hook, but still need the rest of the initialization code below.  */
1706      && (! read_socket_hook)
1707#endif
1708      )
1709#endif
1710    set_terminal_modes ();
1711
1712  if (!term_initted
1713      && FRAMEP (Vterminal_frame)
1714      && FRAME_TERMCAP_P (XFRAME (Vterminal_frame)))
1715    init_frame_faces (XFRAME (Vterminal_frame));
1716
1717  if (term_initted && no_redraw_on_reenter)
1718    {
1719      if (display_completed)
1720	direct_output_forward_char (0);
1721    }
1722  else
1723    {
1724      frame_garbaged = 1;
1725      if (FRAMEP (Vterminal_frame))
1726	FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
1727    }
1728
1729  term_initted = 1;
1730}
1731
1732/* Return nonzero if safe to use tabs in output.
1733   At the time this is called, init_sys_modes has not been done yet.  */
1734
1735int
1736tabs_safe_p ()
1737{
1738  struct emacs_tty tty;
1739
1740  EMACS_GET_TTY (input_fd, &tty);
1741  return EMACS_TTY_TABS_OK (&tty);
1742}
1743
1744/* Get terminal size from system.
1745   Store number of lines into *HEIGHTP and width into *WIDTHP.
1746   We store 0 if there's no valid information.  */
1747
1748void
1749get_frame_size (widthp, heightp)
1750     int *widthp, *heightp;
1751{
1752
1753#ifdef TIOCGWINSZ
1754
1755  /* BSD-style.  */
1756  struct winsize size;
1757
1758  if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
1759    *widthp = *heightp = 0;
1760  else
1761    {
1762      *widthp = size.ws_col;
1763      *heightp = size.ws_row;
1764    }
1765
1766#else
1767#ifdef TIOCGSIZE
1768
1769  /* SunOS - style.  */
1770  struct ttysize size;
1771
1772  if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1773    *widthp = *heightp = 0;
1774  else
1775    {
1776      *widthp = size.ts_cols;
1777      *heightp = size.ts_lines;
1778    }
1779
1780#else
1781#ifdef VMS
1782
1783  /* Use a fresh channel since the current one may have stale info
1784     (for example, from prior to a suspend); and to avoid a dependency
1785     in the init sequence.  */
1786  int chan;
1787  struct sensemode tty;
1788
1789  SYS$ASSIGN (&input_dsc, &chan, 0, 0);
1790  SYS$QIOW (0, chan, IO$_SENSEMODE, &tty, 0, 0,
1791            &tty.class, 12, 0, 0, 0, 0);
1792  SYS$DASSGN (chan);
1793  *widthp = tty.scr_wid;
1794  *heightp = tty.scr_len;
1795
1796#else
1797#ifdef MSDOS
1798  *widthp = ScreenCols ();
1799  *heightp = ScreenRows ();
1800#else /* system doesn't know size */
1801  *widthp = 0;
1802  *heightp = 0;
1803#endif
1804
1805#endif /* not VMS */
1806#endif /* not SunOS-style */
1807#endif /* not BSD-style */
1808}
1809
1810/* Set the logical window size associated with descriptor FD
1811   to HEIGHT and WIDTH.  This is used mainly with ptys.  */
1812
1813int
1814set_window_size (fd, height, width)
1815     int fd, height, width;
1816{
1817#ifdef TIOCSWINSZ
1818
1819  /* BSD-style.  */
1820  struct winsize size;
1821  size.ws_row = height;
1822  size.ws_col = width;
1823
1824  if (ioctl (fd, TIOCSWINSZ, &size) == -1)
1825    return 0; /* error */
1826  else
1827    return 1;
1828
1829#else
1830#ifdef TIOCSSIZE
1831
1832  /* SunOS - style.  */
1833  struct ttysize size;
1834  size.ts_lines = height;
1835  size.ts_cols = width;
1836
1837  if (ioctl (fd, TIOCGSIZE, &size) == -1)
1838    return 0;
1839  else
1840    return 1;
1841#else
1842  return -1;
1843#endif /* not SunOS-style */
1844#endif /* not BSD-style */
1845}
1846
1847
1848/* Prepare the terminal for exiting Emacs; move the cursor to the
1849   bottom of the frame, turn off interrupt-driven I/O, etc.  */
1850void
1851reset_sys_modes ()
1852{
1853  struct frame *sf;
1854
1855  if (noninteractive)
1856    {
1857      fflush (stdout);
1858      return;
1859    }
1860  if (!term_initted)
1861    return;
1862#ifdef HAVE_WINDOW_SYSTEM
1863  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1864     needs the clean-up code below.  */
1865  if (!EQ (Vwindow_system, Qnil)
1866#ifndef WINDOWSNT
1867      /* When running in tty mode on NT/Win95, we have a read_socket
1868	 hook, but still need the rest of the clean-up code below.  */
1869      || read_socket_hook
1870#endif
1871      )
1872    return;
1873#endif
1874  sf = SELECTED_FRAME ();
1875  cursor_to (FRAME_LINES (sf) - 1, 0);
1876  clear_end_of_line (FRAME_COLS (sf));
1877  /* clear_end_of_line may move the cursor */
1878  cursor_to (FRAME_LINES (sf) - 1, 0);
1879#if defined (IBMR2AIX) && defined (AIXHFT)
1880  {
1881    /* HFT devices normally use ^J as a LF/CR.  We forced it to
1882       do the LF only.  Now, we need to reset it. */
1883    struct termio tty;
1884
1885    if (ioctl (1, HFTGETID, &tty) != -1)
1886      write (1, "\033[20h", 5);
1887  }
1888#endif
1889
1890  reset_terminal_modes ();
1891  fflush (stdout);
1892#ifdef BSD_SYSTEM
1893#ifndef BSD4_1
1894  /* Avoid possible loss of output when changing terminal modes.  */
1895  fsync (fileno (stdout));
1896#endif
1897#endif
1898
1899#ifdef F_SETFL
1900#ifndef F_SETOWN_BUG
1901#ifdef F_SETOWN		/* F_SETFL does not imply existence of F_SETOWN */
1902  if (interrupt_input)
1903    {
1904      reset_sigio ();
1905      fcntl (input_fd, F_SETOWN, old_fcntl_owner);
1906    }
1907#endif /* F_SETOWN */
1908#endif /* F_SETOWN_BUG */
1909#ifdef O_NDELAY
1910  fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY);
1911#endif
1912#endif /* F_SETFL */
1913#ifdef BSD4_1
1914  if (interrupt_input)
1915    reset_sigio ();
1916#endif /* BSD4_1 */
1917
1918  if (old_tty_valid)
1919    while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
1920      ;
1921
1922#ifdef MSDOS	/* Demacs 1.1.2 91/10/20 Manabu Higashida */
1923  dos_ttcooked ();
1924#endif
1925
1926#ifdef SET_LINE_DISCIPLINE
1927  /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1928     A different old line discipline is therefore not restored, yet.
1929     Restore the old line discipline by hand.  */
1930  ioctl (0, TIOCSETD, &old_tty.main.c_line);
1931#endif
1932
1933#ifdef AIXHFT
1934  hft_reset ();
1935#endif
1936
1937#ifdef BSD_PGRPS
1938  widen_foreground_group ();
1939#endif
1940}
1941
1942#ifdef HAVE_PTYS
1943
1944/* Set up the proper status flags for use of a pty.  */
1945
1946void
1947setup_pty (fd)
1948     int fd;
1949{
1950  /* I'm told that TOICREMOTE does not mean control chars
1951     "can't be sent" but rather that they don't have
1952     input-editing or signaling effects.
1953     That should be good, because we have other ways
1954     to do those things in Emacs.
1955     However, telnet mode seems not to work on 4.2.
1956     So TIOCREMOTE is turned off now. */
1957
1958  /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1959     will hang.  In particular, the "timeout" feature (which
1960     causes a read to return if there is no data available)
1961     does this.  Also it is known that telnet mode will hang
1962     in such a way that Emacs must be stopped (perhaps this
1963     is the same problem).
1964
1965     If TIOCREMOTE is turned off, then there is a bug in
1966     hp-ux which sometimes loses data.  Apparently the
1967     code which blocks the master process when the internal
1968     buffer fills up does not work.  Other than this,
1969     though, everything else seems to work fine.
1970
1971     Since the latter lossage is more benign, we may as well
1972     lose that way.  -- cph */
1973#ifdef FIONBIO
1974#if defined(SYSV_PTYS) || defined(UNIX98_PTYS)
1975  {
1976    int on = 1;
1977    ioctl (fd, FIONBIO, &on);
1978  }
1979#endif
1980#endif
1981#ifdef IBMRTAIX
1982  /* On AIX, the parent gets SIGHUP when a pty attached child dies.  So, we */
1983  /* ignore SIGHUP once we've started a child on a pty.  Note that this may */
1984  /* cause EMACS not to die when it should, i.e., when its own controlling  */
1985  /* tty goes away.  I've complained to the AIX developers, and they may    */
1986  /* change this behavior, but I'm not going to hold my breath.             */
1987  signal (SIGHUP, SIG_IGN);
1988#endif
1989}
1990#endif /* HAVE_PTYS */
1991
1992#ifdef VMS
1993
1994/* Assigning an input channel is done at the start of Emacs execution.
1995   This is called each time Emacs is resumed, also, but does nothing
1996   because input_chain is no longer zero.  */
1997
1998void
1999init_vms_input ()
2000{
2001  int status;
2002
2003  if (input_fd == 0)
2004    {
2005      status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
2006      if (! (status & 1))
2007	LIB$STOP (status);
2008    }
2009}
2010
2011/* Deassigning the input channel is done before exiting.  */
2012
2013void
2014stop_vms_input ()
2015{
2016  return SYS$DASSGN (input_fd);
2017}
2018
2019short input_buffer;
2020
2021/* Request reading one character into the keyboard buffer.
2022   This is done as soon as the buffer becomes empty.  */
2023
2024void
2025queue_kbd_input ()
2026{
2027  int status;
2028  extern kbd_input_ast ();
2029
2030  waiting_for_ast = 0;
2031  stop_input = 0;
2032  status = SYS$QIO (0, input_fd, IO$_READVBLK,
2033		    &input_iosb, kbd_input_ast, 1,
2034		    &input_buffer, 1, 0, terminator_mask, 0, 0);
2035}
2036
2037int input_count;
2038
2039/* Ast routine that is called when keyboard input comes in
2040   in accord with the SYS$QIO above.  */
2041
2042void
2043kbd_input_ast ()
2044{
2045  register int c = -1;
2046  int old_errno = errno;
2047  extern EMACS_TIME *input_available_clear_time;
2048
2049  if (waiting_for_ast)
2050    SYS$SETEF (input_ef);
2051  waiting_for_ast = 0;
2052  input_count++;
2053#ifdef ASTDEBUG
2054  if (input_count == 25)
2055    exit (1);
2056  printf ("Ast # %d,", input_count);
2057  printf (" iosb = %x, %x, %x, %x",
2058	  input_iosb.offset, input_iosb.status, input_iosb.termlen,
2059	  input_iosb.term);
2060#endif
2061  if (input_iosb.offset)
2062    {
2063      c = input_buffer;
2064#ifdef ASTDEBUG
2065      printf (", char = 0%o", c);
2066#endif
2067    }
2068#ifdef ASTDEBUG
2069  printf ("\n");
2070  fflush (stdout);
2071  sleep (1);
2072#endif
2073  if (! stop_input)
2074    queue_kbd_input ();
2075  if (c >= 0)
2076    {
2077      struct input_event e;
2078      EVENT_INIT (e);
2079
2080      e.kind = ASCII_KEYSTROKE_EVENT;
2081      XSETINT (e.code, c);
2082      e.frame_or_window = selected_frame;
2083      kbd_buffer_store_event (&e);
2084    }
2085  if (input_available_clear_time)
2086    EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
2087  errno = old_errno;
2088}
2089
2090/* Wait until there is something in kbd_buffer.  */
2091
2092void
2093wait_for_kbd_input ()
2094{
2095  extern int have_process_input, process_exited;
2096
2097  /* If already something, avoid doing system calls.  */
2098  if (detect_input_pending ())
2099    {
2100      return;
2101    }
2102  /* Clear a flag, and tell ast routine above to set it.  */
2103  SYS$CLREF (input_ef);
2104  waiting_for_ast = 1;
2105  /* Check for timing error: ast happened while we were doing that.  */
2106  if (!detect_input_pending ())
2107    {
2108      /* No timing error: wait for flag to be set.  */
2109      set_waiting_for_input (0);
2110      SYS$WFLOR (input_ef, input_eflist);
2111      clear_waiting_for_input ();
2112      if (!detect_input_pending ())
2113	/* Check for subprocess input availability */
2114	{
2115	  int dsp = have_process_input || process_exited;
2116
2117	  SYS$CLREF (process_ef);
2118	  if (have_process_input)
2119	    process_command_input ();
2120	  if (process_exited)
2121	    process_exit ();
2122	  if (dsp)
2123	    {
2124	      update_mode_lines++;
2125	      prepare_menu_bars ();
2126	      redisplay_preserve_echo_area (18);
2127	    }
2128	}
2129    }
2130  waiting_for_ast = 0;
2131}
2132
2133/* Get rid of any pending QIO, when we are about to suspend
2134   or when we want to throw away pending input.
2135   We wait for a positive sign that the AST routine has run
2136   and therefore there is no I/O request queued when we return.
2137   SYS$SETAST is used to avoid a timing error.  */
2138
2139void
2140end_kbd_input ()
2141{
2142#ifdef ASTDEBUG
2143  printf ("At end_kbd_input.\n");
2144  fflush (stdout);
2145  sleep (1);
2146#endif
2147  if (LIB$AST_IN_PROG ())  /* Don't wait if suspending from kbd_buffer_store_event! */
2148    {
2149      SYS$CANCEL (input_fd);
2150      return;
2151    }
2152
2153  SYS$SETAST (0);
2154  /* Clear a flag, and tell ast routine above to set it.  */
2155  SYS$CLREF (input_ef);
2156  waiting_for_ast = 1;
2157  stop_input = 1;
2158  SYS$CANCEL (input_fd);
2159  SYS$SETAST (1);
2160  SYS$WAITFR (input_ef);
2161  waiting_for_ast = 0;
2162}
2163
2164/* Wait for either input available or time interval expiry.  */
2165
2166void
2167input_wait_timeout (timeval)
2168     int timeval;		/* Time to wait, in seconds */
2169{
2170  int time [2];
2171  static int zero = 0;
2172  static int large = -10000000;
2173
2174  LIB$EMUL (&timeval, &large, &zero, time); 	  /* Convert to VMS format */
2175
2176  /* If already something, avoid doing system calls.  */
2177  if (detect_input_pending ())
2178    {
2179      return;
2180    }
2181  /* Clear a flag, and tell ast routine above to set it.  */
2182  SYS$CLREF (input_ef);
2183  waiting_for_ast = 1;
2184  /* Check for timing error: ast happened while we were doing that.  */
2185  if (!detect_input_pending ())
2186    {
2187      /* No timing error: wait for flag to be set.  */
2188      SYS$CANTIM (1, 0);
2189      if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
2190	SYS$WFLOR (timer_ef, timer_eflist);	  /* Wait for timer expiry or input */
2191    }
2192  waiting_for_ast = 0;
2193}
2194
2195/* The standard `sleep' routine works some other way
2196   and it stops working if you have ever quit out of it.
2197   This one continues to work.  */
2198
2199sys_sleep (timeval)
2200     int timeval;
2201{
2202  int time [2];
2203  static int zero = 0;
2204  static int large = -10000000;
2205
2206  LIB$EMUL (&timeval, &large, &zero, time); 	  /* Convert to VMS format */
2207
2208  SYS$CANTIM (1, 0);
2209  if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
2210    SYS$WAITFR (timer_ef);	  /* Wait for timer expiry only */
2211}
2212
2213void
2214init_sigio (fd)
2215     int fd;
2216{
2217  request_sigio ();
2218}
2219
2220reset_sigio ()
2221{
2222  unrequest_sigio ();
2223}
2224
2225void
2226request_sigio ()
2227{
2228  if (noninteractive)
2229    return;
2230  croak ("request sigio");
2231}
2232
2233void
2234unrequest_sigio ()
2235{
2236  if (noninteractive)
2237    return;
2238  croak ("unrequest sigio");
2239}
2240
2241#endif /* VMS */
2242
2243/* Note that VMS compiler won't accept defined (CANNOT_DUMP).  */
2244#ifndef CANNOT_DUMP
2245#define NEED_STARTS
2246#endif
2247
2248#ifndef SYSTEM_MALLOC
2249#ifndef NEED_STARTS
2250#define NEED_STARTS
2251#endif
2252#endif
2253
2254#ifdef NEED_STARTS
2255/* Some systems that cannot dump also cannot implement these.  */
2256
2257/*
2258 *	Return the address of the start of the text segment prior to
2259 *	doing an unexec.  After unexec the return value is undefined.
2260 *	See crt0.c for further explanation and _start.
2261 *
2262 */
2263
2264#if !(defined (__NetBSD__) && defined (__ELF__))
2265#ifndef HAVE_TEXT_START
2266char *
2267start_of_text ()
2268{
2269#ifdef TEXT_START
2270  return ((char *) TEXT_START);
2271#else
2272#ifdef GOULD
2273  extern csrt ();
2274  return ((char *) csrt);
2275#else /* not GOULD */
2276  extern int _start ();
2277  return ((char *) _start);
2278#endif /* GOULD */
2279#endif /* TEXT_START */
2280}
2281#endif /* not HAVE_TEXT_START */
2282#endif
2283
2284/*
2285 *	Return the address of the start of the data segment prior to
2286 *	doing an unexec.  After unexec the return value is undefined.
2287 *	See crt0.c for further information and definition of data_start.
2288 *
2289 *	Apparently, on BSD systems this is etext at startup.  On
2290 *	USG systems (swapping) this is highly mmu dependent and
2291 *	is also dependent on whether or not the program is running
2292 *	with shared text.  Generally there is a (possibly large)
2293 *	gap between end of text and start of data with shared text.
2294 *
2295 *	On Uniplus+ systems with shared text, data starts at a
2296 *	fixed address.  Each port (from a given oem) is generally
2297 *	different, and the specific value of the start of data can
2298 *	be obtained via the UniPlus+ specific "uvar" system call,
2299 *	however the method outlined in crt0.c seems to be more portable.
2300 *
2301 *	Probably what will have to happen when a USG unexec is available,
2302 *	at least on UniPlus, is temacs will have to be made unshared so
2303 *	that text and data are contiguous.  Then once loadup is complete,
2304 *	unexec will produce a shared executable where the data can be
2305 *	at the normal shared text boundary and the startofdata variable
2306 *	will be patched by unexec to the correct value.
2307 *
2308 */
2309
2310#ifndef start_of_data
2311char *
2312start_of_data ()
2313{
2314#ifdef DATA_START
2315  return ((char *) DATA_START);
2316#else
2317#ifdef ORDINARY_LINK
2318  /*
2319   * This is a hack.  Since we're not linking crt0.c or pre_crt0.c,
2320   * data_start isn't defined.  We take the address of environ, which
2321   * is known to live at or near the start of the system crt0.c, and
2322   * we don't sweat the handful of bytes that might lose.
2323   */
2324  extern char **environ;
2325
2326  return ((char *) &environ);
2327#else
2328  extern int data_start;
2329  return ((char *) &data_start);
2330#endif /* ORDINARY_LINK */
2331#endif /* DATA_START */
2332}
2333#endif /* start_of_data */
2334#endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2335
2336/* init_system_name sets up the string for the Lisp function
2337   system-name to return. */
2338
2339#ifdef BSD4_1
2340#include <whoami.h>
2341#endif
2342
2343extern Lisp_Object Vsystem_name;
2344
2345#ifndef BSD4_1
2346#ifndef VMS
2347#ifdef HAVE_SOCKETS
2348#include <sys/socket.h>
2349#include <netdb.h>
2350#endif /* HAVE_SOCKETS */
2351#endif /* not VMS */
2352#endif /* not BSD4_1 */
2353
2354#ifdef TRY_AGAIN
2355#ifndef HAVE_H_ERRNO
2356extern int h_errno;
2357#endif
2358#endif /* TRY_AGAIN */
2359
2360void
2361init_system_name ()
2362{
2363#ifdef BSD4_1
2364  Vsystem_name = build_string (sysname);
2365#else
2366#ifdef VMS
2367  char *sp, *end;
2368  if ((sp = egetenv ("SYS$NODE")) == 0)
2369    Vsystem_name = build_string ("vax-vms");
2370  else if ((end = index (sp, ':')) == 0)
2371    Vsystem_name = build_string (sp);
2372  else
2373    Vsystem_name = make_string (sp, end - sp);
2374#else
2375#ifndef HAVE_GETHOSTNAME
2376  struct utsname uts;
2377  uname (&uts);
2378  Vsystem_name = build_string (uts.nodename);
2379#else /* HAVE_GETHOSTNAME */
2380  unsigned int hostname_size = 256;
2381  char *hostname = (char *) alloca (hostname_size);
2382
2383  /* Try to get the host name; if the buffer is too short, try
2384     again.  Apparently, the only indication gethostname gives of
2385     whether the buffer was large enough is the presence or absence
2386     of a '\0' in the string.  Eech.  */
2387  for (;;)
2388    {
2389      gethostname (hostname, hostname_size - 1);
2390      hostname[hostname_size - 1] = '\0';
2391
2392      /* Was the buffer large enough for the '\0'?  */
2393      if (strlen (hostname) < hostname_size - 1)
2394	break;
2395
2396      hostname_size <<= 1;
2397      hostname = (char *) alloca (hostname_size);
2398    }
2399#ifdef HAVE_SOCKETS
2400  /* Turn the hostname into the official, fully-qualified hostname.
2401     Don't do this if we're going to dump; this can confuse system
2402     libraries on some machines and make the dumped emacs core dump. */
2403#ifndef CANNOT_DUMP
2404  if (initialized)
2405#endif /* not CANNOT_DUMP */
2406    if (! index (hostname, '.'))
2407      {
2408	struct hostent *hp;
2409	int count;
2410	for (count = 0;; count++)
2411	  {
2412#ifdef TRY_AGAIN
2413	    h_errno = 0;
2414#endif
2415	    hp = gethostbyname (hostname);
2416#ifdef TRY_AGAIN
2417	    if (! (hp == 0 && h_errno == TRY_AGAIN))
2418#endif
2419	      break;
2420	    if (count >= 5)
2421	      break;
2422	    Fsleep_for (make_number (1), Qnil);
2423	  }
2424	if (hp)
2425	  {
2426	    char *fqdn = (char *) hp->h_name;
2427#if 0
2428	    char *p;
2429#endif
2430
2431	    if (!index (fqdn, '.'))
2432	      {
2433		/* We still don't have a fully qualified domain name.
2434		   Try to find one in the list of alternate names */
2435		char **alias = hp->h_aliases;
2436		while (*alias
2437		       && (!index (*alias, '.')
2438			   || !strcmp (*alias, "localhost.localdomain")))
2439		  alias++;
2440		if (*alias)
2441		  fqdn = *alias;
2442	      }
2443	    hostname = fqdn;
2444#if 0
2445	    /* Convert the host name to lower case.  */
2446	    /* Using ctype.h here would introduce a possible locale
2447	       dependence that is probably wrong for hostnames.  */
2448	    p = hostname;
2449	    while (*p)
2450	      {
2451		if (*p >= 'A' && *p <= 'Z')
2452		  *p += 'a' - 'A';
2453		p++;
2454	      }
2455#endif
2456	  }
2457      }
2458#endif /* HAVE_SOCKETS */
2459  /* We used to try using getdomainname here,
2460     but NIIBE Yutaka <gniibe@etl.go.jp> says that
2461     getdomainname gets the NIS/YP domain which often is not the same
2462     as in Internet domain name.  */
2463#if 0 /* Turned off because sysinfo is not really likely to return the
2464	 correct Internet domain.  */
2465#if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
2466  if (! index (hostname, '.'))
2467    {
2468      /* The hostname is not fully qualified.  Append the domain name.  */
2469
2470      int hostlen = strlen (hostname);
2471      int domain_size = 256;
2472
2473      for (;;)
2474	{
2475	  char *domain = (char *) alloca (domain_size + 1);
2476	  char *fqdn = (char *) alloca (hostlen + 1 + domain_size + 1);
2477	  int sys_domain_size = sysinfo (SI_SRPC_DOMAIN, domain, domain_size);
2478	  if (sys_domain_size <= 0)
2479	    break;
2480	  if (domain_size < sys_domain_size)
2481	    {
2482	      domain_size = sys_domain_size;
2483	      continue;
2484	    }
2485	  strcpy (fqdn, hostname);
2486	  if (domain[0] == '.')
2487	    strcpy (fqdn + hostlen, domain);
2488	  else if (domain[0] != 0)
2489	    {
2490	      fqdn[hostlen] = '.';
2491	      strcpy (fqdn + hostlen + 1, domain);
2492	    }
2493	  hostname = fqdn;
2494	  break;
2495	}
2496    }
2497#endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
2498#endif /* 0 */
2499  Vsystem_name = build_string (hostname);
2500#endif /* HAVE_GETHOSTNAME */
2501#endif /* VMS */
2502#endif /* BSD4_1 */
2503  {
2504    unsigned char *p;
2505    for (p = SDATA (Vsystem_name); *p; p++)
2506      if (*p == ' ' || *p == '\t')
2507	*p = '-';
2508  }
2509}
2510
2511#ifndef MSDOS
2512#ifndef VMS
2513#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2514
2515#include "sysselect.h"
2516#undef select
2517
2518#if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
2519/* Cause explanatory error message at compile time,
2520   since the select emulation is not good enough for X.  */
2521int *x = &x_windows_lose_if_no_select_system_call;
2522#endif
2523
2524/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2525 * Only checks read descriptors.
2526 */
2527/* How long to wait between checking fds in select */
2528#define SELECT_PAUSE 1
2529int select_alarmed;
2530
2531/* For longjmp'ing back to read_input_waiting.  */
2532
2533jmp_buf read_alarm_throw;
2534
2535/* Nonzero if the alarm signal should throw back to read_input_waiting.
2536   The read_socket_hook function sets this to 1 while it is waiting.  */
2537
2538int read_alarm_should_throw;
2539
2540SIGTYPE
2541select_alarm ()
2542{
2543  select_alarmed = 1;
2544#ifdef BSD4_1
2545  sigrelse (SIGALRM);
2546#else /* not BSD4_1 */
2547  signal (SIGALRM, SIG_IGN);
2548#endif /* not BSD4_1 */
2549  SIGNAL_THREAD_CHECK (SIGALRM);
2550  if (read_alarm_should_throw)
2551    longjmp (read_alarm_throw, 1);
2552}
2553
2554#ifndef WINDOWSNT
2555/* Only rfds are checked.  */
2556int
2557sys_select (nfds, rfds, wfds, efds, timeout)
2558     int nfds;
2559     SELECT_TYPE *rfds, *wfds, *efds;
2560     EMACS_TIME *timeout;
2561{
2562  int ravail = 0;
2563  SELECT_TYPE orfds;
2564  int timeoutval;
2565  int *local_timeout;
2566  extern int proc_buffered_char[];
2567#ifndef subprocesses
2568  int process_tick = 0, update_tick = 0;
2569#else
2570  extern int process_tick, update_tick;
2571#endif
2572  unsigned char buf;
2573
2574#if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2575  /* If we're using X, then the native select will work; we only need the
2576     emulation for non-X usage.  */
2577  if (!NILP (Vwindow_system))
2578    return select (nfds, rfds, wfds, efds, timeout);
2579#endif
2580  timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
2581  local_timeout = &timeoutval;
2582  FD_ZERO (&orfds);
2583  if (rfds)
2584    {
2585      orfds = *rfds;
2586      FD_ZERO (rfds);
2587    }
2588  if (wfds)
2589    FD_ZERO (wfds);
2590  if (efds)
2591    FD_ZERO (efds);
2592
2593  /* If we are looking only for the terminal, with no timeout,
2594     just read it and wait -- that's more efficient.  */
2595  if (*local_timeout == 100000 && process_tick == update_tick
2596      && FD_ISSET (0, &orfds))
2597    {
2598      int fd;
2599      for (fd = 1; fd < nfds; ++fd)
2600	if (FD_ISSET (fd, &orfds))
2601	  goto hardway;
2602      if (! detect_input_pending ())
2603	read_input_waiting ();
2604      FD_SET (0, rfds);
2605      return 1;
2606    }
2607
2608 hardway:
2609  /* Once a second, till the timer expires, check all the flagged read
2610   * descriptors to see if any input is available.  If there is some then
2611   * set the corresponding bit in the return copy of rfds.
2612   */
2613  while (1)
2614    {
2615      register int to_check, fd;
2616
2617      if (rfds)
2618	{
2619	  for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
2620	    {
2621	      if (FD_ISSET (fd, &orfds))
2622		{
2623		  int avail = 0, status = 0;
2624
2625		  if (fd == 0)
2626		    avail = detect_input_pending (); /* Special keyboard handler */
2627		  else
2628		    {
2629#ifdef FIONREAD
2630		      status = ioctl (fd, FIONREAD, &avail);
2631#else /* no FIONREAD */
2632		      /* Hoping it will return -1 if nothing available
2633			 or 0 if all 0 chars requested are read.  */
2634		      if (proc_buffered_char[fd] >= 0)
2635			avail = 1;
2636		      else
2637			{
2638			  avail = read (fd, &buf, 1);
2639			  if (avail > 0)
2640			    proc_buffered_char[fd] = buf;
2641			}
2642#endif /* no FIONREAD */
2643		    }
2644		  if (status >= 0 && avail > 0)
2645		    {
2646		      FD_SET (fd, rfds);
2647		      ravail++;
2648		    }
2649		}
2650	    }
2651	}
2652      if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
2653	break;
2654
2655      turn_on_atimers (0);
2656      signal (SIGALRM, select_alarm);
2657      select_alarmed = 0;
2658      alarm (SELECT_PAUSE);
2659
2660      /* Wait for a SIGALRM (or maybe a SIGTINT) */
2661      while (select_alarmed == 0 && *local_timeout != 0
2662	     && process_tick == update_tick)
2663	{
2664	  /* If we are interested in terminal input,
2665	     wait by reading the terminal.
2666	     That makes instant wakeup for terminal input at least.  */
2667	  if (FD_ISSET (0, &orfds))
2668	    {
2669	      read_input_waiting ();
2670	      if (detect_input_pending ())
2671		select_alarmed = 1;
2672	    }
2673	  else
2674	    pause ();
2675	}
2676      (*local_timeout) -= SELECT_PAUSE;
2677
2678      /* Reset the old alarm if there was one.  */
2679      turn_on_atimers (1);
2680
2681      if (*local_timeout == 0)  /* Stop on timer being cleared */
2682	break;
2683    }
2684  return ravail;
2685}
2686#endif /* not WINDOWSNT */
2687
2688/* Read keyboard input into the standard buffer,
2689   waiting for at least one character.  */
2690
2691void
2692read_input_waiting ()
2693{
2694  int nread, i;
2695  extern int quit_char;
2696
2697  if (read_socket_hook)
2698    {
2699      struct input_event hold_quit;
2700
2701      EVENT_INIT (hold_quit);
2702      hold_quit.kind = NO_EVENT;
2703
2704      read_alarm_should_throw = 0;
2705      if (! setjmp (read_alarm_throw))
2706	nread = (*read_socket_hook) (0, 1, &hold_quit);
2707      else
2708	nread = -1;
2709
2710      if (hold_quit.kind != NO_EVENT)
2711	kbd_buffer_store_event (&hold_quit);
2712    }
2713  else
2714    {
2715      struct input_event e;
2716      char buf[3];
2717      nread = read (fileno (stdin), buf, 1);
2718      EVENT_INIT (e);
2719
2720      /* Scan the chars for C-g and store them in kbd_buffer.  */
2721      e.kind = ASCII_KEYSTROKE_EVENT;
2722      e.frame_or_window = selected_frame;
2723      e.modifiers = 0;
2724      for (i = 0; i < nread; i++)
2725	{
2726	  /* Convert chars > 0177 to meta events if desired.
2727	     We do this under the same conditions that read_avail_input does.  */
2728	  if (read_socket_hook == 0)
2729	    {
2730	      /* If the user says she has a meta key, then believe her. */
2731	      if (meta_key == 1 && (buf[i] & 0x80))
2732		e.modifiers = meta_modifier;
2733	      if (meta_key != 2)
2734		buf[i] &= ~0x80;
2735	    }
2736
2737	  XSETINT (e.code, buf[i]);
2738	  kbd_buffer_store_event (&e);
2739	  /* Don't look at input that follows a C-g too closely.
2740	     This reduces lossage due to autorepeat on C-g.  */
2741	  if (buf[i] == quit_char)
2742	    break;
2743	}
2744    }
2745}
2746
2747#endif /* not HAVE_SELECT */
2748#endif /* not VMS */
2749#endif /* not MSDOS */
2750
2751#ifdef BSD4_1
2752void
2753init_sigio (fd)
2754     int fd;
2755{
2756  if (noninteractive)
2757    return;
2758  lmode = LINTRUP | lmode;
2759  ioctl (fd, TIOCLSET, &lmode);
2760}
2761
2762void
2763reset_sigio ()
2764{
2765  if (noninteractive)
2766    return;
2767  lmode = ~LINTRUP & lmode;
2768  ioctl (0, TIOCLSET, &lmode);
2769}
2770
2771void
2772request_sigio ()
2773{
2774  if (noninteractive)
2775    return;
2776  sigrelse (SIGTINT);
2777
2778  interrupts_deferred = 0;
2779}
2780
2781void
2782unrequest_sigio ()
2783{
2784  if (noninteractive)
2785    return;
2786  sighold (SIGTINT);
2787
2788  interrupts_deferred = 1;
2789}
2790
2791/* still inside #ifdef BSD4_1 */
2792#ifdef subprocesses
2793
2794int sigheld; /* Mask of held signals */
2795
2796void
2797sigholdx (signum)
2798     int signum;
2799{
2800  sigheld |= sigbit (signum);
2801  sighold (signum);
2802}
2803
2804void
2805sigisheld (signum)
2806     int signum;
2807{
2808  sigheld |= sigbit (signum);
2809}
2810
2811void
2812sigunhold (signum)
2813     int signum;
2814{
2815  sigheld &= ~sigbit (signum);
2816  sigrelse (signum);
2817}
2818
2819void
2820sigfree ()    /* Free all held signals */
2821{
2822  int i;
2823  for (i = 0; i < NSIG; i++)
2824    if (sigheld & sigbit (i))
2825      sigrelse (i);
2826  sigheld = 0;
2827}
2828
2829int
2830sigbit (i)
2831{
2832  return 1 << (i - 1);
2833}
2834#endif /* subprocesses */
2835#endif /* BSD4_1 */
2836
2837/* POSIX signals support - DJB */
2838/* Anyone with POSIX signals should have ANSI C declarations */
2839
2840#ifdef POSIX_SIGNALS
2841
2842sigset_t empty_mask, full_mask;
2843
2844signal_handler_t
2845sys_signal (int signal_number, signal_handler_t action)
2846{
2847  struct sigaction new_action, old_action;
2848  sigemptyset (&new_action.sa_mask);
2849  new_action.sa_handler = action;
2850#if defined (SA_RESTART) && ! defined (BROKEN_SA_RESTART) && !defined(SYNC_INPUT)
2851  /* Emacs mostly works better with restartable system services. If this
2852     flag exists, we probably want to turn it on here.
2853     However, on some systems this resets the timeout of `select'
2854     which means that `select' never finishes if it keeps getting signals.
2855     BROKEN_SA_RESTART is defined on those systems.  */
2856  /* It's not clear why the comment above says "mostly works better".  --Stef
2857     When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
2858     for pending input so we need long-running syscalls to be interrupted
2859     after a signal that sets the interrupt_input_pending flag.  */
2860  new_action.sa_flags = SA_RESTART;
2861#else
2862  new_action.sa_flags = 0;
2863#endif
2864  sigaction (signal_number, &new_action, &old_action);
2865  return (old_action.sa_handler);
2866}
2867
2868#ifndef __GNUC__
2869/* If we're compiling with GCC, we don't need this function, since it
2870   can be written as a macro.  */
2871sigset_t
2872sys_sigmask (int sig)
2873{
2874  sigset_t mask;
2875  sigemptyset (&mask);
2876  sigaddset (&mask, sig);
2877  return mask;
2878}
2879#endif
2880
2881/* I'd like to have these guys return pointers to the mask storage in here,
2882   but there'd be trouble if the code was saving multiple masks.  I'll be
2883   safe and pass the structure.  It normally won't be more than 2 bytes
2884   anyhow. - DJB */
2885
2886sigset_t
2887sys_sigblock (sigset_t new_mask)
2888{
2889  sigset_t old_mask;
2890  sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2891  return (old_mask);
2892}
2893
2894sigset_t
2895sys_sigunblock (sigset_t new_mask)
2896{
2897  sigset_t old_mask;
2898  sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2899  return (old_mask);
2900}
2901
2902sigset_t
2903sys_sigsetmask (sigset_t new_mask)
2904{
2905  sigset_t old_mask;
2906  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2907  return (old_mask);
2908}
2909
2910#endif /* POSIX_SIGNALS */
2911
2912#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
2913static char *my_sys_siglist[NSIG];
2914# ifdef sys_siglist
2915#  undef sys_siglist
2916# endif
2917# define sys_siglist my_sys_siglist
2918#endif
2919
2920void
2921init_signals ()
2922{
2923#ifdef POSIX_SIGNALS
2924  sigemptyset (&empty_mask);
2925  sigfillset (&full_mask);
2926#endif
2927
2928#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
2929  if (! initialized)
2930    {
2931# ifdef SIGABRT
2932      sys_siglist[SIGABRT] = "Aborted";
2933# endif
2934# ifdef SIGAIO
2935      sys_siglist[SIGAIO] = "LAN I/O interrupt";
2936# endif
2937# ifdef SIGALRM
2938      sys_siglist[SIGALRM] = "Alarm clock";
2939# endif
2940# ifdef SIGBUS
2941      sys_siglist[SIGBUS] = "Bus error";
2942# endif
2943# ifdef SIGCLD
2944      sys_siglist[SIGCLD] = "Child status changed";
2945# endif
2946# ifdef SIGCHLD
2947      sys_siglist[SIGCHLD] = "Child status changed";
2948# endif
2949# ifdef SIGCONT
2950      sys_siglist[SIGCONT] = "Continued";
2951# endif
2952# ifdef SIGDANGER
2953      sys_siglist[SIGDANGER] = "Swap space dangerously low";
2954# endif
2955# ifdef SIGDGNOTIFY
2956      sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
2957# endif
2958# ifdef SIGEMT
2959      sys_siglist[SIGEMT] = "Emulation trap";
2960# endif
2961# ifdef SIGFPE
2962      sys_siglist[SIGFPE] = "Arithmetic exception";
2963# endif
2964# ifdef SIGFREEZE
2965      sys_siglist[SIGFREEZE] = "SIGFREEZE";
2966# endif
2967# ifdef SIGGRANT
2968      sys_siglist[SIGGRANT] = "Monitor mode granted";
2969# endif
2970# ifdef SIGHUP
2971      sys_siglist[SIGHUP] = "Hangup";
2972# endif
2973# ifdef SIGILL
2974      sys_siglist[SIGILL] = "Illegal instruction";
2975# endif
2976# ifdef SIGINT
2977      sys_siglist[SIGINT] = "Interrupt";
2978# endif
2979# ifdef SIGIO
2980      sys_siglist[SIGIO] = "I/O possible";
2981# endif
2982# ifdef SIGIOINT
2983      sys_siglist[SIGIOINT] = "I/O intervention required";
2984# endif
2985# ifdef SIGIOT
2986      sys_siglist[SIGIOT] = "IOT trap";
2987# endif
2988# ifdef SIGKILL
2989      sys_siglist[SIGKILL] = "Killed";
2990# endif
2991# ifdef SIGLOST
2992      sys_siglist[SIGLOST] = "Resource lost";
2993# endif
2994# ifdef SIGLWP
2995      sys_siglist[SIGLWP] = "SIGLWP";
2996# endif
2997# ifdef SIGMSG
2998      sys_siglist[SIGMSG] = "Monitor mode data available";
2999# endif
3000# ifdef SIGPHONE
3001      sys_siglist[SIGWIND] = "SIGPHONE";
3002# endif
3003# ifdef SIGPIPE
3004      sys_siglist[SIGPIPE] = "Broken pipe";
3005# endif
3006# ifdef SIGPOLL
3007      sys_siglist[SIGPOLL] = "Pollable event occurred";
3008# endif
3009# ifdef SIGPROF
3010      sys_siglist[SIGPROF] = "Profiling timer expired";
3011# endif
3012# ifdef SIGPTY
3013      sys_siglist[SIGPTY] = "PTY I/O interrupt";
3014# endif
3015# ifdef SIGPWR
3016      sys_siglist[SIGPWR] = "Power-fail restart";
3017# endif
3018# ifdef SIGQUIT
3019      sys_siglist[SIGQUIT] = "Quit";
3020# endif
3021# ifdef SIGRETRACT
3022      sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
3023# endif
3024# ifdef SIGSAK
3025      sys_siglist[SIGSAK] = "Secure attention";
3026# endif
3027# ifdef SIGSEGV
3028      sys_siglist[SIGSEGV] = "Segmentation violation";
3029# endif
3030# ifdef SIGSOUND
3031      sys_siglist[SIGSOUND] = "Sound completed";
3032# endif
3033# ifdef SIGSTOP
3034      sys_siglist[SIGSTOP] = "Stopped (signal)";
3035# endif
3036# ifdef SIGSTP
3037      sys_siglist[SIGSTP] = "Stopped (user)";
3038# endif
3039# ifdef SIGSYS
3040      sys_siglist[SIGSYS] = "Bad argument to system call";
3041# endif
3042# ifdef SIGTERM
3043      sys_siglist[SIGTERM] = "Terminated";
3044# endif
3045# ifdef SIGTHAW
3046      sys_siglist[SIGTHAW] = "SIGTHAW";
3047# endif
3048# ifdef SIGTRAP
3049      sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
3050# endif
3051# ifdef SIGTSTP
3052      sys_siglist[SIGTSTP] = "Stopped (user)";
3053# endif
3054# ifdef SIGTTIN
3055      sys_siglist[SIGTTIN] = "Stopped (tty input)";
3056# endif
3057# ifdef SIGTTOU
3058      sys_siglist[SIGTTOU] = "Stopped (tty output)";
3059# endif
3060# ifdef SIGURG
3061      sys_siglist[SIGURG] = "Urgent I/O condition";
3062# endif
3063# ifdef SIGUSR1
3064      sys_siglist[SIGUSR1] = "User defined signal 1";
3065# endif
3066# ifdef SIGUSR2
3067      sys_siglist[SIGUSR2] = "User defined signal 2";
3068# endif
3069# ifdef SIGVTALRM
3070      sys_siglist[SIGVTALRM] = "Virtual timer expired";
3071# endif
3072# ifdef SIGWAITING
3073      sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
3074# endif
3075# ifdef SIGWINCH
3076      sys_siglist[SIGWINCH] = "Window size changed";
3077# endif
3078# ifdef SIGWIND
3079      sys_siglist[SIGWIND] = "SIGWIND";
3080# endif
3081# ifdef SIGXCPU
3082      sys_siglist[SIGXCPU] = "CPU time limit exceeded";
3083# endif
3084# ifdef SIGXFSZ
3085      sys_siglist[SIGXFSZ] = "File size limit exceeded";
3086# endif
3087    }
3088#endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
3089}
3090
3091#ifndef HAVE_RANDOM
3092#ifdef random
3093#define HAVE_RANDOM
3094#endif
3095#endif
3096
3097/* Figure out how many bits the system's random number generator uses.
3098   `random' and `lrand48' are assumed to return 31 usable bits.
3099   BSD `rand' returns a 31 bit value but the low order bits are unusable;
3100   so we'll shift it and treat it like the 15-bit USG `rand'.  */
3101
3102#ifndef RAND_BITS
3103# ifdef HAVE_RANDOM
3104#  define RAND_BITS 31
3105# else /* !HAVE_RANDOM */
3106#  ifdef HAVE_LRAND48
3107#   define RAND_BITS 31
3108#   define random lrand48
3109#  else /* !HAVE_LRAND48 */
3110#   define RAND_BITS 15
3111#   if RAND_MAX == 32767
3112#    define random rand
3113#   else /* RAND_MAX != 32767 */
3114#    if RAND_MAX == 2147483647
3115#     define random() (rand () >> 16)
3116#    else /* RAND_MAX != 2147483647 */
3117#     ifdef USG
3118#      define random rand
3119#     else
3120#      define random() (rand () >> 16)
3121#     endif /* !USG */
3122#    endif /* RAND_MAX != 2147483647 */
3123#   endif /* RAND_MAX != 32767 */
3124#  endif /* !HAVE_LRAND48 */
3125# endif /* !HAVE_RANDOM */
3126#endif /* !RAND_BITS */
3127
3128void
3129seed_random (arg)
3130     long arg;
3131{
3132#ifdef HAVE_RANDOM
3133  srandom ((unsigned int)arg);
3134#else
3135# ifdef HAVE_LRAND48
3136  srand48 (arg);
3137# else
3138  srand ((unsigned int)arg);
3139# endif
3140#endif
3141}
3142
3143/*
3144 * Build a full Emacs-sized word out of whatever we've got.
3145 * This suffices even for a 64-bit architecture with a 15-bit rand.
3146 */
3147long
3148get_random ()
3149{
3150  long val = random ();
3151#if VALBITS > RAND_BITS
3152  val = (val << RAND_BITS) ^ random ();
3153#if VALBITS > 2*RAND_BITS
3154  val = (val << RAND_BITS) ^ random ();
3155#if VALBITS > 3*RAND_BITS
3156  val = (val << RAND_BITS) ^ random ();
3157#if VALBITS > 4*RAND_BITS
3158  val = (val << RAND_BITS) ^ random ();
3159#endif /* need at least 5 */
3160#endif /* need at least 4 */
3161#endif /* need at least 3 */
3162#endif /* need at least 2 */
3163  return val & ((1L << VALBITS) - 1);
3164}
3165
3166#ifdef WRONG_NAME_INSQUE
3167
3168insque (q,p)
3169     caddr_t q,p;
3170{
3171  _insque (q,p);
3172}
3173
3174#endif
3175
3176#ifdef VMS
3177
3178#ifdef getenv
3179/* If any place else asks for the TERM variable,
3180   allow it to be overridden with the EMACS_TERM variable
3181   before attempting to translate the logical name TERM.  As a last
3182   resort, ask for VAX C's special idea of the TERM variable.  */
3183#undef getenv
3184char *
3185sys_getenv (name)
3186     char *name;
3187{
3188  register char *val;
3189  static char buf[256];
3190  static struct dsc$descriptor_s equiv
3191    = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
3192  static struct dsc$descriptor_s d_name
3193    = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
3194  short eqlen;
3195
3196  if (!strcmp (name, "TERM"))
3197    {
3198      val = (char *) getenv ("EMACS_TERM");
3199      if (val)
3200	return val;
3201    }
3202
3203  d_name.dsc$w_length = strlen (name);
3204  d_name.dsc$a_pointer = name;
3205  if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
3206    {
3207      char *str = (char *) xmalloc (eqlen + 1);
3208      bcopy (buf, str, eqlen);
3209      str[eqlen] = '\0';
3210      /* This is a storage leak, but a pain to fix.  With luck,
3211	 no one will ever notice.  */
3212      return str;
3213    }
3214  return (char *) getenv (name);
3215}
3216#endif /* getenv */
3217
3218#ifdef abort
3219/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3220   to force a call on the debugger from within the image. */
3221#undef abort
3222sys_abort ()
3223{
3224  reset_sys_modes ();
3225  LIB$SIGNAL (SS$_DEBUG);
3226}
3227#endif /* abort */
3228#endif /* VMS */
3229
3230#ifdef VMS
3231#ifdef LINK_CRTL_SHARE
3232#ifdef SHARABLE_LIB_BUG
3233/* Variables declared noshare and initialized in sharable libraries
3234   cannot be shared.  The VMS linker incorrectly forces you to use a private
3235   version which is uninitialized... If not for this "feature", we
3236   could use the C library definition of sys_nerr and sys_errlist. */
3237int sys_nerr = 35;
3238char *sys_errlist[] =
3239  {
3240    "error 0",
3241    "not owner",
3242    "no such file or directory",
3243    "no such process",
3244    "interrupted system call",
3245    "i/o error",
3246    "no such device or address",
3247    "argument list too long",
3248    "exec format error",
3249    "bad file number",
3250    "no child process",
3251    "no more processes",
3252    "not enough memory",
3253    "permission denied",
3254    "bad address",
3255    "block device required",
3256    "mount devices busy",
3257    "file exists",
3258    "cross-device link",
3259    "no such device",
3260    "not a directory",
3261    "is a directory",
3262    "invalid argument",
3263    "file table overflow",
3264    "too many open files",
3265    "not a typewriter",
3266    "text file busy",
3267    "file too big",
3268    "no space left on device",
3269    "illegal seek",
3270    "read-only file system",
3271    "too many links",
3272    "broken pipe",
3273    "math argument",
3274    "result too large",
3275    "I/O stream empty",
3276    "vax/vms specific error code nontranslatable error"
3277  };
3278#endif /* SHARABLE_LIB_BUG */
3279#endif /* LINK_CRTL_SHARE */
3280#endif /* VMS */
3281
3282#ifndef HAVE_STRERROR
3283#ifndef WINDOWSNT
3284char *
3285strerror (errnum)
3286     int errnum;
3287{
3288  extern char *sys_errlist[];
3289  extern int sys_nerr;
3290
3291  if (errnum >= 0 && errnum < sys_nerr)
3292    return sys_errlist[errnum];
3293  return (char *) "Unknown error";
3294}
3295#endif /* not WINDOWSNT */
3296#endif /* ! HAVE_STRERROR */
3297
3298int
3299emacs_open (path, oflag, mode)
3300     const char *path;
3301     int oflag, mode;
3302{
3303  register int rtnval;
3304
3305#ifdef BSD4_1
3306  if (oflag & O_CREAT)
3307    return creat (path, mode);
3308#endif
3309
3310  while ((rtnval = open (path, oflag, mode)) == -1
3311	 && (errno == EINTR))
3312    QUIT;
3313  return (rtnval);
3314}
3315
3316int
3317emacs_close (fd)
3318     int fd;
3319{
3320  int did_retry = 0;
3321  register int rtnval;
3322
3323  while ((rtnval = close (fd)) == -1
3324	 && (errno == EINTR))
3325    did_retry = 1;
3326
3327  /* If close is interrupted SunOS 4.1 may or may not have closed the
3328     file descriptor.  If it did the second close will fail with
3329     errno = EBADF.  That means we have succeeded.  */
3330  if (rtnval == -1 && did_retry && errno == EBADF)
3331    return 0;
3332
3333  return rtnval;
3334}
3335
3336int
3337emacs_read (fildes, buf, nbyte)
3338     int fildes;
3339     char *buf;
3340     unsigned int nbyte;
3341{
3342  register int rtnval;
3343
3344  while ((rtnval = read (fildes, buf, nbyte)) == -1
3345	 && (errno == EINTR))
3346    QUIT;
3347  return (rtnval);
3348}
3349
3350int
3351emacs_write (fildes, buf, nbyte)
3352     int fildes;
3353     const char *buf;
3354     unsigned int nbyte;
3355{
3356  register int rtnval, bytes_written;
3357
3358  bytes_written = 0;
3359
3360  while (nbyte > 0)
3361    {
3362      rtnval = write (fildes, buf, nbyte);
3363
3364      if (rtnval == -1)
3365	{
3366	  if (errno == EINTR)
3367	    {
3368#ifdef SYNC_INPUT
3369	      /* I originally used `QUIT' but that might causes files to
3370		 be truncated if you hit C-g in the middle of it.  --Stef  */
3371	      if (interrupt_input_pending)
3372		handle_async_input ();
3373#endif
3374	      continue;
3375	    }
3376	  else
3377	    return (bytes_written ? bytes_written : -1);
3378	}
3379
3380      buf += rtnval;
3381      nbyte -= rtnval;
3382      bytes_written += rtnval;
3383    }
3384  return (bytes_written);
3385}
3386
3387#ifdef USG
3388/*
3389 *	All of the following are for USG.
3390 *
3391 *	On USG systems the system calls are INTERRUPTIBLE by signals
3392 *	that the user program has elected to catch.  Thus the system call
3393 *	must be retried in these cases.  To handle this without massive
3394 *	changes in the source code, we remap the standard system call names
3395 *	to names for our own functions in sysdep.c that do the system call
3396 *	with retries.  Actually, for portability reasons, it is good
3397 *	programming practice, as this example shows, to limit all actual
3398 *	system calls to a single occurrence in the source.  Sure, this
3399 *	adds an extra level of function call overhead but it is almost
3400 *	always negligible.   Fred Fish, Unisoft Systems Inc.
3401 */
3402
3403/*
3404 *	Warning, this function may not duplicate 4.2 action properly
3405 *	under error conditions.
3406 */
3407
3408#ifndef MAXPATHLEN
3409/* In 4.1, param.h fails to define this.  */
3410#define MAXPATHLEN 1024
3411#endif
3412
3413#ifndef HAVE_GETWD
3414
3415char *
3416getwd (pathname)
3417     char *pathname;
3418{
3419  char *npath, *spath;
3420  extern char *getcwd ();
3421
3422  BLOCK_INPUT;			/* getcwd uses malloc */
3423  spath = npath = getcwd ((char *) 0, MAXPATHLEN);
3424  if (spath == 0)
3425    {
3426      UNBLOCK_INPUT;
3427      return spath;
3428    }
3429  /* On Altos 3068, getcwd can return @hostname/dir, so discard
3430     up to first slash.  Should be harmless on other systems.  */
3431  while (*npath && *npath != '/')
3432    npath++;
3433  strcpy (pathname, npath);
3434  free (spath);			/* getcwd uses malloc */
3435  UNBLOCK_INPUT;
3436  return pathname;
3437}
3438
3439#endif /* HAVE_GETWD */
3440
3441/*
3442 *	Emulate rename using unlink/link.  Note that this is
3443 *	only partially correct.  Also, doesn't enforce restriction
3444 *	that files be of same type (regular->regular, dir->dir, etc).
3445 */
3446
3447#ifndef HAVE_RENAME
3448
3449rename (from, to)
3450     const char *from;
3451     const char *to;
3452{
3453  if (access (from, 0) == 0)
3454    {
3455      unlink (to);
3456      if (link (from, to) == 0)
3457	if (unlink (from) == 0)
3458	  return (0);
3459    }
3460  return (-1);
3461}
3462
3463#endif
3464
3465
3466#ifdef HPUX
3467#ifndef HAVE_PERROR
3468
3469/* HPUX curses library references perror, but as far as we know
3470   it won't be called.  Anyway this definition will do for now.  */
3471
3472perror ()
3473{
3474}
3475
3476#endif /* not HAVE_PERROR */
3477#endif /* HPUX */
3478
3479#ifndef HAVE_DUP2
3480
3481/*
3482 *	Emulate BSD dup2.  First close newd if it already exists.
3483 *	Then, attempt to dup oldd.  If not successful, call dup2 recursively
3484 *	until we are, then close the unsuccessful ones.
3485 */
3486
3487dup2 (oldd, newd)
3488     int oldd;
3489     int newd;
3490{
3491  register int fd, ret;
3492
3493  emacs_close (newd);
3494
3495#ifdef F_DUPFD
3496  return fcntl (oldd, F_DUPFD, newd);
3497#else
3498  fd = dup (old);
3499  if (fd == -1)
3500    return -1;
3501  if (fd == new)
3502    return new;
3503  ret = dup2 (old,new);
3504  emacs_close (fd);
3505  return ret;
3506#endif
3507}
3508
3509#endif /* not HAVE_DUP2 */
3510
3511/*
3512 *	Gettimeofday.  Simulate as much as possible.  Only accurate
3513 *	to nearest second.  Emacs doesn't use tzp so ignore it for now.
3514 *	Only needed when subprocesses are defined.
3515 */
3516
3517#ifdef subprocesses
3518#ifndef VMS
3519#ifndef HAVE_GETTIMEOFDAY
3520#ifdef HAVE_TIMEVAL
3521
3522/* ARGSUSED */
3523int
3524gettimeofday (tp, tzp)
3525     struct timeval *tp;
3526     struct timezone *tzp;
3527{
3528  extern long time ();
3529
3530  tp->tv_sec = time ((long *)0);
3531  tp->tv_usec = 0;
3532  if (tzp != 0)
3533    tzp->tz_minuteswest = -1;
3534  return 0;
3535}
3536
3537#endif
3538#endif
3539#endif
3540#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3541
3542/*
3543 *	This function will go away as soon as all the stubs fixed. (fnf)
3544 */
3545
3546void
3547croak (badfunc)
3548     char *badfunc;
3549{
3550  printf ("%s not yet implemented\r\n", badfunc);
3551  reset_sys_modes ();
3552  exit (1);
3553}
3554
3555#endif /* USG */
3556
3557/* Directory routines for systems that don't have them. */
3558
3559#ifdef SYSV_SYSTEM_DIR
3560
3561#include <dirent.h>
3562
3563#if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3564
3565int
3566closedir (dirp)
3567     register DIR *dirp;              /* stream from opendir */
3568{
3569  int rtnval;
3570
3571  rtnval = emacs_close (dirp->dd_fd);
3572
3573  /* Some systems (like Solaris) allocate the buffer and the DIR all
3574     in one block.  Why in the world are we freeing this ourselves
3575     anyway?  */
3576#if ! (defined (sun) && defined (USG5_4))
3577  xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
3578#endif
3579  xfree ((char *) dirp);
3580
3581  return rtnval;
3582}
3583#endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3584#endif /* SYSV_SYSTEM_DIR */
3585
3586#ifdef NONSYSTEM_DIR_LIBRARY
3587
3588DIR *
3589opendir (filename)
3590     char *filename;	/* name of directory */
3591{
3592  register DIR *dirp;		/* -> malloc'ed storage */
3593  register int fd;		/* file descriptor for read */
3594  struct stat sbuf;		/* result of fstat */
3595
3596  fd = emacs_open (filename, O_RDONLY, 0);
3597  if (fd < 0)
3598    return 0;
3599
3600  BLOCK_INPUT;
3601  if (fstat (fd, &sbuf) < 0
3602      || (sbuf.st_mode & S_IFMT) != S_IFDIR
3603      || (dirp = (DIR *) xmalloc (sizeof (DIR))) == 0)
3604    {
3605      emacs_close (fd);
3606      UNBLOCK_INPUT;
3607      return 0;		/* bad luck today */
3608    }
3609  UNBLOCK_INPUT;
3610
3611  dirp->dd_fd = fd;
3612  dirp->dd_loc = dirp->dd_size = 0;	/* refill needed */
3613
3614  return dirp;
3615}
3616
3617void
3618closedir (dirp)
3619     register DIR *dirp;		/* stream from opendir */
3620{
3621  emacs_close (dirp->dd_fd);
3622  xfree ((char *) dirp);
3623}
3624
3625
3626#ifndef VMS
3627#define DIRSIZ	14
3628struct olddir
3629  {
3630    ino_t od_ino; 		/* inode */
3631    char od_name[DIRSIZ];	/* filename */
3632  };
3633#endif /* not VMS */
3634
3635struct direct dir_static;	/* simulated directory contents */
3636
3637/* ARGUSED */
3638struct direct *
3639readdir (dirp)
3640     register DIR *dirp;	/* stream from opendir */
3641{
3642#ifndef VMS
3643  register struct olddir *dp;	/* -> directory data */
3644#else /* VMS */
3645  register struct dir$_name *dp; /* -> directory data */
3646  register struct dir$_version *dv; /* -> version data */
3647#endif /* VMS */
3648
3649  for (; ;)
3650    {
3651      if (dirp->dd_loc >= dirp->dd_size)
3652	dirp->dd_loc = dirp->dd_size = 0;
3653
3654      if (dirp->dd_size == 0 	/* refill buffer */
3655	  && (dirp->dd_size = emacs_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3656	return 0;
3657
3658#ifndef VMS
3659      dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3660      dirp->dd_loc += sizeof (struct olddir);
3661
3662      if (dp->od_ino != 0)	/* not deleted entry */
3663	{
3664	  dir_static.d_ino = dp->od_ino;
3665	  strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3666	  dir_static.d_name[DIRSIZ] = '\0';
3667	  dir_static.d_namlen = strlen (dir_static.d_name);
3668	  dir_static.d_reclen = sizeof (struct direct)
3669	    - MAXNAMLEN + 3
3670	      + dir_static.d_namlen - dir_static.d_namlen % 4;
3671	  return &dir_static;	/* -> simulated structure */
3672	}
3673#else /* VMS */
3674      dp = (struct dir$_name *) dirp->dd_buf;
3675      if (dirp->dd_loc == 0)
3676	dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3677	  : dp->dir$b_namecount;
3678      dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3679      dir_static.d_ino = dv->dir$w_fid_num;
3680      dir_static.d_namlen = dp->dir$b_namecount;
3681      dir_static.d_reclen = sizeof (struct direct)
3682	- MAXNAMLEN + 3
3683	  + dir_static.d_namlen - dir_static.d_namlen % 4;
3684      strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3685      dir_static.d_name[dir_static.d_namlen] = '\0';
3686      dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3687      return &dir_static;
3688#endif /* VMS */
3689    }
3690}
3691
3692#ifdef VMS
3693/* readdirver is just like readdir except it returns all versions of a file
3694   as separate entries.  */
3695
3696/* ARGUSED */
3697struct direct *
3698readdirver (dirp)
3699     register DIR *dirp;	/* stream from opendir */
3700{
3701  register struct dir$_name *dp; /* -> directory data */
3702  register struct dir$_version *dv; /* -> version data */
3703
3704  if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3705    dirp->dd_loc = dirp->dd_size = 0;
3706
3707  if (dirp->dd_size == 0 	/* refill buffer */
3708      && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3709    return 0;
3710
3711  dp = (struct dir$_name *) dirp->dd_buf;
3712  if (dirp->dd_loc == 0)
3713    dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3714		   : dp->dir$b_namecount;
3715  dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3716  strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3717  sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3718  dir_static.d_namlen = strlen (dir_static.d_name);
3719  dir_static.d_ino = dv->dir$w_fid_num;
3720  dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3721			+ dir_static.d_namlen - dir_static.d_namlen % 4;
3722  dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3723  return &dir_static;
3724}
3725
3726#endif /* VMS */
3727
3728#endif /* NONSYSTEM_DIR_LIBRARY */
3729
3730
3731int
3732set_file_times (filename, atime, mtime)
3733     const char *filename;
3734     EMACS_TIME atime, mtime;
3735{
3736#ifdef HAVE_UTIMES
3737  struct timeval tv[2];
3738  tv[0] = atime;
3739  tv[1] = mtime;
3740  return utimes (filename, tv);
3741#else /* not HAVE_UTIMES */
3742  struct utimbuf utb;
3743  utb.actime = EMACS_SECS (atime);
3744  utb.modtime = EMACS_SECS (mtime);
3745  return utime (filename, &utb);
3746#endif /* not HAVE_UTIMES */
3747}
3748
3749/* mkdir and rmdir functions, for systems which don't have them.  */
3750
3751#ifndef HAVE_MKDIR
3752/*
3753 * Written by Robert Rother, Mariah Corporation, August 1985.
3754 *
3755 * If you want it, it's yours.  All I ask in return is that if you
3756 * figure out how to do this in a Bourne Shell script you send me
3757 * a copy.
3758 *					sdcsvax!rmr or rmr@uscd
3759 *
3760 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3761 * subroutine.  11Mar86; hoptoad!gnu
3762 *
3763 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3764 * subroutine didn't return EEXIST.  It does now.
3765 */
3766
3767/*
3768 * Make a directory.
3769 */
3770#ifdef MKDIR_PROTOTYPE
3771MKDIR_PROTOTYPE
3772#else
3773int
3774mkdir (dpath, dmode)
3775     char *dpath;
3776     int dmode;
3777#endif
3778{
3779  int cpid, status, fd;
3780  struct stat statbuf;
3781
3782  if (stat (dpath, &statbuf) == 0)
3783    {
3784      errno = EEXIST;		/* Stat worked, so it already exists */
3785      return -1;
3786    }
3787
3788  /* If stat fails for a reason other than non-existence, return error */
3789  if (errno != ENOENT)
3790    return -1;
3791
3792  synch_process_alive = 1;
3793  switch (cpid = fork ())
3794    {
3795
3796    case -1:			/* Error in fork */
3797      return (-1);		/* Errno is set already */
3798
3799    case 0:			/* Child process */
3800      /*
3801		 * Cheap hack to set mode of new directory.  Since this
3802		 * child process is going away anyway, we zap its umask.
3803		 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3804		 * directory.  Does anybody care?
3805		 */
3806      status = umask (0);	/* Get current umask */
3807      status = umask (status | (0777 & ~dmode));	/* Set for mkdir */
3808      fd = emacs_open ("/dev/null", O_RDWR, 0);
3809      if (fd >= 0)
3810        {
3811	  dup2 (fd, 0);
3812	  dup2 (fd, 1);
3813	  dup2 (fd, 2);
3814        }
3815      execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
3816      _exit (-1);		/* Can't exec /bin/mkdir */
3817
3818    default:			/* Parent process */
3819      wait_for_termination (cpid);
3820    }
3821
3822  if (synch_process_death != 0 || synch_process_retcode != 0
3823      || synch_process_termsig != 0)
3824    {
3825      errno = EIO;		/* We don't know why, but */
3826      return -1;		/* /bin/mkdir failed */
3827    }
3828
3829  return 0;
3830}
3831#endif /* not HAVE_MKDIR */
3832
3833#ifndef HAVE_RMDIR
3834int
3835rmdir (dpath)
3836     char *dpath;
3837{
3838  int cpid, status, fd;
3839  struct stat statbuf;
3840
3841  if (stat (dpath, &statbuf) != 0)
3842    {
3843      /* Stat just set errno.  We don't have to */
3844      return -1;
3845    }
3846
3847  synch_process_alive = 1;
3848  switch (cpid = fork ())
3849    {
3850
3851    case -1:			/* Error in fork */
3852      return (-1);		/* Errno is set already */
3853
3854    case 0:			/* Child process */
3855      fd = emacs_open ("/dev/null", O_RDWR, 0);
3856      if (fd >= 0)
3857        {
3858	  dup2 (fd, 0);
3859	  dup2 (fd, 1);
3860	  dup2 (fd, 2);
3861        }
3862      execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
3863      _exit (-1);		/* Can't exec /bin/rmdir */
3864
3865    default:			/* Parent process */
3866      wait_for_termination (cpid);
3867    }
3868
3869  if (synch_process_death != 0 || synch_process_retcode != 0
3870      || synch_process_termsig != 0)
3871    {
3872      errno = EIO;		/* We don't know why, but */
3873      return -1;		/* /bin/rmdir failed */
3874    }
3875
3876  return 0;
3877}
3878#endif /* !HAVE_RMDIR */
3879
3880
3881
3882/* Functions for VMS */
3883#ifdef VMS
3884#include <acldef.h>
3885#include <chpdef.h>
3886#include <jpidef.h>
3887
3888/* Return as a string the VMS error string pertaining to STATUS.
3889   Reuses the same static buffer each time it is called.  */
3890
3891char *
3892vmserrstr (status)
3893     int status;		/* VMS status code */
3894{
3895  int bufadr[2];
3896  short len;
3897  static char buf[257];
3898
3899  bufadr[0] = sizeof buf - 1;
3900  bufadr[1] = (int) buf;
3901  if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
3902    return "untranslatable VMS error status";
3903  buf[len] = '\0';
3904  return buf;
3905}
3906
3907#ifdef access
3908#undef access
3909
3910/* The following is necessary because 'access' emulation by VMS C (2.0) does
3911 * not work correctly.  (It also doesn't work well in version 2.3.)
3912 */
3913
3914#ifdef VMS4_4
3915
3916#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3917	{ strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3918
3919typedef union {
3920    struct {
3921	unsigned short s_buflen;
3922	unsigned short s_code;
3923	char *s_bufadr;
3924	unsigned short *s_retlenadr;
3925    } s;
3926    int end;
3927} item;
3928#define buflen s.s_buflen
3929#define code s.s_code
3930#define bufadr s.s_bufadr
3931#define retlenadr s.s_retlenadr
3932
3933#define R_OK 4	/* test for read permission */
3934#define W_OK 2	/* test for write permission */
3935#define X_OK 1	/* test for execute (search) permission */
3936#define F_OK 0	/* test for presence of file */
3937
3938int
3939sys_access (path, mode)
3940     char *path;
3941     int mode;
3942{
3943  static char *user = NULL;
3944  char dir_fn[512];
3945
3946  /* translate possible directory spec into .DIR file name, so brain-dead
3947   * access can treat the directory like a file.  */
3948  if (directory_file_name (path, dir_fn))
3949    path = dir_fn;
3950
3951  if (mode == F_OK)
3952    return access (path, mode);
3953  if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3954    return -1;
3955  {
3956    int stat;
3957    int flags;
3958    int acces;
3959    unsigned short int dummy;
3960    item itemlst[3];
3961    static int constant = ACL$C_FILE;
3962    DESCRIPTOR (path_desc, path);
3963    DESCRIPTOR (user_desc, user);
3964
3965    flags = 0;
3966    acces = 0;
3967    if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3968      return stat;
3969    if (mode & R_OK)
3970      acces |= CHP$M_READ;
3971    if (mode & W_OK)
3972      acces |= CHP$M_WRITE;
3973    itemlst[0].buflen = sizeof (int);
3974    itemlst[0].code = CHP$_FLAGS;
3975    itemlst[0].bufadr = (char *) &flags;
3976    itemlst[0].retlenadr = &dummy;
3977    itemlst[1].buflen = sizeof (int);
3978    itemlst[1].code = CHP$_ACCESS;
3979    itemlst[1].bufadr = (char *) &acces;
3980    itemlst[1].retlenadr = &dummy;
3981    itemlst[2].end = CHP$_END;
3982    stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3983    return stat == SS$_NORMAL ? 0 : -1;
3984  }
3985}
3986
3987#else /* not VMS4_4 */
3988
3989#include <prvdef.h>
3990#define ACE$M_WRITE     2
3991#define ACE$C_KEYID     1
3992
3993static unsigned short memid, grpid;
3994static unsigned int uic;
3995
3996/* Called from init_sys_modes, so it happens not very often
3997   but at least each time Emacs is loaded.  */
3998void
3999sys_access_reinit ()
4000{
4001  uic = 0;
4002}
4003
4004int
4005sys_access (filename, type)
4006     char * filename;
4007     int type;
4008{
4009  struct FAB fab;
4010  struct XABPRO xab;
4011  int status, size, i, typecode, acl_controlled;
4012  unsigned int *aclptr, *aclend, aclbuf[60];
4013  union prvdef prvmask;
4014
4015  /* Get UIC and GRP values for protection checking.  */
4016  if (uic == 0)
4017    {
4018      status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
4019      if (! (status & 1))
4020	return -1;
4021      memid = uic & 0xFFFF;
4022      grpid = uic >> 16;
4023    }
4024
4025  if (type != 2)                /* not checking write access */
4026    return access (filename, type);
4027
4028  /* Check write protection. */
4029
4030#define CHECKPRIV(bit)    (prvmask.bit)
4031#define WRITABLE(field)  (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
4032
4033  /* Find privilege bits */
4034  status = SYS$SETPRV (0, 0, 0, prvmask);
4035  if (! (status & 1))
4036    error ("Unable to find privileges: %s", vmserrstr (status));
4037  if (CHECKPRIV (PRV$V_BYPASS))
4038    return 0;			/* BYPASS enabled */
4039  fab = cc$rms_fab;
4040  fab.fab$b_fac = FAB$M_GET;
4041  fab.fab$l_fna = filename;
4042  fab.fab$b_fns = strlen (filename);
4043  fab.fab$l_xab = &xab;
4044  xab = cc$rms_xabpro;
4045  xab.xab$l_aclbuf = aclbuf;
4046  xab.xab$w_aclsiz = sizeof (aclbuf);
4047  status = SYS$OPEN (&fab, 0, 0);
4048  if (! (status & 1))
4049    return -1;
4050  SYS$CLOSE (&fab, 0, 0);
4051  /* Check system access */
4052  if (CHECKPRIV (PRV$V_SYSPRV) && WRITABLE (XAB$V_SYS))
4053    return 0;
4054  /* Check ACL entries, if any */
4055  acl_controlled = 0;
4056  if (xab.xab$w_acllen > 0)
4057    {
4058      aclptr = aclbuf;
4059      aclend = &aclbuf[xab.xab$w_acllen / 4];
4060      while (*aclptr && aclptr < aclend)
4061	{
4062	  size = (*aclptr & 0xff) / 4;
4063	  typecode = (*aclptr >> 8) & 0xff;
4064	  if (typecode == ACE$C_KEYID)
4065	    for (i = size - 1; i > 1; i--)
4066	      if (aclptr[i] == uic)
4067		{
4068		  acl_controlled = 1;
4069		  if (aclptr[1] & ACE$M_WRITE)
4070		    return 0;	/* Write access through ACL */
4071		}
4072	  aclptr = &aclptr[size];
4073	}
4074      if (acl_controlled)	/* ACL specified, prohibits write access */
4075	return -1;
4076    }
4077  /* No ACL entries specified, check normal protection */
4078  if (WRITABLE (XAB$V_WLD))	/* World writable */
4079    return 0;
4080  if (WRITABLE (XAB$V_GRP) &&
4081      (unsigned short) (xab.xab$l_uic >> 16) == grpid)
4082    return 0;			/* Group writable */
4083  if (WRITABLE (XAB$V_OWN) &&
4084      (xab.xab$l_uic & 0xFFFF) == memid)
4085    return 0;			/* Owner writable */
4086
4087  return -1;	/* Not writable */
4088}
4089#endif /* not VMS4_4 */
4090#endif /* access */
4091
4092static char vtbuf[NAM$C_MAXRSS+1];
4093
4094/* translate a vms file spec to a unix path */
4095char *
4096sys_translate_vms (vfile)
4097     char * vfile;
4098{
4099  char * p;
4100  char * targ;
4101
4102  if (!vfile)
4103    return 0;
4104
4105  targ = vtbuf;
4106
4107  /* leading device or logical name is a root directory */
4108  if (p = strchr (vfile, ':'))
4109    {
4110      *targ++ = '/';
4111      while (vfile < p)
4112	*targ++ = *vfile++;
4113      vfile++;
4114      *targ++ = '/';
4115    }
4116  p = vfile;
4117  if (*p == '[' || *p == '<')
4118    {
4119      while (*++vfile != *p + 2)
4120	switch (*vfile)
4121	  {
4122	  case '.':
4123	    if (vfile[-1] == *p)
4124	      *targ++ = '.';
4125	    *targ++ = '/';
4126	    break;
4127
4128	  case '-':
4129	    *targ++ = '.';
4130	    *targ++ = '.';
4131	    break;
4132
4133	  default:
4134	    *targ++ = *vfile;
4135	    break;
4136	  }
4137      vfile++;
4138      *targ++ = '/';
4139    }
4140  while (*vfile)
4141    *targ++ = *vfile++;
4142
4143  return vtbuf;
4144}
4145
4146static char utbuf[NAM$C_MAXRSS+1];
4147
4148/* translate a unix path to a VMS file spec */
4149char *
4150sys_translate_unix (ufile)
4151     char * ufile;
4152{
4153  int slash_seen = 0;
4154  char *p;
4155  char * targ;
4156
4157  if (!ufile)
4158    return 0;
4159
4160  targ = utbuf;
4161
4162  if (*ufile == '/')
4163    {
4164      ufile++;
4165    }
4166
4167  while (*ufile)
4168    {
4169      switch (*ufile)
4170	{
4171	case '/':
4172	  if (slash_seen)
4173	    if (index (&ufile[1], '/'))
4174	      *targ++ = '.';
4175	    else
4176	      *targ++ = ']';
4177	  else
4178	    {
4179	      *targ++ = ':';
4180	      if (index (&ufile[1], '/'))
4181		*targ++ = '[';
4182	      slash_seen = 1;
4183	    }
4184	  break;
4185
4186	case '.':
4187	  if (strncmp (ufile, "./", 2) == 0)
4188	    {
4189	      if (!slash_seen)
4190		{
4191		  *targ++ = '[';
4192		  slash_seen = 1;
4193		}
4194	      ufile++;		/* skip the dot */
4195	      if (index (&ufile[1], '/'))
4196		*targ++ = '.';
4197	      else
4198		*targ++ = ']';
4199	    }
4200	  else if (strncmp (ufile, "../", 3) == 0)
4201	    {
4202	      if (!slash_seen)
4203		{
4204		  *targ++ = '[';
4205		  slash_seen = 1;
4206		}
4207	      *targ++ = '-';
4208	      ufile += 2;	/* skip the dots */
4209	      if (index (&ufile[1], '/'))
4210		*targ++ = '.';
4211	      else
4212		*targ++ = ']';
4213	    }
4214	  else
4215	    *targ++ = *ufile;
4216	  break;
4217
4218	default:
4219	  *targ++ = *ufile;
4220	  break;
4221	}
4222      ufile++;
4223    }
4224  *targ = '\0';
4225
4226  return utbuf;
4227}
4228
4229char *
4230getwd (pathname)
4231     char *pathname;
4232{
4233  char *ptr, *val;
4234  extern char *getcwd ();
4235
4236#define MAXPATHLEN 1024
4237
4238  ptr = xmalloc (MAXPATHLEN);
4239  val = getcwd (ptr, MAXPATHLEN);
4240  if (val == 0)
4241    {
4242      xfree (ptr);
4243      return val;
4244    }
4245  strcpy (pathname, ptr);
4246  xfree (ptr);
4247
4248 return pathname;
4249}
4250
4251int
4252getppid ()
4253{
4254  long item_code = JPI$_OWNER;
4255  unsigned long parent_id;
4256  int status;
4257
4258  if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
4259    {
4260      errno = EVMSERR;
4261      vaxc$errno = status;
4262      return -1;
4263    }
4264  return parent_id;
4265}
4266
4267#undef getuid
4268unsigned
4269sys_getuid ()
4270{
4271  return (getgid () << 16) | getuid ();
4272}
4273
4274#undef read
4275int
4276sys_read (fildes, buf, nbyte)
4277     int fildes;
4278     char *buf;
4279     unsigned int nbyte;
4280{
4281  return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
4282}
4283
4284#if 0
4285int
4286sys_write (fildes, buf, nbyte)
4287     int fildes;
4288     char *buf;
4289     unsigned int nbyte;
4290{
4291  register int nwrote, rtnval = 0;
4292
4293  while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
4294    nbyte -= nwrote;
4295    buf += nwrote;
4296    rtnval += nwrote;
4297  }
4298  if (nwrote < 0)
4299    return rtnval ? rtnval : -1;
4300  if ((nwrote = write (fildes, buf, nbyte)) < 0)
4301    return rtnval ? rtnval : -1;
4302  return (rtnval + nwrote);
4303}
4304#endif /* 0 */
4305
4306/*
4307 *	VAX/VMS VAX C RTL really loses. It insists that records
4308 *      end with a newline (carriage return) character, and if they
4309 *	don't it adds one (nice of it isn't it!)
4310 *
4311 *	Thus we do this stupidity below.
4312 */
4313
4314#undef write
4315int
4316sys_write (fildes, buf, nbytes)
4317     int fildes;
4318     char *buf;
4319     unsigned int nbytes;
4320{
4321  register char *p;
4322  register char *e;
4323  int sum = 0;
4324  struct stat st;
4325
4326  fstat (fildes, &st);
4327  p = buf;
4328  while (nbytes > 0)
4329    {
4330      int len, retval;
4331
4332      /* Handle fixed-length files with carriage control.  */
4333      if (st.st_fab_rfm == FAB$C_FIX
4334	  && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
4335	{
4336	  len = st.st_fab_mrs;
4337	  retval = write (fildes, p, min (len, nbytes));
4338	  if (retval != len)
4339	    return -1;
4340	  retval++;	/* This skips the implied carriage control */
4341	}
4342      else
4343	{
4344	  e =  p + min (MAXIOSIZE, nbytes) - 1;
4345	  while (*e != '\n' && e > p) e--;
4346	  if (p == e)		/* Ok.. so here we add a newline... sigh. */
4347	    e = p + min (MAXIOSIZE, nbytes) - 1;
4348	  len = e + 1 - p;
4349	  retval = write (fildes, p, len);
4350	  if (retval != len)
4351	    return -1;
4352	}
4353      p += retval;
4354      sum += retval;
4355      nbytes -= retval;
4356    }
4357  return sum;
4358}
4359
4360/* Create file NEW copying its attributes from file OLD.  If
4361   OLD is 0 or does not exist, create based on the value of
4362   vms_stmlf_recfm. */
4363
4364/* Protection value the file should ultimately have.
4365   Set by create_copy_attrs, and use by rename_sansversions.  */
4366static unsigned short int fab_final_pro;
4367
4368int
4369creat_copy_attrs (old, new)
4370     char *old, *new;
4371{
4372  struct FAB fab = cc$rms_fab;
4373  struct XABPRO xabpro;
4374  char aclbuf[256];	/* Choice of size is arbitrary.  See below. */
4375  extern int vms_stmlf_recfm;
4376
4377  if (old)
4378    {
4379      fab.fab$b_fac = FAB$M_GET;
4380      fab.fab$l_fna = old;
4381      fab.fab$b_fns = strlen (old);
4382      fab.fab$l_xab = (char *) &xabpro;
4383      xabpro = cc$rms_xabpro;
4384      xabpro.xab$l_aclbuf = aclbuf;
4385      xabpro.xab$w_aclsiz = sizeof aclbuf;
4386      /* Call $OPEN to fill in the fab & xabpro fields. */
4387      if (SYS$OPEN (&fab, 0, 0) & 1)
4388	{
4389	  SYS$CLOSE (&fab, 0, 0);
4390	  fab.fab$l_alq = 0;	/* zero the allocation quantity */
4391	  if (xabpro.xab$w_acllen > 0)
4392	    {
4393	      if (xabpro.xab$w_acllen > sizeof aclbuf)
4394		/* If the acl buffer was too short, redo open with longer one.
4395		   Wouldn't need to do this if there were some system imposed
4396		   limit on the size of an ACL, but I can't find any such. */
4397		{
4398		  xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
4399		  xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
4400		  if (SYS$OPEN (&fab, 0, 0) & 1)
4401		    SYS$CLOSE (&fab, 0, 0);
4402		  else
4403		    old = 0;
4404		}
4405	    }
4406	  else
4407	    xabpro.xab$l_aclbuf = 0;
4408	}
4409      else
4410	old = 0;
4411    }
4412  fab.fab$l_fna = new;
4413  fab.fab$b_fns = strlen (new);
4414  if (!old)
4415    {
4416      fab.fab$l_xab = 0;
4417      fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
4418      fab.fab$b_rat = FAB$M_CR;
4419    }
4420
4421  /* Set the file protections such that we will be able to manipulate
4422     this file.  Once we are done writing and renaming it, we will set
4423     the protections back.  */
4424  if (old)
4425    fab_final_pro = xabpro.xab$w_pro;
4426  else
4427    SYS$SETDFPROT (0, &fab_final_pro);
4428  xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
4429
4430  /* Create the new file with either default attrs or attrs copied
4431     from old file. */
4432  if (!(SYS$CREATE (&fab, 0, 0) & 1))
4433    return -1;
4434  SYS$CLOSE (&fab, 0, 0);
4435  /* As this is a "replacement" for creat, return a file descriptor
4436     opened for writing. */
4437  return open (new, O_WRONLY);
4438}
4439
4440#ifdef creat
4441#undef creat
4442#include <varargs.h>
4443#ifdef __GNUC__
4444#ifndef va_count
4445#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4446#endif
4447#endif
4448
4449int
4450sys_creat (va_alist)
4451     va_dcl
4452{
4453  va_list list_incrementer;
4454  char *name;
4455  int mode;
4456  int rfd;			/* related file descriptor */
4457  int fd;			/* Our new file descriptor */
4458  int count;
4459  struct stat st_buf;
4460  char rfm[12];
4461  char rat[15];
4462  char mrs[13];
4463  char fsz[13];
4464  extern int vms_stmlf_recfm;
4465
4466  va_count (count);
4467  va_start (list_incrementer);
4468  name = va_arg (list_incrementer, char *);
4469  mode = va_arg (list_incrementer, int);
4470  if (count > 2)
4471    rfd = va_arg (list_incrementer, int);
4472  va_end (list_incrementer);
4473  if (count > 2)
4474    {
4475      /* Use information from the related file descriptor to set record
4476	 format of the newly created file. */
4477      fstat (rfd, &st_buf);
4478      switch (st_buf.st_fab_rfm)
4479	{
4480	case FAB$C_FIX:
4481	  strcpy (rfm, "rfm = fix");
4482	  sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
4483	  strcpy (rat, "rat = ");
4484	  if (st_buf.st_fab_rat & FAB$M_CR)
4485	    strcat (rat, "cr");
4486	  else if (st_buf.st_fab_rat & FAB$M_FTN)
4487	    strcat (rat, "ftn");
4488	  else if (st_buf.st_fab_rat & FAB$M_PRN)
4489	    strcat (rat, "prn");
4490	  if (st_buf.st_fab_rat & FAB$M_BLK)
4491	    if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4492	      strcat (rat, ", blk");
4493	    else
4494	      strcat (rat, "blk");
4495	  return creat (name, 0, rfm, rat, mrs);
4496
4497	case FAB$C_VFC:
4498	  strcpy (rfm, "rfm = vfc");
4499	  sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
4500	  strcpy (rat, "rat = ");
4501	  if (st_buf.st_fab_rat & FAB$M_CR)
4502	    strcat (rat, "cr");
4503	  else if (st_buf.st_fab_rat & FAB$M_FTN)
4504	    strcat (rat, "ftn");
4505	  else if (st_buf.st_fab_rat & FAB$M_PRN)
4506	    strcat (rat, "prn");
4507	  if (st_buf.st_fab_rat & FAB$M_BLK)
4508	    if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4509	      strcat (rat, ", blk");
4510	    else
4511	      strcat (rat, "blk");
4512	  return creat (name, 0, rfm, rat, fsz);
4513
4514	case FAB$C_STM:
4515	  strcpy (rfm, "rfm = stm");
4516	  break;
4517
4518	case FAB$C_STMCR:
4519	  strcpy (rfm, "rfm = stmcr");
4520	  break;
4521
4522	case FAB$C_STMLF:
4523	  strcpy (rfm, "rfm = stmlf");
4524	  break;
4525
4526	case FAB$C_UDF:
4527	  strcpy (rfm, "rfm = udf");
4528	  break;
4529
4530	case FAB$C_VAR:
4531	  strcpy (rfm, "rfm = var");
4532	  break;
4533	}
4534      strcpy (rat, "rat = ");
4535      if (st_buf.st_fab_rat & FAB$M_CR)
4536	strcat (rat, "cr");
4537      else if (st_buf.st_fab_rat & FAB$M_FTN)
4538	strcat (rat, "ftn");
4539      else if (st_buf.st_fab_rat & FAB$M_PRN)
4540	strcat (rat, "prn");
4541      if (st_buf.st_fab_rat & FAB$M_BLK)
4542	if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4543	  strcat (rat, ", blk");
4544	else
4545	  strcat (rat, "blk");
4546    }
4547  else
4548    {
4549      strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
4550      strcpy (rat, "rat=cr");
4551    }
4552  /* Until the VAX C RTL fixes the many bugs with modes, always use
4553     mode 0 to get the user's default protection. */
4554  fd = creat (name, 0, rfm, rat);
4555  if (fd < 0 && errno == EEXIST)
4556    {
4557      if (unlink (name) < 0)
4558	report_file_error ("delete", build_string (name));
4559      fd = creat (name, 0, rfm, rat);
4560    }
4561  return fd;
4562}
4563#endif /* creat */
4564
4565/* fwrite to stdout is S L O W.  Speed it up by using fputc...*/
4566int
4567sys_fwrite (ptr, size, num, fp)
4568     register char * ptr;
4569     FILE * fp;
4570{
4571  register int tot = num * size;
4572
4573  while (tot--)
4574    fputc (*ptr++, fp);
4575  return num;
4576}
4577
4578/*
4579 * The VMS C library routine creat actually creates a new version of an
4580 * existing file rather than truncating the old version.  There are times
4581 * when this is not the desired behavior, for instance, when writing an
4582 * auto save file (you only want one version), or when you don't have
4583 * write permission in the directory containing the file (but the file
4584 * itself is writable).  Hence this routine, which is equivalent to
4585 * "close (creat (fn, 0));" on Unix if fn already exists.
4586 */
4587int
4588vms_truncate (fn)
4589     char *fn;
4590{
4591  struct FAB xfab = cc$rms_fab;
4592  struct RAB xrab = cc$rms_rab;
4593  int status;
4594
4595  xfab.fab$l_fop = FAB$M_TEF;	/* free allocated but unused blocks on close */
4596  xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
4597  xfab.fab$b_shr = FAB$M_NIL;	/* allow no sharing - file must be locked */
4598  xfab.fab$l_fna = fn;
4599  xfab.fab$b_fns = strlen (fn);
4600  xfab.fab$l_dna = ";0";	/* default to latest version of the file */
4601  xfab.fab$b_dns = 2;
4602  xrab.rab$l_fab = &xfab;
4603
4604  /* This gibberish opens the file, positions to the first record, and
4605     deletes all records from there until the end of file. */
4606  if ((SYS$OPEN (&xfab) & 01) == 01)
4607    {
4608      if ((SYS$CONNECT (&xrab) & 01) == 01 &&
4609	  (SYS$FIND (&xrab) & 01) == 01 &&
4610	  (SYS$TRUNCATE (&xrab) & 01) == 01)
4611	status = 0;
4612      else
4613	status = -1;
4614    }
4615  else
4616    status = -1;
4617  SYS$CLOSE (&xfab);
4618  return status;
4619}
4620
4621/* Define this symbol to actually read SYSUAF.DAT.  This requires either
4622   SYSPRV or a readable SYSUAF.DAT. */
4623
4624#ifdef READ_SYSUAF
4625/*
4626 * getuaf.c
4627 *
4628 * Routine to read the VMS User Authorization File and return
4629 * a specific user's record.
4630 */
4631
4632static struct UAF retuaf;
4633
4634struct UAF *
4635get_uaf_name (uname)
4636     char * uname;
4637{
4638  register status;
4639  struct FAB uaf_fab;
4640  struct RAB uaf_rab;
4641
4642  uaf_fab = cc$rms_fab;
4643  uaf_rab = cc$rms_rab;
4644  /* initialize fab fields */
4645  uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4646  uaf_fab.fab$b_fns = 21;
4647  uaf_fab.fab$b_fac = FAB$M_GET;
4648  uaf_fab.fab$b_org = FAB$C_IDX;
4649  uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4650  /* initialize rab fields */
4651  uaf_rab.rab$l_fab = &uaf_fab;
4652  /* open the User Authorization File */
4653  status = SYS$OPEN (&uaf_fab);
4654  if (!(status&1))
4655    {
4656      errno = EVMSERR;
4657      vaxc$errno = status;
4658      return 0;
4659    }
4660  status = SYS$CONNECT (&uaf_rab);
4661  if (!(status&1))
4662    {
4663      errno = EVMSERR;
4664      vaxc$errno = status;
4665      return 0;
4666    }
4667  /* read the requested record - index is in uname */
4668  uaf_rab.rab$l_kbf = uname;
4669  uaf_rab.rab$b_ksz = strlen (uname);
4670  uaf_rab.rab$b_rac = RAB$C_KEY;
4671  uaf_rab.rab$l_ubf = (char *)&retuaf;
4672  uaf_rab.rab$w_usz = sizeof retuaf;
4673  status = SYS$GET (&uaf_rab);
4674  if (!(status&1))
4675    {
4676      errno = EVMSERR;
4677      vaxc$errno = status;
4678      return 0;
4679    }
4680  /* close the User Authorization File */
4681  status = SYS$DISCONNECT (&uaf_rab);
4682  if (!(status&1))
4683    {
4684      errno = EVMSERR;
4685      vaxc$errno = status;
4686      return 0;
4687    }
4688  status = SYS$CLOSE (&uaf_fab);
4689  if (!(status&1))
4690    {
4691      errno = EVMSERR;
4692      vaxc$errno = status;
4693      return 0;
4694    }
4695  return &retuaf;
4696}
4697
4698struct UAF *
4699get_uaf_uic (uic)
4700     unsigned long uic;
4701{
4702  register status;
4703  struct FAB uaf_fab;
4704  struct RAB uaf_rab;
4705
4706  uaf_fab = cc$rms_fab;
4707  uaf_rab = cc$rms_rab;
4708  /* initialize fab fields */
4709  uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4710  uaf_fab.fab$b_fns = 21;
4711  uaf_fab.fab$b_fac = FAB$M_GET;
4712  uaf_fab.fab$b_org = FAB$C_IDX;
4713  uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4714  /* initialize rab fields */
4715  uaf_rab.rab$l_fab = &uaf_fab;
4716  /* open the User Authorization File */
4717  status = SYS$OPEN (&uaf_fab);
4718  if (!(status&1))
4719    {
4720      errno = EVMSERR;
4721      vaxc$errno = status;
4722      return 0;
4723    }
4724  status = SYS$CONNECT (&uaf_rab);
4725  if (!(status&1))
4726    {
4727      errno = EVMSERR;
4728      vaxc$errno = status;
4729      return 0;
4730    }
4731  /* read the requested record - index is in uic */
4732  uaf_rab.rab$b_krf = 1;	/* 1st alternate key */
4733  uaf_rab.rab$l_kbf = (char *) &uic;
4734  uaf_rab.rab$b_ksz = sizeof uic;
4735  uaf_rab.rab$b_rac = RAB$C_KEY;
4736  uaf_rab.rab$l_ubf = (char *)&retuaf;
4737  uaf_rab.rab$w_usz = sizeof retuaf;
4738  status = SYS$GET (&uaf_rab);
4739  if (!(status&1))
4740    {
4741      errno = EVMSERR;
4742      vaxc$errno = status;
4743      return 0;
4744    }
4745  /* close the User Authorization File */
4746  status = SYS$DISCONNECT (&uaf_rab);
4747  if (!(status&1))
4748    {
4749      errno = EVMSERR;
4750      vaxc$errno = status;
4751      return 0;
4752    }
4753  status = SYS$CLOSE (&uaf_fab);
4754  if (!(status&1))
4755    {
4756      errno = EVMSERR;
4757      vaxc$errno = status;
4758      return 0;
4759    }
4760  return &retuaf;
4761}
4762
4763static struct passwd retpw;
4764
4765struct passwd *
4766cnv_uaf_pw (up)
4767     struct UAF * up;
4768{
4769  char * ptr;
4770
4771  /* copy these out first because if the username is 32 chars, the next
4772     section will overwrite the first byte of the UIC */
4773  retpw.pw_uid = up->uaf$w_mem;
4774  retpw.pw_gid = up->uaf$w_grp;
4775
4776  /* I suppose this is not the best style, to possibly overwrite one
4777     byte beyond the end of the field, but what the heck... */
4778  ptr = &up->uaf$t_username[UAF$S_USERNAME];
4779  while (ptr[-1] == ' ')
4780    ptr--;
4781  *ptr = '\0';
4782  strcpy (retpw.pw_name, up->uaf$t_username);
4783
4784  /* the rest of these are counted ascii strings */
4785  strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
4786  retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
4787  strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
4788  retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
4789  strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
4790  retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
4791  strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
4792  retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
4793
4794  return &retpw;
4795}
4796#else /* not READ_SYSUAF */
4797static struct passwd retpw;
4798#endif /* not READ_SYSUAF */
4799
4800struct passwd *
4801getpwnam (name)
4802     char * name;
4803{
4804#ifdef READ_SYSUAF
4805  struct UAF *up;
4806#else
4807  char * user;
4808  char * dir;
4809  unsigned char * full;
4810#endif /* READ_SYSUAF */
4811  char *ptr = name;
4812
4813  while (*ptr)
4814    {
4815      if ('a' <= *ptr && *ptr <= 'z')
4816	*ptr -= 040;
4817      ptr++;
4818    }
4819#ifdef READ_SYSUAF
4820  if (!(up = get_uaf_name (name)))
4821    return 0;
4822  return cnv_uaf_pw (up);
4823#else
4824  if (strcmp (name, getenv ("USER")) == 0)
4825    {
4826      retpw.pw_uid = getuid ();
4827      retpw.pw_gid = getgid ();
4828      strcpy (retpw.pw_name, name);
4829      if (full = egetenv ("FULLNAME"))
4830	strcpy (retpw.pw_gecos, full);
4831      else
4832	*retpw.pw_gecos = '\0';
4833      strcpy (retpw.pw_dir, egetenv ("HOME"));
4834      *retpw.pw_shell = '\0';
4835      return &retpw;
4836    }
4837  else
4838    return 0;
4839#endif /* not READ_SYSUAF */
4840}
4841
4842struct passwd *
4843getpwuid (uid)
4844     unsigned long uid;
4845{
4846#ifdef READ_SYSUAF
4847  struct UAF * up;
4848
4849  if (!(up = get_uaf_uic (uid)))
4850    return 0;
4851  return cnv_uaf_pw (up);
4852#else
4853  if (uid == sys_getuid ())
4854    return getpwnam (egetenv ("USER"));
4855  else
4856    return 0;
4857#endif /* not READ_SYSUAF */
4858}
4859
4860/* return total address space available to the current process.  This is
4861   the sum of the current p0 size, p1 size and free page table entries
4862   available. */
4863int
4864vlimit ()
4865{
4866  int item_code;
4867  unsigned long free_pages;
4868  unsigned long frep0va;
4869  unsigned long frep1va;
4870  register status;
4871
4872  item_code = JPI$_FREPTECNT;
4873  if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
4874    {
4875      errno = EVMSERR;
4876      vaxc$errno = status;
4877      return -1;
4878    }
4879  free_pages *= 512;
4880
4881  item_code = JPI$_FREP0VA;
4882  if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
4883    {
4884      errno = EVMSERR;
4885      vaxc$errno = status;
4886      return -1;
4887    }
4888  item_code = JPI$_FREP1VA;
4889  if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
4890    {
4891      errno = EVMSERR;
4892      vaxc$errno = status;
4893      return -1;
4894    }
4895
4896  return free_pages + frep0va + (0x7fffffff - frep1va);
4897}
4898
4899int
4900define_logical_name (varname, string)
4901     char *varname;
4902     char *string;
4903{
4904  struct dsc$descriptor_s strdsc =
4905    {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
4906  struct dsc$descriptor_s envdsc =
4907    {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4908  struct dsc$descriptor_s lnmdsc =
4909    {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4910
4911  return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
4912}
4913
4914int
4915delete_logical_name (varname)
4916     char *varname;
4917{
4918  struct dsc$descriptor_s envdsc =
4919    {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4920  struct dsc$descriptor_s lnmdsc =
4921    {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4922
4923  return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
4924}
4925
4926int
4927ulimit ()
4928{
4929  return 0;
4930}
4931
4932int
4933setpgrp ()
4934{
4935  return 0;
4936}
4937
4938int
4939execvp ()
4940{
4941  error ("execvp system call not implemented");
4942  return -1;
4943}
4944
4945int
4946rename (from, to)
4947     char *from, *to;
4948{
4949  int status;
4950  struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4951  struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4952  char from_esn[NAM$C_MAXRSS];
4953  char to_esn[NAM$C_MAXRSS];
4954
4955  from_fab.fab$l_fna = from;
4956  from_fab.fab$b_fns = strlen (from);
4957  from_fab.fab$l_nam = &from_nam;
4958  from_fab.fab$l_fop = FAB$M_NAM;
4959
4960  from_nam.nam$l_esa = from_esn;
4961  from_nam.nam$b_ess = sizeof from_esn;
4962
4963  to_fab.fab$l_fna = to;
4964  to_fab.fab$b_fns = strlen (to);
4965  to_fab.fab$l_nam = &to_nam;
4966  to_fab.fab$l_fop = FAB$M_NAM;
4967
4968  to_nam.nam$l_esa = to_esn;
4969  to_nam.nam$b_ess = sizeof to_esn;
4970
4971  status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4972
4973  if (status & 1)
4974    return 0;
4975  else
4976    {
4977      if (status == RMS$_DEV)
4978	errno = EXDEV;
4979      else
4980	errno = EVMSERR;
4981      vaxc$errno = status;
4982      return -1;
4983    }
4984}
4985
4986/* This function renames a file like `rename', but it strips
4987   the version number from the "to" filename, such that the "to" file is
4988   will always be a new version.  It also sets the file protection once it is
4989   finished.  The protection that we will use is stored in fab_final_pro,
4990   and was set when we did a creat_copy_attrs to create the file that we
4991   are renaming.
4992
4993   We could use the chmod function, but Eunichs uses 3 bits per user category
4994   to describe the protection, and VMS uses 4 (write and delete are separate
4995   bits).  To maintain portability, the VMS implementation of `chmod' wires
4996   the W and D bits together.  */
4997
4998
4999static struct fibdef fib;	/* We need this initialized to zero */
5000char vms_file_written[NAM$C_MAXRSS];
5001
5002int
5003rename_sans_version (from,to)
5004     char *from, *to;
5005{
5006  short int chan;
5007  int stat;
5008  short int iosb[4];
5009  int status;
5010  struct FAB to_fab = cc$rms_fab;
5011  struct NAM to_nam = cc$rms_nam;
5012  struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
5013  struct dsc$descriptor fib_attr[2]
5014    = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
5015  char to_esn[NAM$C_MAXRSS];
5016
5017  $DESCRIPTOR (disk,to_esn);
5018
5019  to_fab.fab$l_fna = to;
5020  to_fab.fab$b_fns = strlen (to);
5021  to_fab.fab$l_nam = &to_nam;
5022  to_fab.fab$l_fop = FAB$M_NAM;
5023
5024  to_nam.nam$l_esa = to_esn;
5025  to_nam.nam$b_ess = sizeof to_esn;
5026
5027  status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
5028
5029  if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
5030    *(to_nam.nam$l_ver) = '\0';
5031
5032  stat = rename (from, to_esn);
5033  if (stat < 0)
5034    return stat;
5035
5036  strcpy (vms_file_written, to_esn);
5037
5038  to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
5039  to_fab.fab$b_fns = strlen (vms_file_written);
5040
5041  /* Now set the file protection to the correct value */
5042  SYS$OPEN (&to_fab, 0, 0);	/* This fills in the nam$w_fid fields */
5043
5044  /* Copy these fields into the fib */
5045  fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
5046  fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
5047  fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
5048
5049  SYS$CLOSE (&to_fab, 0, 0);
5050
5051  stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
5052  if (!stat)
5053    LIB$SIGNAL (stat);
5054  stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
5055		   0, 0, 0, &fib_attr, 0);
5056  if (!stat)
5057    LIB$SIGNAL (stat);
5058  stat = SYS$DASSGN (chan);
5059  if (!stat)
5060    LIB$SIGNAL (stat);
5061  strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
5062  return 0;
5063}
5064
5065int
5066link (file, new)
5067     char * file, * new;
5068{
5069  register status;
5070  struct FAB fab;
5071  struct NAM nam;
5072  unsigned short fid[3];
5073  char esa[NAM$C_MAXRSS];
5074
5075  fab = cc$rms_fab;
5076  fab.fab$l_fop = FAB$M_OFP;
5077  fab.fab$l_fna = file;
5078  fab.fab$b_fns = strlen (file);
5079  fab.fab$l_nam = &nam;
5080
5081  nam = cc$rms_nam;
5082  nam.nam$l_esa = esa;
5083  nam.nam$b_ess = NAM$C_MAXRSS;
5084
5085  status = SYS$PARSE (&fab);
5086  if ((status & 1) == 0)
5087    {
5088      errno = EVMSERR;
5089      vaxc$errno = status;
5090      return -1;
5091    }
5092  status = SYS$SEARCH (&fab);
5093  if ((status & 1) == 0)
5094    {
5095      errno = EVMSERR;
5096      vaxc$errno = status;
5097      return -1;
5098    }
5099
5100  fid[0] = nam.nam$w_fid[0];
5101  fid[1] = nam.nam$w_fid[1];
5102  fid[2] = nam.nam$w_fid[2];
5103
5104  fab.fab$l_fna = new;
5105  fab.fab$b_fns = strlen (new);
5106
5107  status = SYS$PARSE (&fab);
5108  if ((status & 1) == 0)
5109    {
5110      errno = EVMSERR;
5111      vaxc$errno = status;
5112      return -1;
5113    }
5114
5115  nam.nam$w_fid[0] = fid[0];
5116  nam.nam$w_fid[1] = fid[1];
5117  nam.nam$w_fid[2] = fid[2];
5118
5119  nam.nam$l_esa = nam.nam$l_name;
5120  nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
5121
5122  status = SYS$ENTER (&fab);
5123  if ((status & 1) == 0)
5124    {
5125      errno = EVMSERR;
5126      vaxc$errno = status;
5127      return -1;
5128    }
5129
5130  return 0;
5131}
5132
5133void
5134croak (badfunc)
5135     char *badfunc;
5136{
5137  printf ("%s not yet implemented\r\n", badfunc);
5138  reset_sys_modes ();
5139  exit (1);
5140}
5141
5142long
5143random ()
5144{
5145  /* Arrange to return a range centered on zero.  */
5146  return rand () - (1 << 30);
5147}
5148
5149void
5150srandom (seed)
5151{
5152  srand (seed);
5153}
5154#endif /* VMS */
5155
5156#ifdef AIXHFT
5157
5158/* Called from init_sys_modes.  */
5159void
5160hft_init ()
5161{
5162  int junk;
5163
5164  /* If we're not on an HFT we shouldn't do any of this.  We determine
5165     if we are on an HFT by trying to get an HFT error code.  If this
5166     call fails, we're not on an HFT. */
5167#ifdef IBMR2AIX
5168  if (ioctl (0, HFQERROR, &junk) < 0)
5169    return;
5170#else /* not IBMR2AIX */
5171  if (ioctl (0, HFQEIO, 0) < 0)
5172    return;
5173#endif /* not IBMR2AIX */
5174
5175  /* On AIX the default hft keyboard mapping uses backspace rather than delete
5176     as the rubout key's ASCII code.  Here this is changed.  The bug is that
5177     there's no way to determine the old mapping, so in reset_sys_modes
5178     we need to assume that the normal map had been present.  Of course, this
5179     code also doesn't help if on a terminal emulator which doesn't understand
5180     HFT VTD's.  */
5181  {
5182    struct hfbuf buf;
5183    struct hfkeymap keymap;
5184
5185    buf.hf_bufp = (char *)&keymap;
5186    buf.hf_buflen = sizeof (keymap);
5187    keymap.hf_nkeys = 2;
5188    keymap.hfkey[0].hf_kpos = 15;
5189    keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
5190#ifdef IBMR2AIX
5191    keymap.hfkey[0].hf_keyidh = '<';
5192#else /* not IBMR2AIX */
5193    keymap.hfkey[0].hf_page = '<';
5194#endif /* not IBMR2AIX */
5195    keymap.hfkey[0].hf_char = 127;
5196    keymap.hfkey[1].hf_kpos = 15;
5197    keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
5198#ifdef IBMR2AIX
5199    keymap.hfkey[1].hf_keyidh = '<';
5200#else /* not IBMR2AIX */
5201    keymap.hfkey[1].hf_page = '<';
5202#endif /* not IBMR2AIX */
5203    keymap.hfkey[1].hf_char = 127;
5204    hftctl (0, HFSKBD, &buf);
5205  }
5206  /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5207     at times.  */
5208  line_ins_del_ok = char_ins_del_ok = 0;
5209}
5210
5211/* Reset the rubout key to backspace.  */
5212
5213void
5214hft_reset ()
5215{
5216  struct hfbuf buf;
5217  struct hfkeymap keymap;
5218  int junk;
5219
5220#ifdef IBMR2AIX
5221  if (ioctl (0, HFQERROR, &junk) < 0)
5222    return;
5223#else /* not IBMR2AIX */
5224  if (ioctl (0, HFQEIO, 0) < 0)
5225    return;
5226#endif /* not IBMR2AIX */
5227
5228  buf.hf_bufp = (char *)&keymap;
5229  buf.hf_buflen = sizeof (keymap);
5230  keymap.hf_nkeys = 2;
5231  keymap.hfkey[0].hf_kpos = 15;
5232  keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
5233#ifdef IBMR2AIX
5234  keymap.hfkey[0].hf_keyidh = '<';
5235#else /* not IBMR2AIX */
5236  keymap.hfkey[0].hf_page = '<';
5237#endif /* not IBMR2AIX */
5238  keymap.hfkey[0].hf_char = 8;
5239  keymap.hfkey[1].hf_kpos = 15;
5240  keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
5241#ifdef IBMR2AIX
5242  keymap.hfkey[1].hf_keyidh = '<';
5243#else /* not IBMR2AIX */
5244  keymap.hfkey[1].hf_page = '<';
5245#endif /* not IBMR2AIX */
5246  keymap.hfkey[1].hf_char = 8;
5247  hftctl (0, HFSKBD, &buf);
5248}
5249
5250#endif /* AIXHFT */
5251
5252#ifdef USE_DL_STUBS
5253
5254/* These are included on Sunos 4.1 when we do not use shared libraries.
5255   X11 libraries may refer to these functions but (we hope) do not
5256   actually call them.  */
5257
5258void *
5259dlopen ()
5260{
5261  return 0;
5262}
5263
5264void *
5265dlsym ()
5266{
5267  return 0;
5268}
5269
5270int
5271dlclose ()
5272{
5273  return -1;
5274}
5275
5276#endif /* USE_DL_STUBS */
5277
5278#ifndef BSTRING
5279
5280#ifndef bzero
5281
5282void
5283bzero (b, length)
5284     register char *b;
5285     register int length;
5286{
5287#ifdef VMS
5288  short zero = 0;
5289  long max_str = 65535;
5290
5291  while (length > max_str) {
5292    (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5293    length -= max_str;
5294    b += max_str;
5295  }
5296  max_str = length;
5297  (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5298#else
5299  while (length-- > 0)
5300    *b++ = 0;
5301#endif /* not VMS */
5302}
5303
5304#endif /* no bzero */
5305#endif /* BSTRING */
5306
5307#if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
5308#undef bcopy
5309
5310/* Saying `void' requires a declaration, above, where bcopy is used
5311   and that declaration causes pain for systems where bcopy is a macro.  */
5312bcopy (b1, b2, length)
5313     register char *b1;
5314     register char *b2;
5315     register int length;
5316{
5317#ifdef VMS
5318  long max_str = 65535;
5319
5320  while (length > max_str) {
5321    (void) LIB$MOVC3 (&max_str, b1, b2);
5322    length -= max_str;
5323    b1 += max_str;
5324    b2 += max_str;
5325  }
5326  max_str = length;
5327  (void) LIB$MOVC3 (&length, b1, b2);
5328#else
5329  while (length-- > 0)
5330    *b2++ = *b1++;
5331#endif /* not VMS */
5332}
5333#endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
5334
5335#ifndef BSTRING
5336#ifndef bcmp
5337int
5338bcmp (b1, b2, length)	/* This could be a macro! */
5339     register char *b1;
5340     register char *b2;
5341     register int length;
5342{
5343#ifdef VMS
5344  struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
5345  struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
5346
5347  return STR$COMPARE (&src1, &src2);
5348#else
5349  while (length-- > 0)
5350    if (*b1++ != *b2++)
5351      return 1;
5352
5353  return 0;
5354#endif /* not VMS */
5355}
5356#endif /* no bcmp */
5357#endif /* not BSTRING */
5358
5359#ifndef HAVE_STRSIGNAL
5360char *
5361strsignal (code)
5362     int code;
5363{
5364  char *signame = 0;
5365
5366  if (0 <= code && code < NSIG)
5367    {
5368#ifdef VMS
5369      signame = sys_errlist[code];
5370#else
5371      /* Cast to suppress warning if the table has const char *.  */
5372      signame = (char *) sys_siglist[code];
5373#endif
5374    }
5375
5376  return signame;
5377}
5378#endif /* HAVE_STRSIGNAL */
5379
5380/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
5381   (do not change this comment) */
5382