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