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