XEmacs 21.2.32 "Kastor & Polydeukes".
[chise/xemacs-chise.git.1] / src / sysdep.c
1 /* Interfaces to system-dependent kernel and library entries.
2    Copyright (C) 1985-1988, 1992-1995 Free Software Foundation, Inc.
3    Copyright (C) 1995 Tinker Systems.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: FSF 19.30 except for some Windows-NT crap. */
23
24 /* Substantially cleaned up by Ben Wing, Dec. 1994 / Jan. 1995. */
25
26 /* In this file, open, read and write refer to the system calls,
27    not our sugared interfaces sys_open, sys_read and sys_write.
28  */
29
30 #define DONT_ENCAPSULATE
31
32 #include <config.h>
33
34 #ifdef WINDOWSNT
35 #include <direct.h>
36 #ifdef __MINGW32__
37 #include <mingw32/process.h>
38 #else
39 /* <process.h> should not conflict with "process.h", as per ANSI definition.
40    This is not true with visual c though. The trick below works with
41    VC4.2b, 5.0 and 6.0. It assumes that VC is installed in a kind of
42    standard way, so include path ends with /include.
43
44    Unfortunately, this must go before lisp.h, since process.h defines abort()
45    which will conflict with the macro defined in lisp.h
46 */
47 #include <../include/process.h>
48 #endif /* __MINGW32__ */
49 #endif /* WINDOWSNT */
50
51 #include "lisp.h"
52
53 #include <stdlib.h>
54
55 /* ------------------------------- */
56 /*          basic includes         */
57 /* ------------------------------- */
58
59 #ifdef HAVE_TTY
60 #include "console-tty.h"
61 #else
62 #include "syssignal.h"
63 #include "systty.h"
64 #endif /* HAVE_TTY */
65
66 #include "console-stream.h"
67
68 #include "buffer.h"
69 #include "events.h"
70 #include "frame.h"
71 #include "redisplay.h"
72 #include "process.h"
73 #include "sysdep.h"
74 #include "window.h"
75
76 #include <setjmp.h>
77 #ifdef HAVE_LIBGEN_H            /* Must come before sysfile.h */
78 #include <libgen.h>
79 #endif
80 #include "sysfile.h"
81 #include "syswait.h"
82 #include "sysdir.h"
83 #include "systime.h"
84 #if defined(WINDOWSNT) || defined(__CYGWIN32__)
85 #include "syssignal.h"
86 #endif
87 #ifndef WINDOWSNT
88 #include <sys/times.h>
89 #endif
90
91 #ifdef WINDOWSNT
92 #include <sys/utime.h>
93 #include "ntheap.h"
94 #endif
95
96 #ifdef HAVE_MMAP
97 #include <unistd.h>
98 #include <sys/mman.h>
99 #endif
100
101 /* ------------------------------- */
102 /*         TTY definitions         */
103 /* ------------------------------- */
104
105 #ifdef USG
106 #include <sys/utsname.h>
107 #if defined (TIOCGWINSZ) || defined (ISC4_0)
108 #ifdef NEED_SIOCTL
109 #include <sys/sioctl.h>
110 #endif
111 #ifdef NEED_PTEM_H
112 #include <sys/stream.h>
113 #include <sys/ptem.h>
114 #endif
115 #endif /* TIOCGWINSZ or ISC4_0 */
116 #endif /* USG */
117
118 #ifdef HAVE_SYS_STROPTS_H
119 #include <sys/stropts.h>
120 #endif /* HAVE_SYS_STROPTS_H */
121
122 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
123 #ifndef LPASS8
124 #define LPASS8 0
125 #endif
126
127 #ifndef HAVE_H_ERRNO
128 int h_errno;
129 #endif
130
131 #ifdef HAVE_TTY
132
133 static int baud_convert[] =
134 #ifdef BAUD_CONVERT
135   BAUD_CONVERT;
136 #else
137   {
138     0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
139     1800, 2400, 4800, 9600, 19200, 38400
140   };
141 #endif
142
143 #endif
144
145 #ifdef AIXHFT
146 static void hft_init (struct console *c);
147 static void hft_reset (struct console *c);
148 #include <sys/termio.h>
149 #endif
150
151 /* ------------------------------- */
152 /*          miscellaneous          */
153 /* ------------------------------- */
154
155 #ifndef HAVE_UTIMES
156 #ifndef HAVE_STRUCT_UTIMBUF
157 /* We want to use utime rather than utimes, but we couldn't find the
158    structure declaration.  We'll use the traditional one.  */
159 struct utimbuf
160 {
161   long actime;
162   long modtime;
163 };
164 #endif
165 #endif
166
167 \f
168 /************************************************************************/
169 /*                         subprocess control                           */
170 /************************************************************************/
171
172 #ifdef HAVE_TTY
173
174 #ifdef SIGTSTP
175
176 /* Arrange for character C to be read as the next input from
177    the terminal.  */
178 void
179 stuff_char (struct console *con, int c)
180 {
181   int input_fd;
182
183   assert (CONSOLE_TTY_P (con));
184   input_fd = CONSOLE_TTY_DATA (con)->infd;
185 /* Should perhaps error if in batch mode */
186 #ifdef TIOCSTI
187   ioctl (input_fd, TIOCSTI, &c);
188 #else /* no TIOCSTI */
189   error ("Cannot stuff terminal input characters in this version of Unix.");
190 #endif /* no TIOCSTI */
191 }
192
193 #endif /* SIGTSTP */
194
195 #endif /* HAVE_TTY */
196
197 void
198 set_exclusive_use (int fd)
199 {
200 #ifdef FIOCLEX
201   ioctl (fd, FIOCLEX, 0);
202 #endif
203   /* Ok to do nothing if this feature does not exist */
204 }
205
206 void
207 set_descriptor_non_blocking (int fd)
208 {
209 /* Stride people say it's a mystery why this is needed
210    as well as the O_NDELAY, but that it fails without this.  */
211   /* For AIX: Apparently need this for non-blocking reads on sockets.
212      It seems that O_NONBLOCK applies only to FIFOs?  From
213      lowry@watson.ibm.com (Andy Lowry). */
214   /* #### Should this be conditionalized on FIONBIO? */
215 #if defined (STRIDE) || (defined (pfa) && defined (HAVE_PTYS)) || defined (AIX)
216   {
217     int one = 1;
218     ioctl (fd, FIONBIO, &one);
219   }
220 #endif
221
222 #ifdef F_SETFL
223   fcntl (fd, F_SETFL, O_NONBLOCK);
224 #endif
225 }
226
227 #if defined (NO_SUBPROCESSES)
228
229 #ifdef BSD
230 void
231 wait_without_blocking (void)
232 {
233   wait3 (0, WNOHANG | WUNTRACED, 0);
234   synch_process_alive = 0;
235 }
236 #endif /* BSD */
237
238 #endif /* NO_SUBPROCESSES */
239
240
241 #ifdef WINDOWSNT
242 void wait_for_termination (HANDLE pHandle)
243 #else
244 void wait_for_termination (int pid)
245 #endif
246 {
247   /* #### With the new improved SIGCHLD handling stuff, there is much
248      less danger of race conditions and some of the comments below
249      don't apply.  This should be updated. */
250
251 #if defined (NO_SUBPROCESSES)
252   while (1)
253     {
254       /* No need to be tricky like below; we can just call wait(). */
255       /* #### should figure out how to write a wait_allowing_quit().
256          Since hardly any systems don't have subprocess support,
257          however, there doesn't seem to be much point. */
258       if (wait (0) == pid)
259         return;
260     }
261 #elif defined (HAVE_WAITPID)
262   /* Note that, whenever any subprocess terminates (asynch. or synch.),
263      the SIGCHLD handler will be called and it will call wait().  Thus
264      we cannot just call wait() ourselves, and we can't block SIGCHLD
265      and then call wait(), because then if an asynch.  process dies
266      while we're waiting for our synch. process, Emacs will never
267      notice that the asynch. process died.
268
269      So, the general approach we take is to repeatedly block until a
270      signal arrives, and then check if our process died using kill
271      (pid, 0).  (We could also check the value of `synch_process_alive',
272      since the SIGCHLD handler will reset that and we know that we're
273      only being called on synchronous processes, but this approach is
274      safer.  I don't trust the proper delivery of SIGCHLD.
275
276      Note also that we cannot use any form of waitpid().  A loop with
277      WNOHANG will chew up CPU time; better to use sleep().  A loop
278      without WNOWAIT will screw up the SIGCHLD handler (actually this
279      is not true, if you duplicate the exit-status-reaping code; see
280      below).  A loop with WNOWAIT will result in a race condition if
281      the process terminates between the process-status check and the
282      call to waitpid(). */
283
284   /* Formerly, immediate_quit was set around this function call, but
285      that could lead to problems if the QUIT happened when SIGCHLD was
286      blocked -- it would remain blocked.  Yet another reason why
287      immediate_quit is a bad idea.  In any case, there is no reason to
288      resort to this because either the SIGIO or the SIGALRM will stop
289      the block in EMACS_WAIT_FOR_SIGNAL(). */
290
291   /* Apparently there are bugs on some systems with the second method
292      used below (the EMACS_BLOCK_SIGNAL method), whereby zombie
293      processes get left around.  It appears in those cases that the
294      SIGCHLD handler is never getting invoked.  It's not clear whether
295      this is an Emacs bug or a kernel bug or both: on HPUX this
296      problem is observed only with XEmacs, but under Solaris 2.4 all
297      sorts of different programs have problems with zombies.  The
298      method we use here does not require a working SIGCHLD (but will
299      not break if it is working), and should be safe. */
300   /*
301      We use waitpid(), contrary to the remarks above.  There is no
302      race condition, because the three situations when sigchld_handler
303      is invoked should be handled OK:
304
305      - handler invoked before waitpid(): In this case, subprocess
306        status will be set by sigchld_handler.  waitpid() here will
307        return -1 with errno set to ECHILD, which is a valid exit
308        condition.
309
310      - handler invoked during waitpid(): as above, except that errno
311        here will be set to EINTR.  This will cause waitpid() to be
312        called again, and this time it will exit with ECHILD.
313
314      - handler invoked after waitpid(): The following code will reap
315        the subprocess. In the handler, wait() will return -1 because
316        there is no child to reap, and the handler will exit without
317        modifying child subprocess status.  */
318   int ret, status;
319
320   /* Because the SIGCHLD handler can potentially reap the synchronous
321      subprocess, we should take care of that.  */
322
323   /* Will stay in the do loop as long as:
324      1. Process is alive
325      2. Ctrl-G is not pressed */
326   do
327     {
328       QUIT;
329       ret = waitpid (pid, &status, 0);
330       /* waitpid returns 0 if the process is still alive. */
331     }
332   while (ret == 0 || (ret == -1 && errno == EINTR));
333
334   if (ret == pid) /* Success */
335     /* Set synch process globals.  This is can also happen
336        in sigchld_handler, and that code is duplicated. */
337     {
338       synch_process_alive = 0;
339       if (WIFEXITED (status))
340         synch_process_retcode = WEXITSTATUS (status);
341       else if (WIFSIGNALED (status))
342         synch_process_death = signal_name (WTERMSIG (status));
343     }
344   /* On exiting the loop, ret will be -1, with errno set to ECHILD if
345      the child has already been reaped, e.g. in the signal handler.  */
346
347   /* Otherwise, we've had some error condition here.
348      Per POSIX, the only other possibilities are:
349      - EFAULT (bus error accessing arg 2) or
350      - EINVAL (incorrect arguments),
351      which are both program bugs.
352
353      Since implementations may add their own error indicators on top,
354      we ignore it by default.  */
355 #elif defined (WINDOWSNT)
356   int ret = 0, status = 0;
357   if (pHandle == NULL)
358     {
359       warn_when_safe (Qprocess, Qwarning, "Cannot wait for unknown process to terminate");
360       return;
361     }
362   do
363     {
364       QUIT;
365       ret = WaitForSingleObject(pHandle, 100);
366     }
367   while (ret == WAIT_TIMEOUT);
368   if (ret == WAIT_FAILED)
369     {
370       warn_when_safe (Qprocess, Qwarning, "waiting for process failed");
371     }
372   if (ret == WAIT_ABANDONED)
373     {
374       warn_when_safe (Qprocess, Qwarning,
375                       "process to wait for has been abandoned");
376     }
377   if (ret == WAIT_OBJECT_0)
378     {
379       ret = GetExitCodeProcess(pHandle, &status);
380       if (ret)
381         {
382           synch_process_alive = 0;
383           synch_process_retcode = status;
384         }
385       else
386         {
387           /* GetExitCodeProcess() didn't return a valid exit status,
388              nothing to do.  APA */
389           warn_when_safe (Qprocess, Qwarning,
390                           "failure to obtain process exit value");
391         }
392     }
393   if (pHandle != NULL && !CloseHandle(pHandle))
394     {
395       warn_when_safe (Qprocess, Qwarning,
396                       "failure to close unknown process");
397     }
398 #elif defined (EMACS_BLOCK_SIGNAL) && !defined (BROKEN_WAIT_FOR_SIGNAL) && defined (SIGCHLD)
399   while (1)
400     {
401       static int wait_debugging = 0; /* Set nonzero to make following
402                            function work under dbx (at least for bsd).  */
403       QUIT;
404       if (wait_debugging)
405         return;
406
407       EMACS_BLOCK_SIGNAL (SIGCHLD);
408       /* Block SIGCHLD from happening during this check,
409          to avoid race conditions. */
410       if (kill (pid, 0) < 0)
411         {
412           EMACS_UNBLOCK_SIGNAL (SIGCHLD);
413           return;
414         }
415       else
416         /* WARNING: Whatever this macro does *must* not allow SIGCHLD
417            to happen between the time that it's reenabled and when we
418            begin to block.  Otherwise we may end up blocking for a
419            signal that has already arrived and isn't coming again.
420            Can you say "race condition"?
421
422            I assume that the system calls sigpause() or sigsuspend()
423            to provide this atomicness.  If you're getting hangs in
424            sigpause()/sigsuspend(), then your OS doesn't implement
425            this properly (this applies under hpux9, for example).
426            Try defining BROKEN_WAIT_FOR_SIGNAL. */
427         EMACS_WAIT_FOR_SIGNAL (SIGCHLD);
428     }
429 #else /* not HAVE_WAITPID and not WINDOWSNT and (not EMACS_BLOCK_SIGNAL or BROKEN_WAIT_FOR_SIGNAL) */
430   /* This approach is kind of cheesy but is guaranteed(?!) to work
431      for all systems. */
432   while (1)
433     {
434       QUIT;
435       if (kill (pid, 0) < 0)
436         return;
437       emacs_sleep (1);
438     }
439 #endif /* OS features */
440 }
441
442
443 #if !defined (NO_SUBPROCESSES)
444
445 /*
446  *      flush any pending output
447  *      (may flush input as well; it does not matter the way we use it)
448  */
449
450 void
451 flush_pending_output (int channel)
452 {
453 #ifdef HAVE_TERMIOS
454   /* If we try this, we get hit with SIGTTIN, because
455      the child's tty belongs to the child's pgrp. */
456 #elif defined (TCFLSH)
457   ioctl (channel, TCFLSH, 1);
458 #elif defined (TIOCFLUSH)
459   int zero = 0;
460   /* 3rd arg should be ignored
461      but some 4.2 kernels actually want the address of an int
462      and nonzero means something different.  */
463   ioctl (channel, TIOCFLUSH, &zero);
464 #endif
465 }
466
467 #ifndef WINDOWSNT
468 /*  Set up the terminal at the other end of a pseudo-terminal that
469     we will be controlling an inferior through.
470     It should not echo or do line-editing, since that is done
471     in Emacs.  No padding needed for insertion into an Emacs buffer.  */
472
473 void
474 child_setup_tty (int out)
475 {
476   struct emacs_tty s;
477   emacs_get_tty (out, &s);
478
479 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
480   assert (isatty(out));
481   s.main.c_oflag |= OPOST;      /* Enable output postprocessing */
482   s.main.c_oflag &= ~ONLCR;     /* Disable map of NL to CR-NL on output */
483 #ifdef NLDLY
484   s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
485                                 /* No output delays */
486 #endif
487   s.main.c_lflag &= ~ECHO;      /* Disable echo */
488   s.main.c_lflag |= ISIG;       /* Enable signals */
489 #ifdef IUCLC
490   s.main.c_iflag &= ~IUCLC;     /* Disable downcasing on input.  */
491 #endif
492 #ifdef OLCUC
493   s.main.c_oflag &= ~OLCUC;     /* Disable upcasing on output.  */
494 #endif
495   s.main.c_oflag &= ~TAB3;      /* Disable tab expansion */
496 #if defined (CSIZE) && defined (CS8)
497   s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
498 #endif
499 #ifdef ISTRIP
500   s.main.c_iflag &= ~ISTRIP;    /* Don't strip 8th bit on input */
501 #endif
502 #if 0
503   /* Unnecessary as long as ICANON is set */
504   s.main.c_cc[VMIN]  = 1;       /* minimum number of characters to accept  */
505   s.main.c_cc[VTIME] = 0;       /* wait forever for at least 1 character  */
506 #endif /* 0 */
507
508   s.main.c_lflag |= ICANON;     /* Enable erase/kill and eof processing */
509   s.main.c_cc[VEOF] = 04;       /* ensure that EOF is Control-D */
510   s.main.c_cc[VERASE] = _POSIX_VDISABLE; /* disable erase processing */
511   s.main.c_cc[VKILL]  = _POSIX_VDISABLE; /* disable kill processing */
512
513 #ifdef HPUX
514   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
515 #endif /* HPUX */
516
517 #ifdef AIX
518 #ifndef IBMR2AIX
519   /* AIX enhanced edit loses NULs, so disable it. */
520   s.main.c_line = 0;
521   s.main.c_iflag &= ~ASCEDIT;
522 #endif /* IBMR2AIX */
523   /* Also, PTY overloads NUL and BREAK.
524      don't ignore break, but don't signal either, so it looks like NUL.
525      This really serves a purpose only if running in an XTERM window
526      or via TELNET or the like, but does no harm elsewhere.  */
527   s.main.c_iflag &= ~IGNBRK;
528   s.main.c_iflag &= ~BRKINT;
529 #endif /* AIX */
530 #ifdef SIGNALS_VIA_CHARACTERS
531   /* TTY `special characters' are used in process_send_signal
532      so set them here to something useful.  */
533   s.main.c_cc[VQUIT] = '\\'&037; /* Control-\ */
534   s.main.c_cc[VINTR] = 'C' &037; /* Control-C */
535   s.main.c_cc[VSUSP] = 'Z' &037; /* Control-Z */
536 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
537   /* TTY `special characters' work better as signals, so disable
538      character forms */
539   s.main.c_cc[VQUIT] = _POSIX_VDISABLE;
540   s.main.c_cc[VINTR] = _POSIX_VDISABLE;
541   s.main.c_cc[VSUSP] = _POSIX_VDISABLE;
542   s.main.c_lflag &= ~ISIG;
543 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
544   s.main.c_cc[VEOL] = _POSIX_VDISABLE;
545 #if defined (CBAUD)
546   /* <mdiers> #### This is not portable. ###
547      POSIX does not specify CBAUD, and 4.4BSD does not have it.
548      Instead, POSIX suggests to use cfset{i,o}speed().
549      [cf. D. Lewine, POSIX Programmer's Guide, Chapter 8: Terminal
550      I/O, O'Reilly 1991] */
551   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
552 #else
553   /* <mdiers> What to do upon failure? Just ignoring rc is probably
554      not acceptable, is it? */
555   if (cfsetispeed (&s.main, B9600) == -1) /* ignore */;
556   if (cfsetospeed (&s.main, B9600) == -1) /* ignore */;
557 #endif /* defined (CBAUD) */
558
559 #else /* not HAVE_TERMIO */
560
561   s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
562                        | CBREAK | TANDEM);
563   s.main.sg_flags |= LPASS8;
564   s.main.sg_erase = 0377;
565   s.main.sg_kill  = 0377;
566   s.lmode = LLITOUT | s.lmode;        /* Don't strip 8th bit */
567
568 #endif /* not HAVE_TERMIO */
569   emacs_set_tty (out, &s, 0);
570
571 #ifdef RTU
572   {
573     int zero = 0;
574     ioctl (out, FIOASYNC, &zero);
575   }
576 #endif /* RTU */
577 }
578 #endif /* WINDOWSNT */
579
580 #endif /* not NO_SUBPROCESSES */
581
582 \f
583 #if !defined (SIGTSTP) && !defined (USG_JOBCTRL)
584
585 #if defined(__STDC__) || defined(_MSC_VER)
586 #define SIG_PARAM_TYPE int
587 #else
588 #define SIG_PARAM_TYPE
589 #endif
590
591 /* Record a signal code and the handler for it.  */
592 struct save_signal
593 {
594   int code;
595   SIGTYPE (*handler) (SIG_PARAM_TYPE);
596 };
597
598 static void
599 save_signal_handlers (struct save_signal *saved_handlers)
600 {
601   while (saved_handlers->code)
602     {
603       saved_handlers->handler
604         = (SIGTYPE (*) (SIG_PARAM_TYPE)) signal (saved_handlers->code, SIG_IGN);
605       saved_handlers++;
606     }
607 }
608
609 static void
610 restore_signal_handlers (struct save_signal *saved_handlers)
611 {
612   while (saved_handlers->code)
613     {
614       signal (saved_handlers->code, saved_handlers->handler);
615       saved_handlers++;
616     }
617 }
618
619 #ifdef WINDOWSNT
620
621 pid_t
622 sys_getpid (void)
623 {
624   return abs (getpid ());
625 }
626
627 #endif /* WINDOWSNT */
628
629 /* Fork a subshell.  */
630 static void
631 sys_subshell (void)
632 {
633 #ifndef WINDOWSNT
634   int pid;
635 #endif
636   struct save_signal saved_handlers[5];
637   Lisp_Object dir;
638   unsigned char *str = 0;
639   int len;
640   struct gcpro gcpro1;
641
642   saved_handlers[0].code = SIGINT;
643   saved_handlers[1].code = SIGQUIT;
644   saved_handlers[2].code = SIGTERM;
645 #ifdef SIGIO
646   saved_handlers[3].code = SIGIO;
647   saved_handlers[4].code = 0;
648 #else
649   saved_handlers[3].code = 0;
650 #endif
651
652   /* Mentioning current_buffer->buffer would mean including buffer.h,
653      which somehow wedges the hp compiler.  So instead...  */
654
655   if (NILP (Fboundp (Qdefault_directory)))
656     goto xyzzy;
657   dir = Fsymbol_value (Qdefault_directory);
658   if (!STRINGP (dir))
659     goto xyzzy;
660
661   GCPRO1 (dir);
662   dir = Funhandled_file_name_directory (dir);
663   dir = expand_and_dir_to_file (dir, Qnil);
664   UNGCPRO;
665   str = (unsigned char *) alloca (XSTRING_LENGTH (dir) + 2);
666   len = XSTRING_LENGTH (dir);
667   memcpy (str, XSTRING_DATA (dir), len);
668   if (!IS_ANY_SEP (str[len - 1]))
669     str[len++] = DIRECTORY_SEP;
670   str[len] = 0;
671  xyzzy:
672
673 #ifndef WINDOWSNT
674   pid = fork ();
675
676   if (pid == -1)
677     error ("Can't spawn subshell");
678   if (pid == 0)
679 #endif /* not WINDOWSNT */
680   {
681       char *sh = 0;
682
683       if (sh == 0)
684         sh = (char *) egetenv ("SHELL");
685       if (sh == 0)
686         sh = "sh";
687
688     /* Use our buffer's default directory for the subshell.  */
689     if (str)
690       sys_chdir (str);
691
692 #ifdef WINDOWSNT
693
694     /* Waits for process completion */
695     if (_spawnlp (_P_WAIT, sh, sh, NULL) != 0)
696       error ("Can't spawn subshell");
697     else
698       return; /* we're done, no need to wait for termination */
699   }
700
701 #else
702
703 #if !defined (NO_SUBPROCESSES)
704     close_process_descs ();     /* Close Emacs's pipes/ptys */
705 #endif
706
707 #ifdef SET_EMACS_PRIORITY
708     if (emacs_priority != 0)
709       nice (-emacs_priority);   /* Give the new shell the default priority */
710 #endif
711
712     execlp (sh, sh, 0);
713     write (1, "Can't execute subshell", 22);
714     _exit (1);
715   }
716
717   save_signal_handlers (saved_handlers);
718   synch_process_alive = 1;
719   wait_for_termination (pid);
720   restore_signal_handlers (saved_handlers);
721
722 #endif /* not WINDOWSNT */
723
724 }
725
726 #endif /* !defined (SIGTSTP) && !defined (USG_JOBCTRL) */
727
728
729 \f
730 /* Suspend the Emacs process; give terminal to its superior.  */
731 void
732 sys_suspend (void)
733 {
734 #if defined (SIGTSTP)
735   {
736     int pgrp = EMACS_GET_PROCESS_GROUP ();
737     EMACS_KILLPG (pgrp, SIGTSTP);
738   }
739
740 #elif defined (USG_JOBCTRL)
741   /* If you don't know what this is don't mess with it */
742   ptrace (0, 0, 0, 0);          /* set for ptrace - caught by csh */
743   kill (getpid (), SIGQUIT);
744
745 #else /* No SIGTSTP or USG_JOBCTRL */
746
747   /* On a system where suspending is not implemented,
748      instead fork a subshell and let it talk directly to the terminal
749      while we wait.  */
750   sys_subshell ();
751
752 #endif
753 }
754
755 /* Suspend a process if possible; give terminal to its superior.  */
756 void
757 sys_suspend_process (int process)
758 {
759     /* I don't doubt that it is possible to suspend processes on
760      * VMS machines or thost that use USG_JOBCTRL,
761      * but I don't know how to do it, so...
762      */
763 #if defined (SIGTSTP)
764     kill(process, SIGTSTP);
765 #endif
766 }
767 \f
768
769 /* Given FD, obtain pty buffer size. When no luck, a good guess is made,
770    so that the function works even fd is not a pty. */
771
772 int
773 get_pty_max_bytes (int fd)
774 {
775   int pty_max_bytes;
776
777 #if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
778   pty_max_bytes = fpathconf (fd, _PC_MAX_CANON);
779   if (pty_max_bytes < 0)
780 #endif
781     pty_max_bytes = 250;
782
783   /* Deduct one, to leave space for the eof.  */
784   pty_max_bytes--;
785
786   return pty_max_bytes;
787 }
788
789 /* Figure out the eof character for the FD. */
790
791 Bufbyte
792 get_eof_char (int fd)
793 {
794   const Bufbyte ctrl_d = (Bufbyte) '\004';
795
796   if (!isatty (fd))
797     return ctrl_d;
798 #ifdef HAVE_TERMIOS
799   {
800     struct termios t;
801     tcgetattr (fd, &t);
802 #if 0
803     /* What is the following line designed to do??? -mrb */
804     if (strlen ((const char *) t.c_cc) < (unsigned int) (VEOF + 1))
805       return ctrl_d;
806     else
807       return (Bufbyte) t.c_cc[VEOF];
808 #endif
809     return t.c_cc[VEOF] == _POSIX_VDISABLE ? ctrl_d : (Bufbyte) t.c_cc[VEOF];
810   }
811 #else /* ! HAVE_TERMIOS */
812   /* On Berkeley descendants, the following IOCTL's retrieve the
813     current control characters.  */
814 #if defined (TIOCGETC)
815   {
816     struct tchars c;
817     ioctl (fd, TIOCGETC, &c);
818     return (Bufbyte) c.t_eofc;
819   }
820 #else /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
821   /* On SYSV descendants, the TCGETA ioctl retrieves the current control
822      characters.  */
823 #ifdef TCGETA
824   {
825     struct termio t;
826     ioctl (fd, TCGETA, &t);
827     if (strlen ((const char *) t.c_cc) < (unsigned int) (VINTR + 1))
828       return ctrl_d;
829     else
830       return (Bufbyte) t.c_cc[VINTR];
831   }
832 #else /* ! defined (TCGETA) */
833   /* Rather than complain, we'll just guess ^D, which is what
834    * earlier emacsen always used. */
835   return ctrl_d;
836 #endif /* ! defined (TCGETA) */
837 #endif /* ! defined (TIOCGETC) */
838 #endif /* ! defined (HAVE_TERMIOS) */
839 }
840
841 /* Set the logical window size associated with descriptor FD
842    to HEIGHT and WIDTH.  This is used mainly with ptys.  */
843
844 int
845 set_window_size (int fd, int height, int width)
846 {
847 #ifdef TIOCSWINSZ
848
849   /* BSD-style.  */
850   struct winsize size;
851   size.ws_row = height;
852   size.ws_col = width;
853
854   if (ioctl (fd, TIOCSWINSZ, &size) == -1)
855     return 0; /* error */
856   else
857     return 1;
858
859 #elif defined (TIOCSSIZE)
860
861   /* SunOS - style.  */
862   struct ttysize size;
863   size.ts_lines = height;
864   size.ts_cols = width;
865
866   if (ioctl (fd, TIOCGSIZE, &size) == -1)
867     return 0;
868   else
869     return 1;
870 #else
871   return -1;
872 #endif
873 }
874
875 #ifdef HAVE_PTYS
876
877 /* Set up the proper status flags for use of a pty.  */
878
879 void
880 setup_pty (int fd)
881 {
882   /* I'm told that TOICREMOTE does not mean control chars
883      "can't be sent" but rather that they don't have
884      input-editing or signaling effects.
885      That should be good, because we have other ways
886      to do those things in Emacs.
887      However, telnet mode seems not to work on 4.2.
888      So TIOCREMOTE is turned off now. */
889
890   /* Under hp-ux, if TIOCREMOTE is turned on, some calls
891      will hang.  In particular, the "timeout" feature (which
892      causes a read to return if there is no data available)
893      does this.  Also it is known that telnet mode will hang
894      in such a way that Emacs must be stopped (perhaps this
895      is the same problem).
896
897      If TIOCREMOTE is turned off, then there is a bug in
898      hp-ux which sometimes loses data.  Apparently the
899      code which blocks the master process when the internal
900      buffer fills up does not work.  Other than this,
901      though, everything else seems to work fine.
902
903      Since the latter lossage is more benign, we may as well
904      lose that way.  -- cph */
905 #if defined (FIONBIO) && defined (SYSV_PTYS)
906   {
907     int on = 1;
908     ioctl (fd, FIONBIO, &on);
909   }
910 #endif
911 #ifdef IBMRTAIX
912   /* On AIX, the parent gets SIGHUP when a pty attached child dies.  So, we */
913   /* ignore SIGHUP once we've started a child on a pty.  Note that this may */
914   /* cause EMACS not to die when it should, i.e., when its own controlling  */
915   /* tty goes away.  I've complained to the AIX developers, and they may    */
916   /* change this behavior, but I'm not going to hold my breath.             */
917   signal (SIGHUP, SIG_IGN);
918 #endif
919 #ifdef TIOCPKT
920   /* In some systems (Linux through 2.0.0, at least), packet mode doesn't
921      get cleared when a pty is closed, so we need to clear it here.
922      Linux pre2.0.13 contained an attempted fix for this (from Ted Ts'o,
923      tytso@mit.edu), but apparently it messed up rlogind and telnetd, so he
924      removed the fix in pre2.0.14.     - dkindred@cs.cmu.edu
925    */
926   {
927     int off = 0;
928     ioctl (fd, TIOCPKT, (char *)&off);
929   }
930 #endif
931 }
932 #endif /* HAVE_PTYS */
933
934 \f
935 /************************************************************************/
936 /*                            TTY control                               */
937 /************************************************************************/
938
939 /* ------------------------------------------------------ */
940 /*                     get baud rate                      */
941 /* ------------------------------------------------------ */
942
943 /* It really makes more sense for the baud-rate to be console-specific
944    and not device-specific, but it's (at least potentially) used for output
945    decisions. */
946
947 void
948 init_baud_rate (struct device *d)
949 {
950   struct console *con = XCONSOLE (DEVICE_CONSOLE (d));
951   if (DEVICE_WIN_P (d) || DEVICE_STREAM_P (d))
952     {
953       DEVICE_BAUD_RATE (d) = 38400;
954       return;
955     }
956
957 #ifdef HAVE_TTY
958   assert (DEVICE_TTY_P (d));
959   {
960     int input_fd = CONSOLE_TTY_DATA (con)->infd;
961 #if defined (WINDOWSNT)
962     DEVICE_TTY_DATA (d)->ospeed = 15;
963 #elif defined (HAVE_TERMIOS)
964     struct termios sg;
965
966     sg.c_cflag = B9600;
967     tcgetattr (input_fd, &sg);
968     DEVICE_TTY_DATA (d)->ospeed = cfgetospeed (&sg);
969 # if defined (USE_GETOBAUD) && defined (getobaud)
970     /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
971     if (DEVICE_TTY_DATA (d)->ospeed == 0)
972       DEVICE_TTY_DATA (d)->ospeed = getobaud (sg.c_cflag);
973 # endif
974 #elif defined (HAVE_TERMIO)
975     struct termio sg;
976
977     sg.c_cflag = B9600;
978 # ifdef HAVE_TCATTR
979     tcgetattr (input_fd, &sg);
980 # else
981     ioctl (input_fd, TCGETA, &sg);
982 # endif
983     DEVICE_TTY_DATA (d)->ospeed = sg.c_cflag & CBAUD;
984 #else /* neither TERMIOS nor TERMIO */
985     struct sgttyb sg;
986
987     sg.sg_ospeed = B9600;
988     if (ioctl (input_fd, TIOCGETP, &sg) < 0)
989       abort ();
990     DEVICE_TTY_DATA (d)->ospeed = sg.sg_ospeed;
991 #endif
992   }
993
994   DEVICE_BAUD_RATE (d) =
995     (DEVICE_TTY_DATA (d)->ospeed < countof (baud_convert)
996      ? baud_convert[DEVICE_TTY_DATA (d)->ospeed]
997      : 9600);
998
999   if (DEVICE_BAUD_RATE (d) == 0)
1000     DEVICE_BAUD_RATE (d) = 1200;
1001 #endif /* HAVE_TTY */
1002 }
1003
1004 \f
1005 /* ------------------------------------------------------ */
1006 /*                       SIGIO control                    */
1007 /* ------------------------------------------------------ */
1008
1009 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
1010
1011 static void
1012 init_sigio_on_device (struct device *d)
1013 {
1014   int filedesc = DEVICE_INFD (d);
1015
1016 #if defined (FIOSSAIOOWN)
1017   { /* HPUX stuff */
1018     int owner = getpid ();
1019     int ioctl_status;
1020     if (DEVICE_TTY_P (d))
1021         {
1022           ioctl_status = ioctl (filedesc, FIOGSAIOOWN,
1023                                 &DEVICE_OLD_FCNTL_OWNER (d));
1024           ioctl_status = ioctl (filedesc, FIOSSAIOOWN, &owner);
1025         }
1026 #ifdef HAVE_WINDOW_SYSTEM
1027     else if (!DEVICE_STREAM_P (d))
1028       {
1029         ioctl_status = ioctl (filedesc, SIOCGPGRP,
1030                               &DEVICE_OLD_FCNTL_OWNER (d));
1031         ioctl_status = ioctl (filedesc, SIOCSPGRP, &owner);
1032       }
1033 #endif
1034   }
1035 #elif defined (F_SETOWN) && !defined (F_SETOWN_BUG)
1036   DEVICE_OLD_FCNTL_OWNER (d) = fcntl (filedesc, F_GETOWN, 0);
1037 # ifdef F_SETOWN_SOCK_NEG
1038   /* stdin is a socket here */
1039   fcntl (filedesc, F_SETOWN, -getpid ());
1040 # else
1041   fcntl (filedesc, F_SETOWN, getpid ());
1042 # endif
1043 #endif
1044 }
1045
1046 static void
1047 reset_sigio_on_device (struct device *d)
1048 {
1049   int filedesc = DEVICE_INFD (d);
1050
1051 #if defined (FIOSSAIOOWN)
1052   { /* HPUX stuff */
1053     int ioctl_status;
1054     if (DEVICE_TTY_P (d))
1055       {
1056         ioctl_status = ioctl (filedesc, FIOSSAIOOWN,
1057                               &DEVICE_OLD_FCNTL_OWNER (d));
1058       }
1059 #ifdef HAVE_WINDOW_SYSTEM
1060     else if (!DEVICE_STREAM_P (d))
1061       {
1062         ioctl_status = ioctl (filedesc, SIOCSPGRP,
1063                               &DEVICE_OLD_FCNTL_OWNER (d));
1064       }
1065 #endif
1066   }
1067 #elif defined (F_SETOWN) && !defined (F_SETOWN_BUG)
1068   fcntl (filedesc, F_SETOWN, DEVICE_OLD_FCNTL_OWNER (d));
1069 #endif
1070 }
1071
1072 static void
1073 request_sigio_on_device (struct device *d)
1074 {
1075   int filedesc = DEVICE_INFD (d);
1076
1077 #if defined (I_SETSIG) && !defined(HPUX10) && !defined(LINUX)
1078   {
1079     int events=0;
1080     ioctl (filedesc, I_GETSIG, &events);
1081     ioctl (filedesc, I_SETSIG, events | S_INPUT);
1082   }
1083 #elif defined (FASYNC)
1084   fcntl (filedesc, F_SETFL, fcntl (filedesc, F_GETFL, 0) | FASYNC);
1085 #elif defined (FIOSSAIOSTAT)
1086   {
1087       /* DG: Changed for HP-UX. HP-UX uses different IOCTLs for
1088          sockets and other devices for some bizarre reason. We guess
1089          that an X device is a socket, and tty devices aren't. We then
1090          use the following crud to do the appropriate thing. */
1091     int on = 1;
1092     int ioctl_status;           /* ####DG: check if IOCTL succeeds here. */
1093
1094     if (DEVICE_TTY_P (d))
1095       {
1096         ioctl_status = ioctl (filedesc, FIOSSAIOSTAT, &on);
1097       }
1098 #ifdef HAVE_WINDOW_SYSTEM
1099     else if (!DEVICE_STREAM_P (d))
1100       {
1101         ioctl_status = ioctl (filedesc, FIOASYNC, &on);
1102       }
1103 #endif
1104   }
1105 #elif defined (FIOASYNC)
1106   {
1107     int on = 1;
1108     ioctl (filedesc, FIOASYNC, &on);
1109   }
1110 #endif
1111
1112 #if defined (_CX_UX) /* #### Is this crap necessary? */
1113   EMACS_UNBLOCK_SIGNAL (SIGIO);
1114 #endif
1115 }
1116
1117 static void
1118 unrequest_sigio_on_device (struct device *d)
1119 {
1120   int filedesc = DEVICE_INFD (d);
1121
1122 #if defined (I_SETSIG) && !defined(HPUX10)
1123   {
1124     int events=0;
1125     ioctl (filedesc, I_GETSIG, &events);
1126     ioctl (filedesc, I_SETSIG, events & ~S_INPUT);
1127   }
1128 #elif defined (FASYNC)
1129   fcntl (filedesc, F_SETFL, fcntl (filedesc, F_GETFL, 0) & ~FASYNC);
1130 #elif defined (FIOSSAIOSTAT)
1131   {
1132       /* DG: Changed for HP-UX. HP-UX uses different IOCTLs for
1133          sockets and other devices for some bizarre reason. We guess
1134          that an X device is a socket, and tty devices aren't. We then
1135          use the following crud to do the appropriate thing. */
1136
1137     int off = 0;
1138     int ioctl_status;
1139
1140     /* See comment for request_sigio_on_device */
1141
1142     if (DEVICE_TTY_P (d))
1143       {
1144         ioctl_status = ioctl (filedesc, FIOSSAIOSTAT, &off);
1145       }
1146     else
1147       {
1148         ioctl_status = ioctl (filedesc, FIOASYNC, &off);
1149       }
1150   }
1151 #elif defined (FIOASYNC)
1152   {
1153     int off = 0;
1154     ioctl (filedesc, FIOASYNC, &off);
1155   }
1156 #endif
1157 }
1158
1159 void
1160 request_sigio (void)
1161 {
1162   Lisp_Object devcons, concons;
1163
1164   DEVICE_LOOP_NO_BREAK (devcons, concons)
1165     {
1166       struct device *d;
1167
1168       d = XDEVICE (XCAR (devcons));
1169
1170       if (!DEVICE_STREAM_P (d))
1171         request_sigio_on_device (d);
1172     }
1173 }
1174
1175 void
1176 unrequest_sigio (void)
1177 {
1178   Lisp_Object devcons, concons;
1179
1180   DEVICE_LOOP_NO_BREAK (devcons, concons)
1181     {
1182       struct device *d;
1183
1184       d = XDEVICE (XCAR (devcons));
1185
1186       if (!DEVICE_STREAM_P (d))
1187         unrequest_sigio_on_device (d);
1188     }
1189 }
1190
1191 #endif /* SIGIO */
1192 \f
1193 /* ------------------------------------------------------ */
1194 /*             Changing Emacs's process group             */
1195 /* ------------------------------------------------------ */
1196
1197 /* Saving and restoring the process group of Emacs's terminal.  */
1198
1199 /* On some systems, apparently (?!) Emacs must be in its own process
1200    group in order to receive SIGIO correctly.  On other systems
1201    (e.g. Solaris), it's not required and doing it makes things
1202    get fucked up.  So, we only do it when
1203    SIGIO_REQUIRES_SEPARATE_PROCESS_GROUP is defined.  Basically,
1204    this is only required for BSD 4.2 systems. (Actually, I bet
1205    we don't have to do this at all -- those systems also
1206    required interrupt input, which we don't support.)
1207
1208    If Emacs was in its own process group (i.e. inherited_pgroup ==
1209    getpid ()), then we know we're running under a shell with job
1210    control (Emacs would never be run as part of a pipeline).
1211    Everything is fine.
1212
1213    If Emacs was not in its own process group, then we know we're
1214    running under a shell (or a caller) that doesn't know how to
1215    separate itself from Emacs (like sh).  Emacs must be in its own
1216    process group in order to receive SIGIO correctly.  In this
1217    situation, we put ourselves in our own pgroup, forcibly set the
1218    tty's pgroup to our pgroup, and make sure to restore and reinstate
1219    the tty's pgroup just like any other terminal setting.  If
1220    inherited_group was not the tty's pgroup, then we'll get a
1221    SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1222    it goes foreground in the future, which is what should happen.  */
1223
1224 #ifdef SIGIO_REQUIRES_SEPARATE_PROCESS_GROUP
1225
1226 static int inherited_pgroup;
1227 static int inherited_tty_pgroup;
1228
1229 #endif
1230
1231 void
1232 munge_tty_process_group (void)
1233 {
1234 #ifdef SIGIO_REQUIRES_SEPARATE_PROCESS_GROUP
1235   if (noninteractive)
1236     return;
1237
1238   /* Only do this munging if we have a device on the controlling
1239      terminal.  See the large comment below. */
1240
1241   if (CONSOLEP (Vcontrolling_terminal) &&
1242       CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)))
1243     {
1244       int fd = open ("/dev/tty", O_RDWR, 0);
1245       int me = getpid ();
1246       EMACS_BLOCK_SIGNAL (SIGTTOU);
1247       EMACS_SET_TTY_PROCESS_GROUP (fd, &me);
1248       EMACS_UNBLOCK_SIGNAL (SIGTTOU);
1249       close (fd);
1250     }
1251 #endif
1252 }
1253
1254 /* Split off the foreground process group to Emacs alone.
1255    When we are in the foreground, but not started in our own process
1256    group, redirect the TTY to point to our own process group.  We need
1257    to be in our own process group to receive SIGIO properly.  */
1258 static void
1259 munge_process_groups (void)
1260 {
1261 #ifdef SIGIO_REQUIRES_SEPARATE_PROCESS_GROUP
1262   if (noninteractive)
1263     return;
1264
1265   EMACS_SEPARATE_PROCESS_GROUP ();
1266
1267   munge_tty_process_group ();
1268 #endif
1269 }
1270
1271 void
1272 unmunge_tty_process_group (void)
1273 {
1274 #ifdef SIGIO_REQUIRES_SEPARATE_PROCESS_GROUP
1275   {
1276     int fd = open ("/dev/tty", O_RDWR, 0);
1277     EMACS_BLOCK_SIGNAL (SIGTTOU);
1278     EMACS_SET_TTY_PROCESS_GROUP (fd, &inherited_tty_pgroup);
1279     EMACS_UNBLOCK_SIGNAL (SIGTTOU);
1280     close (fd);
1281   }
1282 #endif
1283 }
1284
1285 /* Set the tty to our original foreground group.
1286    Also restore the original process group (put us back into sh's
1287    process group), so that ^Z will suspend both us and sh. */
1288 static void
1289 unmunge_process_groups (void)
1290 {
1291 #ifdef SIGIO_REQUIRES_SEPARATE_PROCESS_GROUP
1292   if (noninteractive)
1293     return;
1294
1295   unmunge_tty_process_group ();
1296
1297   EMACS_SET_PROCESS_GROUP (inherited_pgroup);
1298 #endif
1299 }
1300
1301 /* According to some old wisdom, we need to be in a separate process
1302    group for SIGIO to work correctly (at least on some systems ...).
1303    So go ahead and put ourselves into our own process group.  This
1304    will fail if we're already in our own process group, but who cares.
1305    Also record whether we were in our own process group. (In general,
1306    we will already be in our own process group if we were started from
1307    a job-control shell like csh, but not if we were started from sh).
1308
1309    If we succeeded in changing our process group, then we will no
1310    longer be in the foreground process group of our controlling
1311    terminal.  Therefore, if we have a console open onto this terminal,
1312    we have to change the controlling terminal's foreground process
1313    group (otherwise we will get stopped with a SIGTTIN signal when
1314    attempting to read from the terminal).  It's important,
1315    however, that we do this *only* when we have a console open onto
1316    the terminal.  It's a decidedly bad idea to do so otherwise,
1317    especially if XEmacs was started from the background. */
1318
1319 void
1320 init_process_group (void)
1321 {
1322 #ifdef SIGIO_REQUIRES_SEPARATE_PROCESS_GROUP
1323   if (! noninteractive)
1324     {
1325       int fd = open ("/dev/tty", O_RDWR, 0);
1326       inherited_pgroup = EMACS_GET_PROCESS_GROUP ();
1327       EMACS_GET_TTY_PROCESS_GROUP (fd, &inherited_tty_pgroup);
1328       close (fd);
1329       EMACS_SEPARATE_PROCESS_GROUP ();
1330     }
1331 #endif
1332 }
1333
1334 void
1335 disconnect_controlling_terminal (void)
1336 {
1337 #  ifdef HAVE_SETSID
1338   /* Controlling terminals are attached to a session.
1339      Create a new session for us; it will have no controlling
1340      terminal.  This also, of course, puts us in our own
1341      process group. */
1342   setsid ();
1343 #  else
1344   /* Put us in our own process group. */
1345   EMACS_SEPARATE_PROCESS_GROUP ();
1346 #    if defined (TIOCNOTTY)
1347   /* This is the older way of disconnecting the controlling
1348      terminal, on 4.3 BSD.  We must open /dev/tty; using
1349      filedesc 0 is not sufficient because it could be
1350      something else (e.g. our stdin was redirected to
1351      another terminal).
1352      */
1353   {
1354     int j = open ("/dev/tty", O_RDWR, 0);
1355     ioctl (j, TIOCNOTTY, 0);
1356     close (j);
1357   }
1358 #    endif /* TIOCNOTTY */
1359   /*
1360      On systems without TIOCNOTTY and without
1361      setsid(), we don't need to do anything more to
1362      disconnect our controlling terminal.  Here is
1363      what the man page for termio(7) from a SYSV 3.2
1364      system says:
1365
1366      "The first terminal file opened by the process group leader
1367      of a terminal file not already associated with a process
1368      group becomes the control terminal for that process group.
1369      The control terminal plays a special role in handling quit
1370      and interrupt signals, as discussed below.  The control
1371      terminal is inherited by a child process during a fork(2).
1372      A process can break this association by changing its process
1373      group using setpgrp(2)."
1374
1375      */
1376 #  endif /* not HAVE_SETSID */
1377 }
1378
1379 \f
1380 /* ------------------------------------------------------ */
1381 /*        Getting and setting emacs_tty structures        */
1382 /* ------------------------------------------------------ */
1383
1384 /* It's wrong to encase these into #ifdef HAVE_TTY because we need
1385    them for child TTY processes.  */
1386 /* However, this does break NT support while we don't do child TTY processes */
1387 #ifndef WINDOWSNT
1388
1389 /* Set *TC to the parameters associated with the terminal FD.
1390    Return zero if all's well, or -1 if we ran into an error we
1391    couldn't deal with.  */
1392 int
1393 emacs_get_tty (int fd, struct emacs_tty *settings)
1394 {
1395   /* Retrieve the primary parameters - baud rate, character size, etcetera.  */
1396 #ifdef HAVE_TCATTR
1397   /* We have those nifty POSIX tcmumbleattr functions.  */
1398   if (tcgetattr (fd, &settings->main) < 0)
1399     return -1;
1400
1401 #elif defined HAVE_TERMIO
1402   /* The SYSV-style interface?  */
1403   if (ioctl (fd, TCGETA, &settings->main) < 0)
1404     return -1;
1405
1406 #elif !defined (WINDOWSNT)
1407   /* I give up - I hope you have the BSD ioctls.  */
1408   if (ioctl (fd, TIOCGETP, &settings->main) < 0)
1409     return -1;
1410 #endif /* HAVE_TCATTR */
1411
1412   /* Suivant - Do we have to get struct ltchars data?  */
1413 #ifdef HAVE_LTCHARS
1414   if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
1415     return -1;
1416 #endif
1417
1418   /* How about a struct tchars and a wordful of lmode bits?  */
1419 #ifdef HAVE_TCHARS
1420   if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
1421       || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
1422     return -1;
1423 #endif
1424
1425   /* We have survived the tempest.  */
1426   return 0;
1427 }
1428
1429 /* Set the parameters of the tty on FD according to the contents of
1430    *SETTINGS.  If FLUSHP is non-zero, we discard input.
1431    Return 0 if all went well, and -1 if anything failed.
1432    #### All current callers use FLUSHP == 0. */
1433
1434 int
1435 emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
1436 {
1437   /* Set the primary parameters - baud rate, character size, etcetera.  */
1438 #ifdef HAVE_TCATTR
1439   int i;
1440   /* We have those nifty POSIX tcmumbleattr functions.
1441      William J. Smith <wjs@wiis.wang.com> writes:
1442      "POSIX 1003.1 defines tcsetattr() to return success if it was
1443      able to perform any of the requested actions, even if some
1444      of the requested actions could not be performed.
1445      We must read settings back to ensure tty setup properly.
1446      AIX requires this to keep tty from hanging occasionally."  */
1447   /* This makes sure that we don't loop indefinitely in here.  */
1448   for (i = 0 ; i < 10 ; i++)
1449     if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
1450       {
1451         if (errno == EINTR)
1452           continue;
1453         else
1454           return -1;
1455       }
1456     else
1457       {
1458         struct termios new;
1459
1460         /* Get the current settings, and see if they're what we asked for.  */
1461         tcgetattr (fd, &new);
1462         /* We cannot use memcmp on the whole structure here because under
1463          * aix386 the termios structure has some reserved field that may
1464          * not be filled in.
1465          */
1466         if (   new.c_iflag == settings->main.c_iflag
1467             && new.c_oflag == settings->main.c_oflag
1468             && new.c_cflag == settings->main.c_cflag
1469             && new.c_lflag == settings->main.c_lflag
1470             && memcmp(new.c_cc, settings->main.c_cc, NCCS) == 0)
1471           break;
1472         else
1473           continue;
1474       }
1475 #elif defined HAVE_TERMIO
1476   /* The SYSV-style interface?  */
1477   if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
1478     return -1;
1479
1480 #elif !defined (WINDOWSNT)
1481   /* I give up - I hope you have the BSD ioctls.  */
1482   if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
1483     return -1;
1484 #endif /* HAVE_TCATTR */
1485
1486   /* Suivant - Do we have to get struct ltchars data?  */
1487 #ifdef HAVE_LTCHARS
1488   if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
1489     return -1;
1490 #endif
1491
1492   /* How about a struct tchars and a wordful of lmode bits?  */
1493 #ifdef HAVE_TCHARS
1494   if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
1495       || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
1496     return -1;
1497 #endif
1498
1499   /* We have survived the tempest.  */
1500   return 0;
1501 }
1502
1503 #endif /* WINDOWSNT */
1504 \f
1505 /* ------------------------------------------------------ */
1506 /*                 Initializing a device                  */
1507 /* ------------------------------------------------------ */
1508
1509 #ifdef HAVE_TTY
1510
1511 /* This may also be defined in stdio,
1512    but if so, this does no harm,
1513    and using the same name avoids wasting the other one's space.  */
1514
1515 #if ((defined(USG) || defined(DGUX)) && !defined(__STDC__))
1516 char _sobuf[BUFSIZ+8];
1517 #elif (defined(USG) && !defined(LINUX) && !defined(_SCO_DS)) || defined(IRIX5)
1518 extern unsigned char _sobuf[BUFSIZ+8];
1519 #else
1520 char _sobuf[BUFSIZ];
1521 #endif
1522
1523 #if defined (TIOCGLTC) && defined (HAVE_LTCHARS) /* HAVE_LTCHARS */
1524 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
1525 #endif
1526 #ifdef TIOCGETC /* HAVE_TCHARS */
1527 #ifdef HAVE_TCHARS
1528 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
1529 #endif
1530 #endif
1531
1532 static void
1533 tty_init_sys_modes_on_device (struct device *d)
1534 {
1535   struct emacs_tty tty;
1536   int input_fd, output_fd;
1537   struct console *con = XCONSOLE (DEVICE_CONSOLE (d));
1538
1539   input_fd = CONSOLE_TTY_DATA (con)->infd;
1540   output_fd = CONSOLE_TTY_DATA (con)->outfd;
1541
1542   emacs_get_tty (input_fd, &CONSOLE_TTY_DATA (con)->old_tty);
1543   tty = CONSOLE_TTY_DATA (con)->old_tty;
1544
1545   con->tty_erase_char = Qnil;
1546
1547 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1548   /* after all those years... */
1549   con->tty_erase_char = make_char (tty.main.c_cc[VERASE]);
1550 #ifdef DGUX
1551   /* This allows meta to be sent on 8th bit.  */
1552   tty.main.c_iflag &= ~INPCK;   /* don't check input for parity */
1553 #endif
1554   tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
1555   tty.main.c_iflag &= ~ICRNL;   /* Disable map of CR to NL on input */
1556 #ifdef ISTRIP
1557   tty.main.c_iflag &= ~ISTRIP;  /* don't strip 8th bit on input */
1558 #endif
1559   tty.main.c_lflag &= ~ECHO;    /* Disable echo */
1560   tty.main.c_lflag &= ~ICANON;  /* Disable erase/kill processing */
1561 #ifdef IEXTEN
1562   tty.main.c_lflag &= ~IEXTEN;  /* Disable other editing characters.  */
1563 #endif
1564   tty.main.c_lflag |= ISIG;     /* Enable signals */
1565   if (TTY_FLAGS (con).flow_control)
1566     {
1567       tty.main.c_iflag |= IXON; /* Enable start/stop output control */
1568 #ifdef IXANY
1569       tty.main.c_iflag &= ~IXANY;
1570 #endif /* IXANY */
1571     }
1572   else
1573     tty.main.c_iflag &= ~IXON;  /* Disable start/stop output control */
1574   tty.main.c_oflag &= ~ONLCR;   /* Disable map of NL to CR-NL
1575                                    on output */
1576   tty.main.c_oflag &= ~TAB3;    /* Disable tab expansion */
1577 #ifdef CS8
1578   if (TTY_FLAGS (con).meta_key)
1579     {
1580       tty.main.c_cflag |= CS8;  /* allow 8th bit on input */
1581       tty.main.c_cflag &= ~PARENB;/* Don't check parity */
1582     }
1583 #endif
1584   if (CONSOLE_TTY_DATA (con)->controlling_terminal)
1585     {
1586       tty.main.c_cc[VINTR] =
1587         CONSOLE_QUIT_CHAR (con); /* C-g (usually) gives SIGINT */
1588       /* Set up C-g for both SIGQUIT and SIGINT.
1589          We don't know which we will get, but we handle both alike
1590          so which one it really gives us does not matter.  */
1591       tty.main.c_cc[VQUIT] = CONSOLE_QUIT_CHAR (con);
1592     }
1593   else
1594     {
1595       tty.main.c_cc[VINTR] = _POSIX_VDISABLE;
1596       tty.main.c_cc[VQUIT] = _POSIX_VDISABLE;
1597     }
1598   tty.main.c_cc[VMIN] = 1;      /* Input should wait for at
1599                                    least 1 char */
1600   tty.main.c_cc[VTIME] = 0;     /* no matter how long that takes.  */
1601 #ifdef VSWTCH
1602   tty.main.c_cc[VSWTCH] = _POSIX_VDISABLE; /* Turn off shell layering use
1603                                               of C-z */
1604 #endif /* VSWTCH */
1605   /* There was some conditionalizing here on (mips or TCATTR), but
1606      I think that's wrong.  There was one report of C-y (DSUSP) not being
1607      disabled on HP9000s700 systems, and this might fix it. */
1608 #ifdef VSUSP
1609   tty.main.c_cc[VSUSP] = _POSIX_VDISABLE; /* Turn off mips handling of C-z. */
1610 #endif /* VSUSP */
1611 #ifdef V_DSUSP
1612   tty.main.c_cc[V_DSUSP] = _POSIX_VDISABLE; /* Turn off mips handling of C-y. */
1613 #endif /* V_DSUSP */
1614 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP.  */
1615   tty.main.c_cc[VDSUSP] = _POSIX_VDISABLE;
1616 #endif /* VDSUSP */
1617 #ifdef VLNEXT
1618   tty.main.c_cc[VLNEXT] = _POSIX_VDISABLE;
1619 #endif /* VLNEXT */
1620 #ifdef VREPRINT
1621   tty.main.c_cc[VREPRINT] = _POSIX_VDISABLE;
1622 #endif /* VREPRINT */
1623 #ifdef VWERASE
1624   tty.main.c_cc[VWERASE] = _POSIX_VDISABLE;
1625 #endif /* VWERASE */
1626 #ifdef VDISCARD
1627   tty.main.c_cc[VDISCARD] = _POSIX_VDISABLE;
1628 #endif /* VDISCARD */
1629 #ifdef VSTART
1630   tty.main.c_cc[VSTART] = _POSIX_VDISABLE;
1631 #endif /* VSTART */
1632 #ifdef VSTRT
1633   tty.main.c_cc[VSTRT] = _POSIX_VDISABLE; /* called VSTRT on some systems */
1634 #endif /* VSTART */
1635 #ifdef VSTOP
1636   tty.main.c_cc[VSTOP] = _POSIX_VDISABLE;
1637 #endif /* VSTOP */
1638 #ifdef SET_LINE_DISCIPLINE
1639   /* Need to explicitly request TERMIODISC line discipline or
1640      Ultrix's termios does not work correctly.  */
1641   tty.main.c_line = SET_LINE_DISCIPLINE;
1642 #endif
1643
1644 #ifdef AIX
1645 #ifndef IBMR2AIX
1646   /* AIX enhanced edit loses NULs, so disable it. */
1647   tty.main.c_line = 0;
1648   tty.main.c_iflag &= ~ASCEDIT;
1649 #else
1650   tty.main.c_cc[VSTRT] = 255;
1651   tty.main.c_cc[VSTOP] = 255;
1652   tty.main.c_cc[VSUSP] = 255;
1653   tty.main.c_cc[VDSUSP] = 255;
1654 #endif /* IBMR2AIX */
1655   /* Also, PTY overloads NUL and BREAK.
1656      don't ignore break, but don't signal either, so it looks like NUL.
1657      This really serves a purpose only if running in an XTERM window
1658      or via TELNET or the like, but does no harm elsewhere.  */
1659   tty.main.c_iflag &= ~IGNBRK;
1660   tty.main.c_iflag &= ~BRKINT;
1661 #endif /* AIX */
1662 #else /* if not HAVE_TERMIO */
1663 #if !defined (WINDOWSNT)
1664   con->tty_erase_char = make_char (tty.main.sg_erase);
1665   tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1666   if (TTY_FLAGS (con).meta_key)
1667     tty.main.sg_flags |= ANYP;
1668   /* #### should we be using RAW mode here? */
1669   tty.main.sg_flags |= /* interrupt_input ? RAW : */ CBREAK;
1670 #endif /* not WINDOWSNT */
1671 #endif /* not HAVE_TERMIO */
1672
1673   /* If going to use CBREAK mode, we must request C-g to interrupt
1674      and turn off start and stop chars, etc.  If not going to use
1675      CBREAK mode, do this anyway so as to turn off local flow
1676      control for user coming over network on 4.2; in this case,
1677      only t_stopc and t_startc really matter.  */
1678 #ifndef HAVE_TERMIO
1679 #ifdef HAVE_TCHARS
1680   /* Note: if not using CBREAK mode, it makes no difference how we
1681      set this */
1682   tty.tchars = new_tchars;
1683   tty.tchars.t_intrc = CONSOLE_QUIT_CHAR (con);
1684   if (TTY_FLAGS (con).flow_control)
1685     {
1686       tty.tchars.t_startc = '\021';
1687       tty.tchars.t_stopc = '\023';
1688     }
1689
1690   tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH |
1691     CONSOLE_TTY_DATA (con)->old_tty.lmode;
1692
1693 #if defined (ultrix) || defined (__bsdi__)
1694   /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1695      anything, and leaving it in breaks the meta key.  Go figure.  */
1696   /* Turning off ONLCR is enough under BSD/386.  Leave the general
1697      output post-processing flag alone since for some reason it
1698      doesn't get reset after XEmacs goes away. */
1699   tty.lmode &= ~LLITOUT;
1700 #endif
1701
1702 #endif /* HAVE_TCHARS */
1703 #endif /* not HAVE_TERMIO */
1704
1705 #ifdef HAVE_LTCHARS
1706   tty.ltchars = new_ltchars;
1707 #endif /* HAVE_LTCHARS */
1708
1709   emacs_set_tty (input_fd, &tty, 0);
1710
1711   /* This code added to insure that, if flow-control is not to be used,
1712      we have an unlocked terminal at the start. */
1713
1714 #ifdef TCXONC
1715   if (!TTY_FLAGS (con).flow_control) ioctl (input_fd, TCXONC, 1);
1716 #endif
1717 #ifdef TIOCSTART
1718   if (!TTY_FLAGS (con).flow_control) ioctl (input_fd, TIOCSTART, 0);
1719 #endif
1720
1721 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1722 #ifdef TCOON
1723   if (!TTY_FLAGS (con).flow_control) tcflow (input_fd, TCOON);
1724 #endif
1725 #endif
1726 #ifdef AIXHFT
1727   hft_init (con);
1728 #ifdef IBMR2AIX
1729   {
1730     /* IBM's HFT device usually thinks a ^J should be LF/CR.
1731        We need it to be only LF.  This is the way that is
1732        done. */
1733     struct termio tty;
1734
1735     if (ioctl (output_fd, HFTGETID, &tty) != -1)
1736       write (output_fd, "\033[20l", 5);
1737   }
1738 #endif
1739 #endif
1740
1741 #if 0 /* We do our own buffering with lstreams. */
1742 #ifdef _IOFBF
1743   /* This symbol is defined on recent USG systems.
1744      Someone says without this call USG won't really buffer the file
1745      even with a call to setbuf. */
1746   setvbuf (CONSOLE_TTY_DATA (con)->outfd, (char *) _sobuf, _IOFBF, sizeof _sobuf);
1747 #else
1748   setbuf (CONSOLE_TTY_DATA (con)->outfd, (char *) _sobuf);
1749 #endif
1750 #endif
1751   set_tty_modes (con);
1752 }
1753
1754 #endif /* HAVE_TTY */
1755
1756 void
1757 init_one_device (struct device *d)
1758 {
1759 #ifdef HAVE_TTY
1760   if (DEVICE_TTY_P (d))
1761     tty_init_sys_modes_on_device (d);
1762 #endif
1763 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
1764   if (!DEVICE_STREAM_P (d))
1765     {
1766       init_sigio_on_device (d);
1767       request_sigio_on_device (d);
1768     }
1769 #endif
1770 }
1771
1772 void
1773 init_one_console (struct console *con)
1774 {
1775   Lisp_Object devcons;
1776
1777   CONSOLE_DEVICE_LOOP (devcons, con)
1778     {
1779       struct device *d = XDEVICE (XCAR (devcons));
1780
1781       init_one_device (d);
1782     }
1783 }
1784
1785 void
1786 reinit_initial_console (void)
1787 {
1788   munge_process_groups ();
1789   if (CONSOLEP (Vcontrolling_terminal) &&
1790       CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)))
1791     init_one_console (XCONSOLE (Vcontrolling_terminal));
1792 }
1793
1794 \f
1795 /* ------------------------------------------------------ */
1796 /*                   Other TTY functions                  */
1797 /* ------------------------------------------------------ */
1798
1799 #ifdef HAVE_TTY
1800
1801 #if 0 /* not currently used */
1802
1803 /* Return nonzero if safe to use tabs in output.
1804    At the time this is called, init_sys_modes has not been done yet.  */
1805
1806 int
1807 tabs_safe_p (struct device *d)
1808 {
1809 #ifdef HAVE_TTY
1810   if (DEVICE_TTY_P (d))
1811     {
1812       struct emacs_tty tty;
1813
1814       emacs_get_tty (DEVICE_INFD (d), &tty);
1815       return EMACS_TTY_TABS_OK (&tty);
1816     }
1817 #endif
1818   return 1;
1819 }
1820
1821 #endif /* 0 */
1822
1823 /* Get terminal size from system.
1824    Store number of lines into *heightp and width into *widthp.
1825    If zero or a negative number is stored, the value is not valid.  */
1826
1827 void
1828 get_tty_device_size (struct device *d, int *widthp, int *heightp)
1829 {
1830   int input_fd = DEVICE_INFD (d);
1831
1832   assert (DEVICE_TTY_P (d));
1833
1834 #ifdef TIOCGWINSZ
1835   {
1836     /* BSD-style.  */
1837     struct winsize size;
1838
1839     if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
1840       *widthp = *heightp = 0;
1841     else
1842       {
1843         *widthp = size.ws_col;
1844         *heightp = size.ws_row;
1845       }
1846   }
1847 #elif defined TIOCGSIZE
1848   {
1849     /* SunOS - style.  */
1850     struct ttysize size;
1851
1852     if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1853       *widthp = *heightp = 0;
1854     else
1855       {
1856         *widthp = size.ts_cols;
1857         *heightp = size.ts_lines;
1858       }
1859   }
1860 #else /* system doesn't know size */
1861
1862   *widthp = 0;
1863   *heightp = 0;
1864
1865 #endif /* not !TIOCGWINSZ */
1866 }
1867
1868 #endif /* HAVE_TTY */
1869
1870 \f
1871 /* ------------------------------------------------------ */
1872 /*                   Is device 8 bit ?                    */
1873 /* ------------------------------------------------------ */
1874
1875 #ifdef HAVE_TTY
1876
1877 int
1878 eight_bit_tty (struct device *d)
1879 {
1880   struct emacs_tty s;
1881   int input_fd;
1882   int eight_bit = 0;
1883
1884   assert (DEVICE_TTY_P (d));
1885   input_fd = DEVICE_INFD (d);
1886
1887   emacs_get_tty (input_fd, &s);
1888
1889 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1890   eight_bit = (s.main.c_cflag & CSIZE) == CS8;
1891 #else
1892   eight_bit = 0;        /* I don't know how to do it */
1893 #endif
1894   return eight_bit;
1895 }
1896
1897 #endif /* HAVE_TTY */
1898
1899 \f
1900 /* ------------------------------------------------------ */
1901 /*                   Resetting a device                   */
1902 /* ------------------------------------------------------ */
1903
1904 #ifdef HAVE_TTY
1905
1906 /* Prepare the terminal for exiting Emacs; move the cursor to the
1907    bottom of the frame, turn off interrupt-driven I/O, etc.  */
1908 static void
1909 tty_reset_sys_modes_on_device (struct device *d)
1910 {
1911   int input_fd, output_fd;
1912   struct console *con = XCONSOLE (DEVICE_CONSOLE (d));
1913
1914   input_fd = CONSOLE_TTY_DATA (con)->infd;
1915   output_fd = CONSOLE_TTY_DATA (con)->outfd;
1916
1917 #if defined (IBMR2AIX) && defined (AIXHFT)
1918   {
1919     /* HFT consoles normally use ^J as a LF/CR.  We forced it to
1920        do the LF only.  Now, we need to reset it. */
1921     struct termio tty;
1922
1923     if (ioctl (output_fd, HFTGETID, &tty) != -1)
1924       write (output_fd, "\033[20h", 5);
1925   }
1926 #endif
1927
1928   tty_redisplay_shutdown (con);
1929   /* reset_tty_modes() flushes the connection at its end. */
1930   reset_tty_modes (con);
1931
1932 #if defined (BSD)
1933   /* Avoid possible loss of output when changing terminal modes.  */
1934   fsync (output_fd);
1935 #endif
1936
1937   while (emacs_set_tty (input_fd, &CONSOLE_TTY_DATA (con)->old_tty, 0)
1938          < 0 && errno == EINTR)
1939     ;
1940
1941 #ifdef SET_LINE_DISCIPLINE
1942   /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1943      A different old line discipline is therefore not restored, yet.
1944      Restore the old line discipline by hand.  */
1945   ioctl (input_fd, TIOCSETD, &old_tty.main.c_line);
1946 #endif
1947
1948 #ifdef AIXHFT
1949   hft_reset (con);
1950 #endif
1951
1952 }
1953
1954 #endif /* HAVE_TTY */
1955
1956 void
1957 reset_one_device (struct device *d)
1958 {
1959 #ifdef HAVE_TTY
1960   if (DEVICE_TTY_P (d))
1961     tty_reset_sys_modes_on_device (d);
1962   else
1963 #endif
1964   if (DEVICE_STREAM_P (d))
1965     fflush (CONSOLE_STREAM_DATA (XCONSOLE (DEVICE_CONSOLE (d)))->out);
1966 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
1967   if (!DEVICE_STREAM_P (d))
1968     {
1969       unrequest_sigio_on_device (d);
1970       reset_sigio_on_device (d);
1971     }
1972 #endif
1973 }
1974
1975 void
1976 reset_one_console (struct console *con)
1977 {
1978   /* Note: this can be called during GC. */
1979   Lisp_Object devcons;
1980
1981   CONSOLE_DEVICE_LOOP (devcons, con)
1982     {
1983       struct device *d = XDEVICE (XCAR (devcons));
1984
1985       reset_one_device (d);
1986     }
1987 }
1988
1989 void
1990 reset_all_consoles (void)
1991 {
1992   /* Note: this can be called during GC. */
1993   Lisp_Object concons;
1994
1995   CONSOLE_LOOP (concons)
1996     {
1997       struct console *con = XCONSOLE (XCAR (concons));
1998
1999       reset_one_console (con);
2000     }
2001
2002   unmunge_process_groups ();
2003 }
2004
2005 void
2006 reset_initial_console (void)
2007 {
2008   if (CONSOLEP (Vcontrolling_terminal) &&
2009       CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)))
2010     reset_one_console (XCONSOLE (Vcontrolling_terminal));
2011   unmunge_process_groups ();
2012 }
2013
2014 \f
2015 /* ------------------------------------------------------ */
2016 /*                 extra TTY stuff under AIX              */
2017 /* ------------------------------------------------------ */
2018
2019 #ifdef AIXHFT
2020
2021 /* Called from init_sys_modes.  */
2022 static void
2023 hft_init (struct console *con)
2024 {
2025   int junk;
2026   int input_fd;
2027
2028   assert (CONSOLE_TTY_P (con));
2029   input_fd = CONSOLE_TTY_DATA (con)->infd;
2030
2031   /* If we're not on an HFT we shouldn't do any of this.  We determine
2032      if we are on an HFT by trying to get an HFT error code.  If this
2033      call fails, we're not on an HFT. */
2034 #ifdef IBMR2AIX
2035   if (ioctl (input_fd, HFQERROR, &junk) < 0)
2036     return;
2037 #else /* not IBMR2AIX */
2038   if (ioctl (input_fd, HFQEIO, 0) < 0)
2039     return;
2040 #endif /* not IBMR2AIX */
2041
2042   /* On AIX the default hft keyboard mapping uses backspace rather than delete
2043      as the rubout key's ASCII code.  Here this is changed.  The bug is that
2044      there's no way to determine the old mapping, so in reset_one_console
2045      we need to assume that the normal map had been present.  Of course, this
2046      code also doesn't help if on a terminal emulator which doesn't understand
2047      HFT VTD's. */
2048   {
2049     struct hfbuf buf;
2050     struct hfkeymap keymap;
2051
2052     buf.hf_bufp = (char *)&keymap;
2053     buf.hf_buflen = sizeof (keymap);
2054     keymap.hf_nkeys = 2;
2055     keymap.hfkey[0].hf_kpos = 15;
2056     keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
2057 #ifdef IBMR2AIX
2058     keymap.hfkey[0].hf_keyidh = '<';
2059 #else /* not IBMR2AIX */
2060     keymap.hfkey[0].hf_page = '<';
2061 #endif /* not IBMR2AIX */
2062     keymap.hfkey[0].hf_char = 127;
2063     keymap.hfkey[1].hf_kpos = 15;
2064     keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
2065 #ifdef IBMR2AIX
2066     keymap.hfkey[1].hf_keyidh = '<';
2067 #else /* not IBMR2AIX */
2068     keymap.hfkey[1].hf_page = '<';
2069 #endif /* not IBMR2AIX */
2070     keymap.hfkey[1].hf_char = 127;
2071     hftctl (input_fd, HFSKBD, &buf);
2072   }
2073   /* #### Should probably set a console TTY flag here. */
2074 #if 0
2075   /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
2076      at times. */
2077   line_ins_del_ok = char_ins_del_ok = 0;
2078 #endif /* 0 */
2079 }
2080
2081 /* Reset the rubout key to backspace. */
2082
2083 static void
2084 hft_reset (struct console *con)
2085 {
2086   struct hfbuf buf;
2087   struct hfkeymap keymap;
2088   int junk;
2089   int input_fd;
2090
2091   assert (CONSOLE_TTY_P (con));
2092   input_fd = CONSOLE_TTY_DATA (con)->infd;
2093
2094 #ifdef IBMR2AIX
2095   if (ioctl (input_fd, HFQERROR, &junk) < 0)
2096     return;
2097 #else /* not IBMR2AIX */
2098   if (ioctl (input_fd, HFQEIO, 0) < 0)
2099     return;
2100 #endif /* not IBMR2AIX */
2101
2102   buf.hf_bufp = (char *)&keymap;
2103   buf.hf_buflen = sizeof (keymap);
2104   keymap.hf_nkeys = 2;
2105   keymap.hfkey[0].hf_kpos = 15;
2106   keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
2107 #ifdef IBMR2AIX
2108   keymap.hfkey[0].hf_keyidh = '<';
2109 #else /* not IBMR2AIX */
2110   keymap.hfkey[0].hf_page = '<';
2111 #endif /* not IBMR2AIX */
2112   keymap.hfkey[0].hf_char = 8;
2113   keymap.hfkey[1].hf_kpos = 15;
2114   keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
2115 #ifdef IBMR2AIX
2116   keymap.hfkey[1].hf_keyidh = '<';
2117 #else /* not IBMR2AIX */
2118   keymap.hfkey[1].hf_page = '<';
2119 #endif /* not IBMR2AIX */
2120   keymap.hfkey[1].hf_char = 8;
2121   hftctl (input_fd, HFSKBD, &buf);
2122 }
2123
2124 #endif /* AIXHFT */
2125
2126 \f
2127 /************************************************************************/
2128 /*                    limits of text/data segments                      */
2129 /************************************************************************/
2130
2131 #if !defined(CANNOT_DUMP) && !defined(PDUMP)
2132 #define NEED_STARTS
2133 #endif
2134
2135 #ifndef SYSTEM_MALLOC
2136 #ifndef NEED_STARTS
2137 #define NEED_STARTS
2138 #endif
2139 #endif
2140
2141 #ifdef NEED_STARTS
2142 /* Some systems that cannot dump also cannot implement these.  */
2143
2144 /*
2145  *      Return the address of the start of the text segment prior to
2146  *      doing an unexec.  After unexec the return value is undefined.
2147  *      See crt0.c for further explanation and _start.
2148  *
2149  */
2150
2151 #if !defined(HAVE_TEXT_START) && !defined(PDUMP)
2152
2153 #ifdef __cplusplus
2154   extern "C" int _start (void);
2155 #else
2156   extern int _start (void);
2157 #endif
2158
2159 char *
2160 start_of_text (void)
2161 {
2162 #ifdef TEXT_START
2163   return ((char *) TEXT_START);
2164 #else
2165 #ifdef GOULD
2166   extern csrt ();
2167   return ((char *) csrt);
2168 #else /* not GOULD */
2169   return ((char *) _start);
2170 #endif /* GOULD */
2171 #endif /* TEXT_START */
2172 }
2173 #endif /* !defined(HAVE_TEXT_START) && !defined(PDUMP) */
2174
2175 /*
2176  *      Return the address of the start of the data segment prior to
2177  *      doing an unexec.  After unexec the return value is undefined.
2178  *      See crt0.c for further information and definition of data_start.
2179  *
2180  *      Apparently, on BSD systems this is etext at startup.  On
2181  *      USG systems (swapping) this is highly mmu dependent and
2182  *      is also dependent on whether or not the program is running
2183  *      with shared text.  Generally there is a (possibly large)
2184  *      gap between end of text and start of data with shared text.
2185  *
2186  *      On Uniplus+ systems with shared text, data starts at a
2187  *      fixed address.  Each port (from a given oem) is generally
2188  *      different, and the specific value of the start of data can
2189  *      be obtained via the UniPlus+ specific "uvar" system call,
2190  *      however the method outlined in crt0.c seems to be more portable.
2191  *
2192  *      Probably what will have to happen when a USG unexec is available,
2193  *      at least on UniPlus, is temacs will have to be made unshared so
2194  *      that text and data are contiguous.  Then once loadup is complete,
2195  *      unexec will produce a shared executable where the data can be
2196  *      at the normal shared text boundary and the startofdata variable
2197  *      will be patched by unexec to the correct value.
2198  *
2199  */
2200
2201 #if defined(ORDINARY_LINK) && !defined(__MINGW32__)
2202 extern char **environ;
2203 #endif
2204
2205 void *
2206 start_of_data (void)
2207 {
2208 #ifdef DATA_START
2209   return ((char *) DATA_START);
2210 #else
2211 #ifdef ORDINARY_LINK
2212   /*
2213    * This is a hack.  Since we're not linking crt0.c or pre_crt0.c,
2214    * data_start isn't defined.  We take the address of environ, which
2215    * is known to live at or near the start of the system crt0.c, and
2216    * we don't sweat the handful of bytes that might lose.
2217    */
2218 #if defined (HEAP_IN_DATA) && !defined(PDUMP)
2219   extern char* static_heap_base;
2220   if (!initialized)
2221     return static_heap_base;
2222 #endif
2223   return((char *) &environ);
2224 #else
2225   extern int data_start;
2226   return ((char *) &data_start);
2227 #endif /* ORDINARY_LINK */
2228 #endif /* DATA_START */
2229 }
2230 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2231
2232 #if !defined(CANNOT_DUMP) && !defined(PDUMP)
2233 /* Some systems that cannot dump also cannot implement these.  */
2234
2235 /*
2236  *      Return the address of the end of the text segment prior to
2237  *      doing an unexec.  After unexec the return value is undefined.
2238  */
2239
2240 char *
2241 end_of_text (void)
2242 {
2243 #ifdef TEXT_END
2244   return ((char *) TEXT_END);
2245 #else
2246   extern int etext;
2247   return ((char *) &etext);
2248 #endif
2249 }
2250
2251 /*
2252  *      Return the address of the end of the data segment prior to
2253  *      doing an unexec.  After unexec the return value is undefined.
2254  */
2255
2256 char *
2257 end_of_data (void)
2258 {
2259 #ifdef DATA_END
2260   return ((char *) DATA_END);
2261 #else
2262   extern int edata;
2263   return ((char *) &edata);
2264 #endif
2265 }
2266
2267 #endif /* !defined(CANNOT_DUMP) && !defined(PDUMP) */
2268
2269 \f
2270 /************************************************************************/
2271 /*                          get the system name                         */
2272 /************************************************************************/
2273
2274 /* init_system_name sets up the string for the Lisp function
2275    system-name to return. */
2276
2277 extern Lisp_Object Vsystem_name;
2278
2279 #ifdef HAVE_SOCKETS
2280 # include <sys/socket.h>
2281 # include <netdb.h>
2282 #endif /* HAVE_SOCKETS */
2283
2284 void
2285 init_system_name (void)
2286 {
2287 #if defined (WINDOWSNT)
2288   char hostname [MAX_COMPUTERNAME_LENGTH + 1];
2289   size_t size = sizeof (hostname);
2290   GetComputerName (hostname, &size);
2291   Vsystem_name = build_string (hostname);
2292 #elif !defined (HAVE_GETHOSTNAME)
2293   struct utsname uts;
2294   uname (&uts);
2295   Vsystem_name = build_string (uts.nodename);
2296 #else /* HAVE_GETHOSTNAME */
2297   unsigned int hostname_size = 256;
2298   char *hostname = (char *) alloca (hostname_size);
2299
2300   /* Try to get the host name; if the buffer is too short, try
2301      again.  Apparently, the only indication gethostname gives of
2302      whether the buffer was large enough is the presence or absence
2303      of a '\0' in the string.  Eech.  */
2304   for (;;)
2305     {
2306       gethostname (hostname, hostname_size - 1);
2307       hostname[hostname_size - 1] = '\0';
2308
2309       /* Was the buffer large enough for the '\0'?  */
2310       if (strlen (hostname) < (size_t) (hostname_size - 1))
2311         break;
2312
2313       hostname_size <<= 1;
2314       hostname = (char *) alloca (hostname_size);
2315     }
2316 # if defined( HAVE_SOCKETS) && !defined(BROKEN_CYGWIN)
2317   /* Turn the hostname into the official, fully-qualified hostname.
2318      Don't do this if we're going to dump; this can confuse system
2319      libraries on some machines and make the dumped emacs core dump. */
2320 #  ifndef CANNOT_DUMP
2321   if (initialized)
2322 #  endif /* not CANNOT_DUMP */
2323     if (!strchr (hostname, '.'))
2324       {
2325 #  if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETNAMEINFO))
2326         struct hostent *hp = NULL;
2327         int count;
2328 #   ifdef TRY_AGAIN
2329         for (count = 0; count < 10; count++)
2330           {
2331             h_errno = 0;
2332 #   endif
2333             /* Some systems can't handle SIGALARM/SIGIO in gethostbyname(). */
2334             stop_interrupts ();
2335             hp = gethostbyname (hostname);
2336             start_interrupts ();
2337 #   ifdef TRY_AGAIN
2338             if (! (hp == 0 && h_errno == TRY_AGAIN))
2339               break;
2340             Fsleep_for (make_int (1));
2341           }
2342 #   endif
2343         if (hp)
2344           {
2345             const char *fqdn = (const char *) hp->h_name;
2346
2347             if (!strchr (fqdn, '.'))
2348               {
2349                 /* We still don't have a fully qualified domain name.
2350                    Try to find one in the list of alternate names */
2351                 char **alias = hp->h_aliases;
2352                 while (*alias && !strchr (*alias, '.'))
2353                   alias++;
2354                 if (*alias)
2355                   fqdn = *alias;
2356               }
2357             hostname = (char *) alloca (strlen (fqdn) + 1);
2358             strcpy (hostname, fqdn);
2359           }
2360 #  else /* !(HAVE_GETADDRINFO && HAVE_GETNAMEINFO) */
2361         struct addrinfo hints, *res;
2362
2363         xzero (hints);
2364         hints.ai_flags = AI_CANONNAME;
2365         hints.ai_family = AF_UNSPEC;
2366         hints.ai_socktype = SOCK_STREAM;
2367         hints.ai_protocol = 0;
2368         if (!getaddrinfo (hostname, NULL, &hints, &res))
2369           {
2370             hostname = (char *) alloca (strlen (res->ai_canonname) + 1);
2371             strcpy (hostname, res->ai_canonname);
2372
2373             freeaddrinfo (res);
2374           }
2375 #  endif  /* !(HAVE_GETADDRINFO && HAVE_GETNAMEINFO) */
2376       }
2377 # endif /* HAVE_SOCKETS */
2378   Vsystem_name = build_string (hostname);
2379 #endif /* HAVE_GETHOSTNAME  */
2380   {
2381     Bufbyte *p;
2382     Bytecount i;
2383
2384     for (i = 0, p = XSTRING_DATA (Vsystem_name);
2385          i < XSTRING_LENGTH (Vsystem_name);
2386          i++, p++)
2387       {
2388         if (*p == ' ' || *p == '\t')
2389           *p = '-';
2390       }
2391   }
2392 }
2393
2394 \f
2395 /************************************************************************/
2396 /*                        Emulation of select()                         */
2397 /************************************************************************/
2398
2399 #ifndef HAVE_SELECT
2400
2401 ERROR: XEmacs requires a working select().
2402
2403 #endif /* not HAVE_SELECT */
2404
2405 \f
2406 /************************************************************************/
2407 /*                      Emulation of signal stuff                       */
2408 /************************************************************************/
2409
2410 /* BSD 4.1 crap deleted.  4.2 was released in 1983, for God's sake!  I
2411    can't imagine that anyone is actually running that OS any more.
2412    You can't use X under it (I think) because there's no select().
2413    Anyway, the signal stuff has all been changed.  If someone wants to
2414    get this stuff working again, look in the FSF Emacs sources. */
2415
2416 /* POSIX signals support - DJB */
2417
2418 #ifdef HAVE_SIGPROCMASK
2419
2420 /* #### Is there any reason this is static global rather than local? */
2421 static struct sigaction new_action, old_action;
2422
2423 signal_handler_t
2424 sys_do_signal (int signal_number, signal_handler_t action)
2425 {
2426 #if 0
2427
2428   /* XEmacs works better if system calls are *not* restarted.
2429      This allows C-g to interrupt reads and writes, on most systems.
2430
2431      #### Another possibility is to just longjmp() out of the signal
2432      handler.  According to W.R. Stevens, this should be OK on all
2433      systems.  However, I don't want to deal with the potential
2434      evil ramifications of this at this point. */
2435
2436 #ifdef DGUX
2437   /* This gets us restartable system calls for efficiency.
2438      The "else" code will work as well. */
2439   return (berk_signal (signal_number, action));
2440 #else
2441   sigemptyset (&new_action.sa_mask);
2442   new_action.sa_handler = action;
2443 #if defined (SA_RESTART)
2444   /* Emacs mostly works better with restartable system services. If this
2445    * flag exists, we probably want to turn it on here.
2446    */
2447   new_action.sa_flags = SA_RESTART;
2448 #else
2449   new_action.sa_flags = 0;
2450 #endif
2451   sigaction (signal_number, &new_action, &old_action);
2452   return (old_action.sa_handler);
2453 #endif /* DGUX */
2454
2455 #else /* not 0 */
2456
2457   sigemptyset (&new_action.sa_mask);
2458   new_action.sa_handler = action;
2459 #if defined (SA_INTERRUPT) /* don't restart system calls, under SunOS */
2460   new_action.sa_flags = SA_INTERRUPT;
2461 #else
2462   new_action.sa_flags = 0;
2463 #endif
2464   sigaction (signal_number, &new_action, &old_action);
2465   return (signal_handler_t) (old_action.sa_handler);
2466
2467 #endif /* not 0 */
2468 }
2469
2470 #elif defined (HAVE_SIGBLOCK)
2471
2472 /* We use sigvec() rather than signal() if we have it, because
2473    it lets us specify interruptible system calls. */
2474 signal_handler_t
2475 sys_do_signal (int signal_number, signal_handler_t action)
2476 {
2477   struct sigvec vec, ovec;
2478
2479   vec.sv_handler = action;
2480   vec.sv_mask = 0;
2481 #ifdef SV_INTERRUPT /* don't restart system calls */
2482   vec.sv_flags = SV_INTERRUPT;
2483 #else
2484   vec.sv_flags = 0;
2485 #endif
2486
2487   sigvec (signal_number, &vec, &ovec);
2488
2489   return (ovec.sv_handler);
2490 }
2491
2492 #endif /* HAVE_SIGBLOCK (HAVE_SIGPROCMASK) */
2493
2494 \f
2495 /************************************************************************/
2496 /*           Emulation of strerror() and errno support                  */
2497 /************************************************************************/
2498
2499 #ifndef HAVE_STRERROR
2500
2501 #if !defined(NeXT) && !defined(__alpha) && !defined(MACH) && !defined(LINUX) && !defined(IRIX) && !defined(__NetBSD__)
2502 /* Linux added here by Raymond L. Toy <toy@alydar.crd.ge.com> for XEmacs. */
2503 /* Irix added here by gparker@sni-usa.com for XEmacs. */
2504 /* NetBSD added here by James R Grinter <jrg@doc.ic.ac.uk> for XEmacs */
2505 extern const char *sys_errlist[];
2506 extern int sys_nerr;
2507 #endif
2508
2509 #ifdef __NetBSD__
2510 extern char *sys_errlist[];
2511 extern int sys_nerr;
2512 #endif
2513
2514
2515 const char *
2516 strerror (int errnum)
2517 {
2518   if (errnum >= 0 && errnum < sys_nerr)
2519     return sys_errlist[errnum];
2520   return ((const char *) GETTEXT ("Unknown error"));
2521 }
2522
2523 #endif /* ! HAVE_STRERROR */
2524
2525 #ifdef WINDOWSNT
2526
2527 struct errentry {
2528   unsigned long oscode;  /* Win32 error */
2529   int errnocode;         /* unix errno */
2530 };
2531
2532 static struct errentry errtable[] = {
2533   {  ERROR_INVALID_FUNCTION,       EINVAL    },  /* 1 */
2534   {  ERROR_FILE_NOT_FOUND,         ENOENT    },  /* 2 */
2535   {  ERROR_PATH_NOT_FOUND,         ENOENT    },  /* 3 */
2536   {  ERROR_TOO_MANY_OPEN_FILES,    EMFILE    },  /* 4 */
2537   {  ERROR_ACCESS_DENIED,          EACCES    },  /* 5 */
2538   {  ERROR_INVALID_HANDLE,         EBADF     },  /* 6 */
2539   {  ERROR_ARENA_TRASHED,          ENOMEM    },  /* 7 */
2540   {  ERROR_NOT_ENOUGH_MEMORY,      ENOMEM    },  /* 8 */
2541   {  ERROR_INVALID_BLOCK,          ENOMEM    },  /* 9 */
2542   {  ERROR_BAD_ENVIRONMENT,        E2BIG     },  /* 10 */
2543   {  ERROR_BAD_FORMAT,             ENOEXEC   },  /* 11 */
2544   {  ERROR_INVALID_ACCESS,         EINVAL    },  /* 12 */
2545   {  ERROR_INVALID_DATA,           EINVAL    },  /* 13 */
2546   {  ERROR_INVALID_DRIVE,          ENOENT    },  /* 15 */
2547   {  ERROR_CURRENT_DIRECTORY,      EACCES    },  /* 16 */
2548   {  ERROR_NOT_SAME_DEVICE,        EXDEV     },  /* 17 */
2549   {  ERROR_NO_MORE_FILES,          ENOENT    },  /* 18 */
2550   {  ERROR_LOCK_VIOLATION,         EACCES    },  /* 33 */
2551   {  ERROR_BAD_NETPATH,            ENOENT    },  /* 53 */
2552   {  ERROR_NETWORK_ACCESS_DENIED,  EACCES    },  /* 65 */
2553   {  ERROR_BAD_NET_NAME,           ENOENT    },  /* 67 */
2554   {  ERROR_FILE_EXISTS,            EEXIST    },  /* 80 */
2555   {  ERROR_CANNOT_MAKE,            EACCES    },  /* 82 */
2556   {  ERROR_FAIL_I24,               EACCES    },  /* 83 */
2557   {  ERROR_INVALID_PARAMETER,      EINVAL    },  /* 87 */
2558   {  ERROR_NO_PROC_SLOTS,          EAGAIN    },  /* 89 */
2559   {  ERROR_DRIVE_LOCKED,           EACCES    },  /* 108 */
2560   {  ERROR_BROKEN_PIPE,            EPIPE     },  /* 109 */
2561   {  ERROR_DISK_FULL,              ENOSPC    },  /* 112 */
2562   {  ERROR_INVALID_TARGET_HANDLE,  EBADF     },  /* 114 */
2563   {  ERROR_INVALID_HANDLE,         EINVAL    },  /* 124 */
2564   {  ERROR_WAIT_NO_CHILDREN,       ECHILD    },  /* 128 */
2565   {  ERROR_CHILD_NOT_COMPLETE,     ECHILD    },  /* 129 */
2566   {  ERROR_DIRECT_ACCESS_HANDLE,   EBADF     },  /* 130 */
2567   {  ERROR_NEGATIVE_SEEK,          EINVAL    },  /* 131 */
2568   {  ERROR_SEEK_ON_DEVICE,         EACCES    },  /* 132 */
2569   {  ERROR_DIR_NOT_EMPTY,          ENOTEMPTY },  /* 145 */
2570   {  ERROR_NOT_LOCKED,             EACCES    },  /* 158 */
2571   {  ERROR_BAD_PATHNAME,           ENOENT    },  /* 161 */
2572   {  ERROR_MAX_THRDS_REACHED,      EAGAIN    },  /* 164 */
2573   {  ERROR_LOCK_FAILED,            EACCES    },  /* 167 */
2574   {  ERROR_ALREADY_EXISTS,         EEXIST    },  /* 183 */
2575   {  ERROR_FILENAME_EXCED_RANGE,   ENOENT    },  /* 206 */
2576   {  ERROR_NESTING_NOT_ALLOWED,    EAGAIN    },  /* 215 */
2577   {  ERROR_NOT_ENOUGH_QUOTA,       ENOMEM    }    /* 1816 */
2578 };
2579
2580 /* The following two constants must be the minimum and maximum
2581    values in the (contiguous) range of Exec Failure errors. */
2582 #define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
2583 #define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
2584
2585 /* These are the low and high value in the range of errors that are
2586    access violations */
2587 #define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
2588 #define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
2589
2590 void
2591 mswindows_set_errno (unsigned long win32_error)
2592 {
2593   int i;
2594
2595   /* check the table for the OS error code */
2596   for (i = 0; i < countof (errtable); ++i)
2597     {
2598       if (win32_error == errtable[i].oscode)
2599         {
2600           errno = errtable[i].errnocode;
2601           return;
2602         }
2603     }
2604
2605   /* The error code wasn't in the table.  We check for a range of
2606    * EACCES errors or exec failure errors (ENOEXEC).  Otherwise EINVAL is
2607    * returned. */
2608   if (win32_error >= MIN_EACCES_RANGE && win32_error <= MAX_EACCES_RANGE)
2609     errno = EACCES;
2610   else if (win32_error >= MIN_EXEC_ERROR && win32_error <= MAX_EXEC_ERROR)
2611     errno = ENOEXEC;
2612   else
2613     errno = EINVAL;
2614 }
2615
2616 void
2617 mswindows_set_last_errno (void)
2618 {
2619   mswindows_set_errno (GetLastError ());
2620 }
2621
2622 #endif /* WINDOWSNT */
2623
2624 \f
2625 /************************************************************************/
2626 /*                    Encapsulations of system calls                    */
2627 /************************************************************************/
2628
2629 #define PATHNAME_CONVERT_OUT(path) \
2630   TO_EXTERNAL_FORMAT (C_STRING, (path), C_STRING_ALLOCA, (path), Qfile_name);
2631
2632 /***************** low-level calls ****************/
2633
2634 /*
2635  *      On USG systems the system calls are INTERRUPTIBLE by signals
2636  *      that the user program has elected to catch.  Thus the system call
2637  *      must be retried in these cases.  To handle this without massive
2638  *      changes in the source code, we remap the standard system call names
2639  *      to names for our own functions in sysdep.c that do the system call
2640  *      with retries.  Actually, for portability reasons, it is good
2641  *      programming practice, as this example shows, to limit all actual
2642  *      system calls to a single occurrence in the source.  Sure, this
2643  *      adds an extra level of function call overhead but it is almost
2644  *      always negligible.   Fred Fish, Unisoft Systems Inc.
2645  */
2646
2647 /* Ben sez: read Dick Gabriel's essay about the Worse Is Better
2648    approach to programming and its connection to the silly
2649    interruptible-system-call business.  To find it, look on
2650    Jamie's home page (http://www.jwz.org/worse-is-better.html). */
2651
2652 #ifdef ENCAPSULATE_OPEN
2653 int
2654 sys_open (const char *path, int oflag, ...)
2655 {
2656   int mode;
2657   va_list ap;
2658
2659   va_start (ap, oflag);
2660   mode = va_arg (ap, int);
2661   va_end (ap);
2662
2663   PATHNAME_CONVERT_OUT (path);
2664
2665 #ifdef WINDOWSNT
2666   /* Make all handles non-inheritable */
2667   oflag |= _O_NOINHERIT;
2668 #endif
2669
2670 #ifdef INTERRUPTIBLE_OPEN
2671   {
2672     int rtnval;
2673     while ((rtnval = open (path, oflag, mode)) == -1
2674            && (errno == EINTR))
2675       DO_NOTHING;
2676     return rtnval;
2677   }
2678 #else
2679   return open (path, oflag, mode);
2680 #endif
2681 }
2682 #endif /* ENCAPSULATE_OPEN */
2683
2684 /* Like sys_open, only when open() is interrupted by EINTR, check for
2685    QUIT.  This allows the callers of this function to be interrupted
2686    with C-g when, say, reading from named pipes.  However, this should
2687    be used with caution, as it can GC.
2688
2689    This function will not function as expected on systems where open()
2690    is not interrupted by C-g.  However, the worst that can happen is
2691    the fallback to simple open().  */
2692 int
2693 interruptible_open (const char *path, int oflag, int mode)
2694 {
2695   /* This function can GC */
2696   size_t len = strlen (path);
2697   char *nonreloc = (char *) alloca (len + 1);
2698
2699   /* Must copy PATH, because it might be the data of a Lisp_String,
2700      which could be relocated by GC when checking for QUIT.  */
2701   memcpy (nonreloc, path, len + 1);
2702
2703   PATHNAME_CONVERT_OUT (nonreloc);
2704
2705 #ifdef WINDOWSNT
2706   /* Make all handles non-inheritable */
2707   oflag |= _O_NOINHERIT;
2708 #endif
2709
2710   for (;;)
2711     {
2712       int rtnval = open (nonreloc, oflag, mode);
2713       if (!(rtnval == -1 && errno == EINTR))
2714         return rtnval;
2715       /* open() was interrupted.  Was QUIT responsible?  */
2716       QUIT;
2717     }
2718 }
2719
2720 #ifdef ENCAPSULATE_CLOSE
2721 int
2722 sys_close (int filedes)
2723 {
2724 #ifdef INTERRUPTIBLE_CLOSE
2725   int did_retry = 0;
2726   REGISTER int rtnval;
2727
2728   while ((rtnval = close (filedes)) == -1
2729          && (errno == EINTR))
2730     did_retry = 1;
2731
2732   /* If close is interrupted SunOS 4.1 may or may not have closed the
2733      file descriptor.  If it did the second close will fail with
2734      errno = EBADF.  That means we have succeeded.  */
2735   if (rtnval == -1 && did_retry && errno == EBADF)
2736     return 0;
2737
2738   return rtnval;
2739 #else
2740   return close (filedes);
2741 #endif
2742 }
2743 #endif /* ENCAPSULATE_CLOSE */
2744
2745 ssize_t
2746 sys_read_1 (int fildes, void *buf, size_t nbyte, int allow_quit)
2747 {
2748   ssize_t rtnval;
2749
2750   /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */
2751   while ((rtnval = read (fildes, buf, nbyte)) == -1
2752          && (errno == EINTR))
2753     {
2754       if (allow_quit)
2755         REALLY_QUIT;
2756     }
2757   return rtnval;
2758 }
2759
2760 #ifdef ENCAPSULATE_READ
2761 ssize_t
2762 sys_read (int fildes, void *buf, size_t nbyte)
2763 {
2764   return sys_read_1 (fildes, buf, nbyte, 0);
2765 }
2766 #endif /* ENCAPSULATE_READ */
2767
2768 ssize_t
2769 sys_write_1 (int fildes, const void *buf, size_t nbyte, int allow_quit)
2770 {
2771   ssize_t bytes_written = 0;
2772   const char *b = (const char *) buf;
2773
2774   /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */
2775   while (nbyte > 0)
2776     {
2777       ssize_t rtnval = write (fildes, b, nbyte);
2778
2779       if (allow_quit)
2780         REALLY_QUIT;
2781
2782       if (rtnval == -1)
2783         {
2784           if (errno == EINTR)
2785             continue;
2786           else
2787             return bytes_written ? bytes_written : -1;
2788         }
2789       b += rtnval;
2790       nbyte -= rtnval;
2791       bytes_written += rtnval;
2792     }
2793   return bytes_written;
2794 }
2795
2796 #ifdef ENCAPSULATE_WRITE
2797 ssize_t
2798 sys_write (int fildes, const void *buf, size_t nbyte)
2799 {
2800   return sys_write_1 (fildes, buf, nbyte, 0);
2801 }
2802 #endif /* ENCAPSULATE_WRITE */
2803
2804
2805 /**************** stdio calls ****************/
2806
2807 /* There is at least some evidence that the stdio calls are interruptible
2808    just like the normal system calls, at least on some systems.  In any
2809    case, it doesn't hurt to encapsulate them. */
2810
2811 /* #### Should also encapsulate fflush().
2812    #### Should conceivably encapsulate getchar() etc.  What a pain! */
2813
2814 #ifdef ENCAPSULATE_FOPEN
2815 FILE *
2816 sys_fopen (const char *path, const char *type)
2817 {
2818   PATHNAME_CONVERT_OUT (path);
2819 #if defined (WINDOWSNT)
2820   {
2821     int fd;
2822     int oflag;
2823     const char * type_save = type;
2824
2825     /* Force all file handles to be non-inheritable.  This is necessary to
2826        ensure child processes don't unwittingly inherit handles that might
2827        prevent future file access. */
2828
2829     if (type[0] == 'r')
2830       oflag = O_RDONLY;
2831     else if (type[0] == 'w' || type[0] == 'a')
2832       oflag = O_WRONLY | O_CREAT | O_TRUNC;
2833     else
2834       return 0;
2835
2836     /* Only do simplistic option parsing. */
2837     while (*++type)
2838       if (type[0] == '+')
2839         {
2840           oflag &= ~(O_RDONLY | O_WRONLY);
2841           oflag |= O_RDWR;
2842         }
2843       else if (type[0] == 'b')
2844         {
2845           oflag &= ~O_TEXT;
2846           oflag |= O_BINARY;
2847         }
2848       else if (type[0] == 't')
2849         {
2850           oflag &= ~O_BINARY;
2851           oflag |= O_TEXT;
2852         }
2853       else break;
2854
2855     fd = open (path, oflag | _O_NOINHERIT, 0644);
2856     if (fd < 0)
2857       return NULL;
2858
2859     return _fdopen (fd, type_save);
2860   }
2861 #elif defined (INTERRUPTIBLE_OPEN)
2862   {
2863     FILE *rtnval;
2864     while (!(rtnval = fopen (path, type)) && (errno == EINTR))
2865       DO_NOTHING;
2866     return rtnval;
2867   }
2868 #else
2869   return fopen (path, type);
2870 #endif
2871 }
2872 #endif /* ENCAPSULATE_FOPEN */
2873
2874
2875 #ifdef ENCAPSULATE_FCLOSE
2876 int
2877 sys_fclose (FILE *stream)
2878 {
2879 #ifdef INTERRUPTIBLE_CLOSE
2880   int rtnval;
2881
2882   while ((rtnval = fclose (stream)) == EOF
2883          && (errno == EINTR))
2884     ;
2885   return rtnval;
2886 #else
2887   return fclose (stream);
2888 #endif
2889 }
2890 #endif /* ENCAPSULATE_FCLOSE */
2891
2892
2893 #ifdef ENCAPSULATE_FREAD
2894 size_t
2895 sys_fread (void *ptr, size_t size, size_t nitem, FILE *stream)
2896 {
2897 #ifdef INTERRUPTIBLE_IO
2898   size_t rtnval;
2899   size_t items_read = 0;
2900   char *b = (char *) ptr;
2901
2902   while (nitem > 0)
2903     {
2904       rtnval = fread (b, size, nitem, stream);
2905       if (rtnval == 0)
2906         {
2907           if (ferror (stream) && errno == EINTR)
2908             continue;
2909           else
2910             return items_read;
2911         }
2912       b += size*rtnval;
2913       nitem -= rtnval;
2914       items_read += rtnval;
2915     }
2916   return (items_read);
2917 #else
2918   return fread (ptr, size, nitem, stream);
2919 #endif
2920 }
2921 #endif /* ENCAPSULATE_FREAD */
2922
2923
2924 #ifdef ENCAPSULATE_FWRITE
2925 size_t
2926 sys_fwrite (const void *ptr, size_t size, size_t nitem, FILE *stream)
2927 {
2928 #ifdef INTERRUPTIBLE_IO
2929   size_t rtnval;
2930   size_t items_written = 0;
2931   const char *b = (const char *) ptr;
2932
2933   while (nitem > 0)
2934     {
2935       rtnval = fwrite (b, size, nitem, stream);
2936       if (rtnval == 0)
2937         {
2938           if (ferror (stream) && errno == EINTR)
2939             continue;
2940           else
2941             return items_written;
2942         }
2943       b += size*rtnval;
2944       nitem -= rtnval;
2945       items_written += rtnval;
2946     }
2947   return (items_written);
2948 #else
2949   return fwrite (ptr, size, nitem, stream);
2950 #endif
2951 }
2952 #endif /* ENCAPSULATE_FWRITE */
2953
2954
2955 /********************* directory calls *******************/
2956
2957 #ifdef ENCAPSULATE_CHDIR
2958 int
2959 sys_chdir (const char *path)
2960 {
2961   PATHNAME_CONVERT_OUT (path);
2962   return chdir (path);
2963 }
2964 #endif /* ENCAPSULATE_CHDIR */
2965
2966
2967 #ifdef ENCAPSULATE_MKDIR
2968 int
2969 sys_mkdir (const char *path, mode_t mode)
2970 {
2971   PATHNAME_CONVERT_OUT (path);
2972 #ifdef WINDOWSNT
2973   return mkdir (path);
2974 #else
2975   return mkdir (path, mode);
2976 #endif
2977 }
2978 #endif /* ENCAPSULATE_MKDIR */
2979
2980
2981 #ifdef ENCAPSULATE_OPENDIR
2982 DIR *
2983 sys_opendir (const char *filename)
2984 {
2985   DIR *rtnval;
2986   PATHNAME_CONVERT_OUT (filename);
2987
2988   while (!(rtnval = opendir (filename))
2989          && (errno == EINTR))
2990     ;
2991   return rtnval;
2992 }
2993 #endif /* ENCAPSULATE_OPENDIR */
2994
2995
2996 #ifdef ENCAPSULATE_READDIR
2997 DIRENTRY *
2998 sys_readdir (DIR *dirp)
2999 {
3000   DIRENTRY *rtnval;
3001
3002   /* Apparently setting errno is necessary on some systems?
3003      Maybe readdir() doesn't always set errno ?! */
3004   while (!(errno = 0, rtnval = readdir (dirp))
3005          && (errno == EINTR))
3006     ;
3007 #ifndef MULE
3008   return rtnval;
3009 #else /* MULE */
3010   if (rtnval == NULL)           /* End of directory */
3011     return NULL;
3012   {
3013     Extcount external_len;
3014     int ascii_filename_p = 1;
3015     const Extbyte * const external_name = (const Extbyte *) rtnval->d_name;
3016
3017     /* Optimize for the common all-ASCII case, computing len en passant */
3018     for (external_len = 0; external_name[external_len] ; external_len++)
3019       {
3020         if (!BYTE_ASCII_P (external_name[external_len]))
3021           ascii_filename_p = 0;
3022       }
3023     if (ascii_filename_p)
3024       return rtnval;
3025
3026     { /* Non-ASCII filename */
3027       static Bufbyte_dynarr *internal_DIRENTRY;
3028       const Bufbyte *internal_name;
3029       Bytecount internal_len;
3030       if (!internal_DIRENTRY)
3031         internal_DIRENTRY = Dynarr_new (Bufbyte);
3032       else
3033         Dynarr_reset (internal_DIRENTRY);
3034
3035       Dynarr_add_many (internal_DIRENTRY, (Bufbyte *) rtnval,
3036                        offsetof (DIRENTRY, d_name));
3037
3038       TO_INTERNAL_FORMAT (DATA, (external_name, external_len),
3039                           ALLOCA, (internal_name, internal_len),
3040                           Qfile_name);
3041
3042       Dynarr_add_many (internal_DIRENTRY, internal_name, internal_len);
3043       Dynarr_add (internal_DIRENTRY, 0); /* zero-terminate */
3044       return (DIRENTRY *) Dynarr_atp (internal_DIRENTRY, 0);
3045     }
3046   }
3047 #endif /* MULE */
3048 }
3049 #endif /* ENCAPSULATE_READDIR */
3050
3051
3052 #ifdef ENCAPSULATE_CLOSEDIR
3053 int
3054 sys_closedir (DIR *dirp)
3055 {
3056   int rtnval;
3057
3058   while ((rtnval = closedir (dirp)) == -1
3059          && (errno == EINTR))
3060     ;
3061   return rtnval;
3062 }
3063 #endif /* ENCAPSULATE_CLOSEDIR */
3064
3065
3066 #ifdef ENCAPSULATE_RMDIR
3067 int
3068 sys_rmdir (const char *path)
3069 {
3070   PATHNAME_CONVERT_OUT (path);
3071   return rmdir (path);
3072 }
3073 #endif /* ENCAPSULATE_RMDIR */
3074
3075
3076 /***************** file-information calls ******************/
3077
3078 #ifdef ENCAPSULATE_ACCESS
3079 int
3080 sys_access (const char *path, int mode)
3081 {
3082   PATHNAME_CONVERT_OUT (path);
3083   return access (path, mode);
3084 }
3085 #endif /* ENCAPSULATE_ACCESS */
3086
3087
3088 #ifdef HAVE_EACCESS
3089 #ifdef ENCAPSULATE_EACCESS
3090 int
3091 sys_eaccess (const char *path, int mode)
3092 {
3093   PATHNAME_CONVERT_OUT (path);
3094   return eaccess (path, mode);
3095 }
3096 #endif /* ENCAPSULATE_EACCESS */
3097 #endif /* HAVE_EACCESS */
3098
3099
3100 #ifdef ENCAPSULATE_LSTAT
3101 int
3102 sys_lstat (const char *path, struct stat *buf)
3103 {
3104   PATHNAME_CONVERT_OUT (path);
3105   return lstat (path, buf);
3106 }
3107 #endif /* ENCAPSULATE_LSTAT */
3108
3109
3110 #ifdef ENCAPSULATE_READLINK
3111 int
3112 sys_readlink (const char *path, char *buf, size_t bufsiz)
3113 {
3114   PATHNAME_CONVERT_OUT (path);
3115   /* #### currently we don't do conversions on the incoming data */
3116   return readlink (path, buf, bufsiz);
3117 }
3118 #endif /* ENCAPSULATE_READLINK */
3119
3120
3121 #ifdef ENCAPSULATE_FSTAT
3122 int
3123 sys_fstat (int fd, struct stat *buf)
3124 {
3125   return fstat (fd, buf);
3126 }
3127 #endif /* ENCAPSULATE_FSTAT */
3128
3129
3130 #ifdef ENCAPSULATE_STAT
3131 int
3132 sys_stat (const char *path, struct stat *buf)
3133 {
3134   PATHNAME_CONVERT_OUT (path);
3135   return stat (path, buf);
3136 }
3137 #endif /* ENCAPSULATE_STAT */
3138
3139
3140 /****************** file-manipulation calls *****************/
3141
3142 #ifdef ENCAPSULATE_CHMOD
3143 int
3144 sys_chmod (const char *path, mode_t mode)
3145 {
3146   PATHNAME_CONVERT_OUT (path);
3147   return chmod (path, mode);
3148 }
3149 #endif /* ENCAPSULATE_CHMOD */
3150
3151
3152 #ifdef ENCAPSULATE_CREAT
3153 int
3154 sys_creat (const char *path, mode_t mode)
3155 {
3156   PATHNAME_CONVERT_OUT (path);
3157   return creat (path, mode);
3158 }
3159 #endif /* ENCAPSULATE_CREAT */
3160
3161
3162 #ifdef ENCAPSULATE_LINK
3163 int
3164 sys_link (const char *existing, const char *new)
3165 {
3166   PATHNAME_CONVERT_OUT (existing);
3167   PATHNAME_CONVERT_OUT (new);
3168   return link (existing, new);
3169 }
3170 #endif /* ENCAPSULATE_LINK */
3171
3172
3173 #ifdef ENCAPSULATE_RENAME
3174 int
3175 sys_rename (const char *old, const char *new)
3176 {
3177   PATHNAME_CONVERT_OUT (old);
3178   PATHNAME_CONVERT_OUT (new);
3179 #ifdef WINDOWSNT
3180   /* Windows rename fails if NEW exists */
3181   if (rename (old, new) == 0)
3182     return 0;
3183   if (errno != EEXIST)
3184     return -1;
3185   unlink (new);
3186 #endif /* WINDOWSNT */
3187   return rename (old, new);
3188 }
3189 #endif /* ENCAPSULATE_RENAME */
3190
3191
3192 #ifdef ENCAPSULATE_SYMLINK
3193 int
3194 sys_symlink (const char *name1, const char *name2)
3195 {
3196   PATHNAME_CONVERT_OUT (name1);
3197   PATHNAME_CONVERT_OUT (name2);
3198   return symlink (name1, name2);
3199 }
3200 #endif /* ENCAPSULATE_SYMLINK */
3201
3202
3203 #ifdef ENCAPSULATE_UNLINK
3204 int
3205 sys_unlink (const char *path)
3206 {
3207   PATHNAME_CONVERT_OUT (path);
3208   return unlink (path);
3209 }
3210 #endif /* ENCAPSULATE_UNLINK */
3211
3212
3213 #ifdef ENCAPSULATE_EXECVP
3214 int
3215 sys_execvp (const char *path, char * const * argv)
3216 {
3217   int i, argc;
3218   char ** new_argv;
3219
3220   PATHNAME_CONVERT_OUT (path);
3221   for (argc = 0; argv[argc]; argc++)
3222     ;
3223   new_argv = alloca_array (char *, argc + 1);
3224   for (i = 0; i < argc; i++)
3225     {
3226       new_argv[i] = argv[i];
3227       PATHNAME_CONVERT_OUT (new_argv[i]);
3228     }
3229   new_argv[argc] = NULL;
3230   return execvp (path, new_argv);
3231 }
3232 #endif /* ENCAPSULATE_EXECVP */
3233
3234 \f
3235 /************************************************************************/
3236 /*                  Emulations of missing system calls                  */
3237 /************************************************************************/
3238
3239 /***** (these are primarily required for USG, it seems) *****/
3240
3241 #ifndef HAVE_GETCWD
3242 char *
3243 getcwd (char *pathname, size_t size)
3244 {
3245   return getwd (pathname);
3246 }
3247 #endif /* emulate getcwd */
3248
3249
3250 #if 0 /* mrb */
3251 /*
3252  *      Warning, this function may not duplicate BSD 4.2 action properly
3253  *      under error conditions.
3254  */
3255
3256 #ifndef HAVE_GETWD
3257 char *
3258 getwd (char *pathname)
3259 {
3260   char *npath, *spath;
3261 #if !__STDC__ && !defined(STDC_HEADERS)
3262   extern char *getcwd ();
3263 #endif
3264
3265   spath = npath = getcwd ((char *) 0, MAXPATHLEN);
3266   if (spath == 0)
3267     return spath;
3268   /* On Altos 3068, getcwd can return @hostname/dir, so discard
3269      up to first slash.  Should be harmless on other systems.  */
3270   while (*npath && *npath != '/')
3271     npath++;
3272   strcpy (pathname, npath);
3273   xfree (spath);                  /* getcwd uses malloc */
3274   return pathname;
3275 }
3276 #endif /* HAVE_GETWD */
3277 #endif /* 0 - mrb */
3278
3279 /*
3280  *      Emulate rename using unlink/link.  Note that this is
3281  *      only partially correct.  Also, doesn't enforce restriction
3282  *      that files be of same type (regular->regular, dir->dir, etc).
3283  */
3284
3285 #ifndef HAVE_RENAME
3286 int
3287 rename (const char *from, const char *to)
3288 {
3289   if (access (from, 0) == 0)
3290     {
3291       unlink (to);
3292       if (link (from, to) == 0)
3293         if (unlink (from) == 0)
3294           return (0);
3295     }
3296   return (-1);
3297 }
3298 #endif /* HAVE_RENAME */
3299
3300 #ifdef HPUX
3301 #ifndef HAVE_PERROR
3302
3303 /* HPUX curses library references perror, but as far as we know
3304    it won't be called.  Anyway this definition will do for now.  */
3305
3306 perror (void)
3307 {
3308 }
3309
3310 #endif /* not HAVE_PERROR */
3311 #endif /* HPUX */
3312
3313 #ifndef HAVE_DUP2
3314
3315 /*
3316  *      Emulate BSD dup2.  First close newd if it already exists.
3317  *      Then, attempt to dup oldd.  If not successful, call dup2 recursively
3318  *      until we are, then close the unsuccessful ones.
3319  */
3320
3321 int
3322 dup2 (int oldd, int newd)
3323 {
3324   int fd, ret;
3325
3326   sys_close (newd);
3327
3328 #ifdef F_DUPFD
3329   fd = fcntl (oldd, F_DUPFD, newd);
3330   if (fd != newd)
3331     error ("can't dup2 (%i,%i) : %s", oldd, newd, strerror (errno));
3332 #else
3333   fd = dup (old);
3334   if (fd == -1)
3335     return -1;
3336   if (fd == new)
3337     return new;
3338   ret = dup2 (old, new);
3339   sys_close (fd);
3340   return ret;
3341 #endif /*  F_DUPFD */
3342 }
3343
3344 #endif /* not HAVE_DUP2 */
3345
3346 /*
3347  *      Gettimeofday.  Simulate as much as possible.  Only accurate
3348  *      to nearest second.  Emacs doesn't use tzp so ignore it for now.
3349  */
3350
3351 #if !defined (HAVE_GETTIMEOFDAY)
3352
3353 int
3354 gettimeofday (struct timeval *tp, struct timezone *tzp)
3355 {
3356   extern long time ();
3357
3358   tp->tv_sec = time ((long *)0);
3359   tp->tv_usec = 0;
3360   if (tzp != 0)
3361     tzp->tz_minuteswest = -1;
3362   return (0);
3363 }
3364
3365 #endif /* !HAVE_GETTIMEOFDAY */
3366
3367 /* No need to encapsulate utime and utimes explicitly because all
3368    access to those functions goes through the following. */
3369
3370 int
3371 set_file_times (char *filename, EMACS_TIME atime, EMACS_TIME mtime)
3372 {
3373 #ifdef HAVE_UTIMES
3374   struct timeval tv[2];
3375   tv[0] = atime;
3376   tv[1] = mtime;
3377   return utimes (filename, tv);
3378 #else /* not HAVE_UTIMES */
3379   struct utimbuf utb;
3380   utb.actime = EMACS_SECS (atime);
3381   utb.modtime = EMACS_SECS (mtime);
3382   return utime (filename, &utb);
3383 #endif /* not HAVE_UTIMES */
3384 }
3385
3386 /* */
3387
3388 static long ticks_per_second;
3389 static long orig_user_ticks, orig_system_ticks;
3390 EMACS_TIME orig_real_time;
3391
3392 static int process_times_available;
3393
3394 /* Return the relative user and system tick count.  We try to
3395    maintain calculations in terms of integers as long as possible
3396    for increased accuracy. */
3397
3398 static int
3399 get_process_times_1 (long *user_ticks, long *system_ticks)
3400 {
3401 #if defined (_SC_CLK_TCK) || defined (CLK_TCK) && !defined(WINDOWSNT)
3402   /* We have the POSIX times() function available. */
3403   struct tms tttt;
3404   times (&tttt);
3405   *user_ticks = (long) tttt.tms_utime;
3406   *system_ticks = (long) tttt.tms_stime;
3407   return 1;
3408 #elif defined (CLOCKS_PER_SEC)
3409   *user_ticks = (long) clock ();
3410   *system_ticks = 0;
3411   return 1;
3412 #else
3413   return 0;
3414 #endif
3415 }
3416
3417 void
3418 init_process_times_very_early (void)
3419 {
3420 #if defined (_SC_CLK_TCK)
3421   ticks_per_second = sysconf (_SC_CLK_TCK);
3422 #elif defined (CLK_TCK)
3423   ticks_per_second = CLK_TCK;
3424 #elif defined (CLOCKS_PER_SEC)
3425   ticks_per_second = CLOCKS_PER_SEC;
3426 #endif
3427
3428   process_times_available = get_process_times_1 (&orig_user_ticks,
3429                                                  &orig_system_ticks);
3430   EMACS_GET_TIME (orig_real_time);
3431 }
3432
3433 /* Return the user and system times used up by this process so far. */
3434 void
3435 get_process_times (double *user_time, double *system_time, double *real_time)
3436 {
3437   EMACS_TIME curr_real_time;
3438   EMACS_TIME elapsed_time;
3439   long curr_user_ticks, curr_system_ticks;
3440
3441   EMACS_GET_TIME (curr_real_time);
3442   EMACS_SUB_TIME (elapsed_time, curr_real_time, orig_real_time);
3443   *real_time = (EMACS_SECS (elapsed_time)
3444                 + ((double) EMACS_USECS (elapsed_time)) / 1000000);
3445   if (get_process_times_1 (&curr_user_ticks, &curr_system_ticks))
3446     {
3447       *user_time = (((double) (curr_user_ticks - orig_user_ticks))
3448                     / ticks_per_second);
3449       *system_time = (((double) (curr_system_ticks - orig_system_ticks))
3450                       / ticks_per_second);
3451     }
3452   else
3453     {
3454       /* A lame OS */
3455       *user_time = *real_time;
3456       *system_time = 0;
3457     }
3458 }
3459
3460 #ifndef HAVE_RANDOM
3461 #ifdef random
3462 #define HAVE_RANDOM
3463 #endif
3464 #endif
3465
3466 /* Figure out how many bits the system's random number generator uses.
3467    `random' and `lrand48' are assumed to return 31 usable bits.
3468    BSD `rand' returns a 31 bit value but the low order bits are unusable;
3469    so we'll shift it and treat it like the 15-bit USG `rand'.  */
3470
3471 #ifndef RAND_BITS
3472 # ifdef HAVE_RANDOM
3473 #  define RAND_BITS 31
3474 # else /* !HAVE_RANDOM */
3475 #  ifdef HAVE_LRAND48
3476 #   define RAND_BITS 31
3477 #   define random lrand48
3478 #  else /* !HAVE_LRAND48 */
3479 #   define RAND_BITS 15
3480 #   if RAND_MAX == 32767
3481 #    define random rand
3482 #   else /* RAND_MAX != 32767 */
3483 #    if RAND_MAX == 2147483647
3484 #     define random() (rand () >> 16)
3485 #    else /* RAND_MAX != 2147483647 */
3486 #     ifdef USG
3487 #      define random rand
3488 #     else
3489 #      define random() (rand () >> 16)
3490 #     endif /* !BSD */
3491 #    endif /* RAND_MAX != 2147483647 */
3492 #   endif /* RAND_MAX != 32767 */
3493 #  endif /* !HAVE_LRAND48 */
3494 # endif /* !HAVE_RANDOM */
3495 #endif /* !RAND_BITS */
3496
3497 void seed_random (long arg);
3498 void
3499 seed_random (long arg)
3500 {
3501 #ifdef HAVE_RANDOM
3502   srandom ((unsigned int)arg);
3503 #else
3504 # ifdef HAVE_LRAND48
3505   srand48 (arg);
3506 # else
3507   srand ((unsigned int)arg);
3508 # endif
3509 #endif
3510 }
3511
3512 /*
3513  * Build a full Emacs-sized word out of whatever we've got.
3514  * This suffices even for a 64-bit architecture with a 15-bit rand.
3515  */
3516 long get_random (void);
3517 long
3518 get_random (void)
3519 {
3520   long val = random ();
3521 #if VALBITS > RAND_BITS
3522   val = (val << RAND_BITS) ^ random ();
3523 #if VALBITS > 2*RAND_BITS
3524   val = (val << RAND_BITS) ^ random ();
3525 #if VALBITS > 3*RAND_BITS
3526   val = (val << RAND_BITS) ^ random ();
3527 #if VALBITS > 4*RAND_BITS
3528   val = (val << RAND_BITS) ^ random ();
3529 #endif /* need at least 5 */
3530 #endif /* need at least 4 */
3531 #endif /* need at least 3 */
3532 #endif /* need at least 2 */
3533   return val & ((1L << VALBITS) - 1);
3534 }
3535
3536 \f
3537 /************************************************************************/
3538 /*               Strings corresponding to defined signals               */
3539 /************************************************************************/
3540
3541 #if !defined (SYS_SIGLIST_DECLARED) && !defined (HAVE_SYS_SIGLIST)
3542
3543 #if defined(WINDOWSNT) || defined(__CYGWIN32__)
3544 const char *sys_siglist[] =
3545   {
3546     "bum signal!!",
3547     "hangup",
3548     "interrupt",
3549     "quit",
3550     "illegal instruction",
3551     "trace trap",
3552     "iot instruction",
3553     "emt instruction",
3554     "floating point exception",
3555     "kill",
3556     "bus error",
3557     "segmentation violation",
3558     "bad argument to system call",
3559     "write on a pipe with no one to read it",
3560     "alarm clock",
3561     "software termination signal from kill",
3562     "status signal",
3563     "sendable stop signal not from tty",
3564     "stop signal from tty",
3565     "continue a stopped process",
3566     "child status has changed",
3567     "background read attempted from control tty",
3568     "background write attempted from control tty",
3569     "input record available at control tty",
3570     "exceeded CPU time limit",
3571     "exceeded file size limit"
3572     };
3573 #endif
3574
3575 #ifdef USG
3576 #ifdef AIX
3577 const char *sys_siglist[NSIG + 1] =
3578   {
3579     /* AIX has changed the signals a bit */
3580     DEFER_GETTEXT ("bogus signal"),                     /* 0 */
3581     DEFER_GETTEXT ("hangup"),                           /* 1  SIGHUP */
3582     DEFER_GETTEXT ("interrupt"),                        /* 2  SIGINT */
3583     DEFER_GETTEXT ("quit"),                             /* 3  SIGQUIT */
3584     DEFER_GETTEXT ("illegal instruction"),              /* 4  SIGILL */
3585     DEFER_GETTEXT ("trace trap"),                       /* 5  SIGTRAP */
3586     DEFER_GETTEXT ("IOT instruction"),                  /* 6  SIGIOT */
3587     DEFER_GETTEXT ("crash likely"),                     /* 7  SIGDANGER */
3588     DEFER_GETTEXT ("floating point exception"),         /* 8  SIGFPE */
3589     DEFER_GETTEXT ("kill"),                             /* 9  SIGKILL */
3590     DEFER_GETTEXT ("bus error"),                        /* 10 SIGBUS */
3591     DEFER_GETTEXT ("segmentation violation"),           /* 11 SIGSEGV */
3592     DEFER_GETTEXT ("bad argument to system call"),      /* 12 SIGSYS */
3593     DEFER_GETTEXT ("write on a pipe with no one to read it"), /* 13 SIGPIPE */
3594     DEFER_GETTEXT ("alarm clock"),                      /* 14 SIGALRM */
3595     DEFER_GETTEXT ("software termination signum"),      /* 15 SIGTERM */
3596     DEFER_GETTEXT ("user defined signal 1"),            /* 16 SIGUSR1 */
3597     DEFER_GETTEXT ("user defined signal 2"),            /* 17 SIGUSR2 */
3598     DEFER_GETTEXT ("death of a child"),                 /* 18 SIGCLD */
3599     DEFER_GETTEXT ("power-fail restart"),               /* 19 SIGPWR */
3600     DEFER_GETTEXT ("bogus signal"),                     /* 20 */
3601     DEFER_GETTEXT ("bogus signal"),                     /* 21 */
3602     DEFER_GETTEXT ("bogus signal"),                     /* 22 */
3603     DEFER_GETTEXT ("bogus signal"),                     /* 23 */
3604     DEFER_GETTEXT ("bogus signal"),                     /* 24 */
3605     DEFER_GETTEXT ("LAN I/O interrupt"),                /* 25 SIGAIO */
3606     DEFER_GETTEXT ("PTY I/O interrupt"),                /* 26 SIGPTY */
3607     DEFER_GETTEXT ("I/O intervention required"),        /* 27 SIGIOINT */
3608 #ifdef AIXHFT
3609     DEFER_GETTEXT ("HFT grant"),                        /* 28 SIGGRANT */
3610     DEFER_GETTEXT ("HFT retract"),                      /* 29 SIGRETRACT */
3611     DEFER_GETTEXT ("HFT sound done"),                   /* 30 SIGSOUND */
3612     DEFER_GETTEXT ("HFT input ready"),                  /* 31 SIGMSG */
3613 #endif
3614     0
3615   };
3616 #else /* USG, not AIX */
3617 const char *sys_siglist[NSIG + 1] =
3618   {
3619     DEFER_GETTEXT ("bogus signal"),                     /* 0 */
3620     DEFER_GETTEXT ("hangup"),                           /* 1  SIGHUP */
3621     DEFER_GETTEXT ("interrupt"),                        /* 2  SIGINT */
3622     DEFER_GETTEXT ("quit"),                             /* 3  SIGQUIT */
3623     DEFER_GETTEXT ("illegal instruction"),              /* 4  SIGILL */
3624     DEFER_GETTEXT ("trace trap"),                       /* 5  SIGTRAP */
3625     DEFER_GETTEXT ("IOT instruction"),                  /* 6  SIGIOT */
3626     DEFER_GETTEXT ("EMT instruction"),                  /* 7  SIGEMT */
3627     DEFER_GETTEXT ("floating point exception"),         /* 8  SIGFPE */
3628     DEFER_GETTEXT ("kill"),                             /* 9  SIGKILL */
3629     DEFER_GETTEXT ("bus error"),                        /* 10 SIGBUS */
3630     DEFER_GETTEXT ("segmentation violation"),           /* 11 SIGSEGV */
3631     DEFER_GETTEXT ("bad argument to system call"),      /* 12 SIGSYS */
3632     DEFER_GETTEXT ("write on a pipe with no one to read it"), /* 13 SIGPIPE */
3633     DEFER_GETTEXT ("alarm clock"),                      /* 14 SIGALRM */
3634     DEFER_GETTEXT ("software termination signum"),      /* 15 SIGTERM */
3635     DEFER_GETTEXT ("user defined signal 1"),            /* 16 SIGUSR1 */
3636     DEFER_GETTEXT ("user defined signal 2"),            /* 17 SIGUSR2 */
3637     DEFER_GETTEXT ("death of a child"),                 /* 18 SIGCLD */
3638     DEFER_GETTEXT ("power-fail restart"),               /* 19 SIGPWR */
3639 #ifdef sun
3640     DEFER_GETTEXT ("window size changed"),              /* 20 SIGWINCH */
3641     DEFER_GETTEXT ("urgent socket condition"),          /* 21 SIGURG */
3642     DEFER_GETTEXT ("pollable event occurred"),          /* 22 SIGPOLL */
3643     DEFER_GETTEXT ("stop (cannot be caught or ignored)"), /*  23 SIGSTOP */
3644     DEFER_GETTEXT ("user stop requested from tty"),     /* 24 SIGTSTP */
3645     DEFER_GETTEXT ("stopped process has been continued"), /* 25 SIGCONT */
3646     DEFER_GETTEXT ("background tty read attempted"),    /* 26 SIGTTIN */
3647     DEFER_GETTEXT ("background tty write attempted"),   /* 27 SIGTTOU */
3648     DEFER_GETTEXT ("virtual timer expired"),            /* 28 SIGVTALRM */
3649     DEFER_GETTEXT ("profiling timer expired"),          /* 29 SIGPROF */
3650     DEFER_GETTEXT ("exceeded cpu limit"),               /* 30 SIGXCPU */
3651     DEFER_GETTEXT ("exceeded file size limit"),         /* 31 SIGXFSZ */
3652     DEFER_GETTEXT ("process's lwps are blocked"),       /* 32 SIGWAITING */
3653     DEFER_GETTEXT ("special signal used by thread library"), /* 33 SIGLWP */
3654 #ifdef SIGFREEZE
3655     DEFER_GETTEXT ("special signal used by CPR"),        /* 34 SIGFREEZE */
3656 #endif
3657 #ifdef SIGTHAW
3658     DEFER_GETTEXT ("special signal used by CPR"),        /* 35 SIGTHAW */
3659 #endif
3660 #endif /* sun */
3661     0
3662   };
3663 #endif /* not AIX */
3664 #endif /* USG */
3665 #ifdef DGUX
3666 const char *sys_siglist[NSIG + 1] =
3667   {
3668     DEFER_GETTEXT ("null signal"),                       /*  0 SIGNULL   */
3669     DEFER_GETTEXT ("hangup"),                            /*  1 SIGHUP    */
3670     DEFER_GETTEXT ("interrupt"),                         /*  2 SIGINT    */
3671     DEFER_GETTEXT ("quit"),                              /*  3 SIGQUIT   */
3672     DEFER_GETTEXT ("illegal instruction"),               /*  4 SIGILL    */
3673     DEFER_GETTEXT ("trace trap"),                        /*  5 SIGTRAP   */
3674     DEFER_GETTEXT ("abort termination"),                 /*  6 SIGABRT   */
3675     DEFER_GETTEXT ("SIGEMT"),                            /*  7 SIGEMT    */
3676     DEFER_GETTEXT ("floating point exception"),          /*  8 SIGFPE    */
3677     DEFER_GETTEXT ("kill"),                              /*  9 SIGKILL   */
3678     DEFER_GETTEXT ("bus error"),                         /* 10 SIGBUS    */
3679     DEFER_GETTEXT ("segmentation violation"),            /* 11 SIGSEGV   */
3680     DEFER_GETTEXT ("bad argument to system call"),       /* 12 SIGSYS    */
3681     DEFER_GETTEXT ("write on a pipe with no reader"),    /* 13 SIGPIPE   */
3682     DEFER_GETTEXT ("alarm clock"),                       /* 14 SIGALRM   */
3683     DEFER_GETTEXT ("software termination signal"),       /* 15 SIGTERM   */
3684     DEFER_GETTEXT ("user defined signal 1"),             /* 16 SIGUSR1   */
3685     DEFER_GETTEXT ("user defined signal 2"),             /* 17 SIGUSR2   */
3686     DEFER_GETTEXT ("child stopped or terminated"),       /* 18 SIGCLD    */
3687     DEFER_GETTEXT ("power-fail restart"),                /* 19 SIGPWR    */
3688     DEFER_GETTEXT ("window size changed"),               /* 20 SIGWINCH  */
3689     DEFER_GETTEXT ("undefined"),                         /* 21           */
3690     DEFER_GETTEXT ("pollable event occurred"),           /* 22 SIGPOLL   */
3691     DEFER_GETTEXT ("sendable stop signal not from tty"), /* 23 SIGSTOP   */
3692     DEFER_GETTEXT ("stop signal from tty"),              /* 24 SIGSTP    */
3693     DEFER_GETTEXT ("continue a stopped process"),        /* 25 SIGCONT   */
3694     DEFER_GETTEXT ("attempted background tty read"),     /* 26 SIGTTIN   */
3695     DEFER_GETTEXT ("attempted background tty write"),    /* 27 SIGTTOU   */
3696     DEFER_GETTEXT ("undefined"),                         /* 28           */
3697     DEFER_GETTEXT ("undefined"),                         /* 29           */
3698     DEFER_GETTEXT ("undefined"),                         /* 30           */
3699     DEFER_GETTEXT ("undefined"),                         /* 31           */
3700     DEFER_GETTEXT ("undefined"),                         /* 32           */
3701     DEFER_GETTEXT ("socket (TCP/IP) urgent data arrival"), /* 33 SIGURG    */
3702     DEFER_GETTEXT ("I/O is possible"),                   /* 34 SIGIO     */
3703     DEFER_GETTEXT ("exceeded cpu time limit"),           /* 35 SIGXCPU   */
3704     DEFER_GETTEXT ("exceeded file size limit"),          /* 36 SIGXFSZ   */
3705     DEFER_GETTEXT ("virtual time alarm"),                /* 37 SIGVTALRM */
3706     DEFER_GETTEXT ("profiling time alarm"),              /* 38 SIGPROF   */
3707     DEFER_GETTEXT ("undefined"),                         /* 39           */
3708     DEFER_GETTEXT ("file record locks revoked"),         /* 40 SIGLOST   */
3709     DEFER_GETTEXT ("undefined"),                         /* 41           */
3710     DEFER_GETTEXT ("undefined"),                         /* 42           */
3711     DEFER_GETTEXT ("undefined"),                         /* 43           */
3712     DEFER_GETTEXT ("undefined"),                         /* 44           */
3713     DEFER_GETTEXT ("undefined"),                         /* 45           */
3714     DEFER_GETTEXT ("undefined"),                         /* 46           */
3715     DEFER_GETTEXT ("undefined"),                         /* 47           */
3716     DEFER_GETTEXT ("undefined"),                         /* 48           */
3717     DEFER_GETTEXT ("undefined"),                         /* 49           */
3718     DEFER_GETTEXT ("undefined"),                         /* 50           */
3719     DEFER_GETTEXT ("undefined"),                         /* 51           */
3720     DEFER_GETTEXT ("undefined"),                         /* 52           */
3721     DEFER_GETTEXT ("undefined"),                         /* 53           */
3722     DEFER_GETTEXT ("undefined"),                         /* 54           */
3723     DEFER_GETTEXT ("undefined"),                         /* 55           */
3724     DEFER_GETTEXT ("undefined"),                         /* 56           */
3725     DEFER_GETTEXT ("undefined"),                         /* 57           */
3726     DEFER_GETTEXT ("undefined"),                         /* 58           */
3727     DEFER_GETTEXT ("undefined"),                         /* 59           */
3728     DEFER_GETTEXT ("undefined"),                         /* 60           */
3729     DEFER_GETTEXT ("undefined"),                         /* 61           */
3730     DEFER_GETTEXT ("undefined"),                         /* 62           */
3731     DEFER_GETTEXT ("undefined"),                         /* 63           */
3732     DEFER_GETTEXT ("notification message in mess. queue"), /* 64 SIGDGNOTIFY */
3733     0
3734   };
3735 #endif /* DGUX */
3736
3737 #endif /* ! SYS_SIGLIST_DECLARED && ! HAVE_SYS_SIGLIST */
3738
3739 \f
3740 /************************************************************************/
3741 /*         Directory routines for systems that don't have them          */
3742 /************************************************************************/
3743
3744 #ifdef SYSV_SYSTEM_DIR
3745
3746 #include <dirent.h>
3747
3748 #if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
3749 int
3750 closedir (DIR *dirp)  /* stream from opendir */
3751 {
3752   int rtnval;
3753
3754   rtnval = sys_close (dirp->dd_fd);
3755
3756   /* Some systems (like Solaris) allocate the buffer and the DIR all
3757      in one block.  Why in the world are we freeing this ourselves
3758      anyway?  */
3759 #if ! (defined (sun) && defined (USG5_4))
3760   xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
3761 #endif
3762   xfree ((char *) dirp);
3763   return (rtnval);
3764 }
3765 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3766 #endif /* SYSV_SYSTEM_DIR */
3767
3768 #ifdef NONSYSTEM_DIR_LIBRARY
3769
3770 DIR *
3771 opendir (const char *filename)  /* name of directory */
3772 {
3773   DIR *dirp;            /* -> malloc'ed storage */
3774   int fd;               /* file descriptor for read */
3775   struct stat sbuf;             /* result of fstat */
3776
3777   fd = sys_open (filename, O_RDONLY);
3778   if (fd < 0)
3779     return 0;
3780
3781   if (fstat (fd, &sbuf) < 0
3782       || (sbuf.st_mode & S_IFMT) != S_IFDIR
3783       || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
3784     {
3785       sys_close (fd);
3786       return 0;         /* bad luck today */
3787     }
3788
3789   dirp->dd_fd = fd;
3790   dirp->dd_loc = dirp->dd_size = 0;     /* refill needed */
3791
3792   return dirp;
3793 }
3794
3795 void
3796 closedir (DIR *dirp)            /* stream from opendir */
3797 {
3798   sys_close (dirp->dd_fd);
3799   xfree (dirp);
3800 }
3801
3802
3803 #define DIRSIZ  14
3804 struct olddir
3805   {
3806     ino_t od_ino;               /* inode */
3807     char od_name[DIRSIZ];       /* filename */
3808   };
3809
3810 static struct direct dir_static; /* simulated directory contents */
3811
3812 /* ARGUSED */
3813 struct direct *
3814 readdir (DIR *dirp)     /* stream from opendir */
3815 {
3816   struct olddir *dp;    /* -> directory data */
3817
3818   for (; ;)
3819     {
3820       if (dirp->dd_loc >= dirp->dd_size)
3821         dirp->dd_loc = dirp->dd_size = 0;
3822
3823       if (dirp->dd_size == 0    /* refill buffer */
3824           && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3825         return 0;
3826
3827       dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3828       dirp->dd_loc += sizeof (struct olddir);
3829
3830       if (dp->od_ino != 0)      /* not deleted entry */
3831         {
3832           dir_static.d_ino = dp->od_ino;
3833           strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3834           dir_static.d_name[DIRSIZ] = '\0';
3835           dir_static.d_namlen = strlen (dir_static.d_name);
3836           dir_static.d_reclen = sizeof (struct direct)
3837             - MAXNAMLEN + 3
3838               + dir_static.d_namlen - dir_static.d_namlen % 4;
3839           return &dir_static;   /* -> simulated structure */
3840         }
3841     }
3842 }
3843
3844
3845 #endif /* NONSYSTEM_DIR_LIBRARY */
3846
3847 \f
3848 /* mkdir and rmdir functions, for systems which don't have them.  */
3849
3850 #ifndef HAVE_MKDIR
3851 /*
3852  * Written by Robert Rother, Mariah Corporation, August 1985.
3853  *
3854  * If you want it, it's yours.  All I ask in return is that if you
3855  * figure out how to do this in a Bourne Shell script you send me
3856  * a copy.
3857  *                                      sdcsvax!rmr or rmr@uscd
3858  *
3859  * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3860  * subroutine.  11Mar86; hoptoad!gnu
3861  *
3862  * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3863  * subroutine didn't return EEXIST.  It does now.
3864  */
3865
3866 /*
3867  * Make a directory.
3868  */
3869 #ifdef MKDIR_PROTOTYPE
3870 MKDIR_PROTOTYPE
3871 #else
3872 int
3873 mkdir (const char *dpath, int dmode)
3874 #endif
3875 {
3876   int cpid, status, fd;
3877   struct stat statbuf;
3878
3879   if (stat (dpath, &statbuf) == 0)
3880     {
3881       errno = EEXIST;           /* Stat worked, so it already exists */
3882       return -1;
3883     }
3884
3885   /* If stat fails for a reason other than non-existence, return error */
3886   if (errno != ENOENT)
3887     return -1;
3888
3889   synch_process_alive = 1;
3890   switch (cpid = fork ())
3891     {
3892
3893     case -1:                    /* Error in fork() */
3894       return -1;                /* Errno is set already */
3895
3896     case 0:                     /* Child process */
3897     {
3898       /*
3899        * Cheap hack to set mode of new directory.  Since this
3900        * child process is going away anyway, we zap its umask.
3901        * ####, this won't suffice to set SUID, SGID, etc. on this
3902        * directory.  Does anybody care?
3903        */
3904       status = umask (0);       /* Get current umask */
3905       status = umask (status | (0777 & ~dmode));        /* Set for mkdir */
3906       fd = sys_open ("/dev/null", O_RDWR);
3907       if (fd >= 0)
3908         {
3909           if (fd != STDIN_FILENO)  dup2 (fd, STDIN_FILENO);
3910           if (fd != STDOUT_FILENO) dup2 (fd, STDOUT_FILENO);
3911           if (fd != STDERR_FILENO) dup2 (fd, STDERR_FILENO);
3912         }
3913       execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
3914       _exit (-1);               /* Can't exec /bin/mkdir */
3915     }
3916
3917     default:                    /* Parent process */
3918       wait_for_termination (cpid);
3919     }
3920
3921   if (synch_process_death != 0 || synch_process_retcode != 0)
3922     {
3923       errno = EIO;              /* We don't know why, but */
3924       return -1;                /* /bin/mkdir failed */
3925     }
3926
3927   return 0;
3928 }
3929 #endif /* not HAVE_MKDIR */
3930
3931 #ifndef HAVE_RMDIR
3932 int
3933 rmdir (const char *dpath)
3934 {
3935   int cpid, status, fd;
3936   struct stat statbuf;
3937
3938   if (stat (dpath, &statbuf) != 0)
3939     {
3940       /* Stat just set errno.  We don't have to */
3941       return -1;
3942     }
3943
3944   synch_process_alive = 1;
3945   switch (cpid = fork ())
3946     {
3947
3948     case -1:                    /* Error in fork() */
3949       return (-1);              /* Errno is set already */
3950
3951     case 0:                     /* Child process */
3952       fd = sys_open("/dev/null", O_RDWR);
3953       if (fd >= 0)
3954         {
3955           if (fd != STDIN_FILENO)  dup2 (fd, STDIN_FILENO);
3956           if (fd != STDOUT_FILENO) dup2 (fd, STDOUT_FILENO);
3957           if (fd != STDERR_FILENO) dup2 (fd, STDERR_FILENO);
3958         }
3959       execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
3960       _exit (-1);               /* Can't exec /bin/mkdir */
3961
3962     default:                    /* Parent process */
3963       wait_for_termination (cpid);
3964     }
3965
3966   if (synch_process_death   != 0 ||
3967       synch_process_retcode != 0)
3968     {
3969       errno = EIO;              /* We don't know why, but */
3970       return -1;                /* /bin/rmdir failed */
3971     }
3972
3973   return 0;
3974 }
3975 #endif /* !HAVE_RMDIR */
3976
3977 \f
3978 /************************************************************************/
3979 /*                            Misc. SunOS crap                          */
3980 /************************************************************************/
3981
3982 #ifdef USE_DL_STUBS
3983
3984 /* These are included on Sunos 4.1 when we do not use shared libraries.
3985    X11 libraries may refer to these functions but (we hope) do not
3986    actually call them.  */
3987
3988 void *
3989 dlopen (void)
3990 {
3991   return 0;
3992 }
3993
3994 void *
3995 dlsym (void)
3996 {
3997   return 0;
3998 }
3999
4000 int
4001 dlclose (void)
4002 {
4003   return -1;
4004 }
4005
4006 #endif /* USE_DL_STUBS */
4007
4008 \f
4009
4010 #ifndef HAVE_STRCASECMP
4011 /*
4012  * From BSD
4013  */
4014 static unsigned char charmap[] = {
4015         '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
4016         '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
4017         '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
4018         '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
4019         '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
4020         '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
4021         '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
4022         '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
4023         '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
4024         '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
4025         '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
4026         '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
4027         '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
4028         '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
4029         '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
4030         '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
4031         '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
4032         '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
4033         '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
4034         '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
4035         '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
4036         '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
4037         '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
4038         '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
4039         '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
4040         '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
4041         '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
4042         '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
4043         '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
4044         '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
4045         '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
4046         '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
4047 };
4048
4049 int
4050 strcasecmp (char *s1, char *s2)
4051 {
4052   unsigned char *cm = charmap;
4053   unsigned char *us1 = (unsigned char *) s1;
4054   unsigned char *us2 = (unsigned char *)s2;
4055
4056   while (cm[*us1] == cm[*us2++])
4057     if (*us1++ == '\0')
4058       return (0);
4059
4060   return (cm[*us1] - cm[*--us2]);
4061 }
4062 #endif /* !HAVE_STRCASECMP */