Partially sync files.el from XEmacs 21.5 for wildcard support.
[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
1375         emacs_get_tty(input_fd, &CONSOLE_TTY_DATA(con)->old_tty);
1376         tty = CONSOLE_TTY_DATA(con)->old_tty;
1377
1378         con->tty_erase_char = Qnil;
1379
1380 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1381         /* after all those years... */
1382         con->tty_erase_char = make_char(tty.main.c_cc[VERASE]);
1383 #ifdef DGUX
1384         /* This allows meta to be sent on 8th bit.  */
1385         tty.main.c_iflag &= ~INPCK;     /* don't check input for parity */
1386 #endif
1387         tty.main.c_iflag |= (IGNBRK);   /* Ignore break condition */
1388         tty.main.c_iflag &= ~ICRNL;     /* Disable map of CR to NL on input */
1389 #ifdef ISTRIP
1390         tty.main.c_iflag &= ~ISTRIP;    /* don't strip 8th bit on input */
1391 #endif
1392         tty.main.c_lflag &= ~ECHO;      /* Disable echo */
1393         tty.main.c_lflag &= ~ICANON;    /* Disable erase/kill processing */
1394 #ifdef IEXTEN
1395         tty.main.c_lflag &= ~IEXTEN;    /* Disable other editing characters.  */
1396 #endif
1397         tty.main.c_lflag |= ISIG;       /* Enable signals */
1398         if (TTY_FLAGS(con).flow_control) {
1399                 tty.main.c_iflag |= IXON;       /* Enable start/stop output control */
1400 #ifdef IXANY
1401                 tty.main.c_iflag &= ~IXANY;
1402 #endif                          /* IXANY */
1403         } else
1404                 tty.main.c_iflag &= ~IXON;      /* Disable start/stop output control */
1405         tty.main.c_oflag &= ~ONLCR;     /* Disable map of NL to CR-NL
1406                                            on output */
1407         tty.main.c_oflag &= ~TAB3;      /* Disable tab expansion */
1408 #ifdef CS8
1409         if (TTY_FLAGS(con).meta_key) {
1410                 tty.main.c_cflag |= CS8;        /* allow 8th bit on input */
1411                 tty.main.c_cflag &= ~PARENB;    /* Don't check parity */
1412         }
1413 #endif
1414         if (CONSOLE_TTY_DATA(con)->controlling_terminal) {
1415                 tty.main.c_cc[VINTR] = CONSOLE_QUIT_CHAR(con);  /* C-g (usually) gives SIGINT */
1416                 /* Set up C-g for both SIGQUIT and SIGINT.
1417                    We don't know which we will get, but we handle both alike
1418                    so which one it really gives us does not matter.  */
1419                 tty.main.c_cc[VQUIT] = CONSOLE_QUIT_CHAR(con);
1420         } else {
1421                 tty.main.c_cc[VINTR] = _POSIX_VDISABLE;
1422                 tty.main.c_cc[VQUIT] = _POSIX_VDISABLE;
1423         }
1424         tty.main.c_cc[VMIN] = 1;        /* Input should wait for at
1425                                            least 1 char */
1426         tty.main.c_cc[VTIME] = 0;       /* no matter how long that takes.  */
1427 #ifdef VSWTCH
1428         tty.main.c_cc[VSWTCH] = _POSIX_VDISABLE;        /* Turn off shell layering use
1429                                                            of C-z */
1430 #endif                          /* VSWTCH */
1431         /* There was some conditionalizing here on (mips or TCATTR), but
1432            I think that's wrong.  There was one report of C-y (DSUSP) not being
1433            disabled on HP9000s700 systems, and this might fix it. */
1434 #ifdef VSUSP
1435         tty.main.c_cc[VSUSP] = _POSIX_VDISABLE; /* Turn off mips handling of C-z. */
1436 #endif                          /* VSUSP */
1437 #ifdef V_DSUSP
1438         tty.main.c_cc[V_DSUSP] = _POSIX_VDISABLE;       /* Turn off mips handling of C-y. */
1439 #endif                          /* V_DSUSP */
1440 #ifdef VDSUSP                   /* Some systems have VDSUSP, some have V_DSUSP.  */
1441         tty.main.c_cc[VDSUSP] = _POSIX_VDISABLE;
1442 #endif                          /* VDSUSP */
1443 #ifdef VLNEXT
1444         tty.main.c_cc[VLNEXT] = _POSIX_VDISABLE;
1445 #endif                          /* VLNEXT */
1446 #ifdef VREPRINT
1447         tty.main.c_cc[VREPRINT] = _POSIX_VDISABLE;
1448 #endif                          /* VREPRINT */
1449 #ifdef VWERASE
1450         tty.main.c_cc[VWERASE] = _POSIX_VDISABLE;
1451 #endif                          /* VWERASE */
1452 #ifdef VDISCARD
1453         tty.main.c_cc[VDISCARD] = _POSIX_VDISABLE;
1454 #endif                          /* VDISCARD */
1455 #ifdef VSTART
1456         tty.main.c_cc[VSTART] = _POSIX_VDISABLE;
1457 #endif                          /* VSTART */
1458 #ifdef VSTRT
1459         tty.main.c_cc[VSTRT] = _POSIX_VDISABLE; /* called VSTRT on some systems */
1460 #endif                          /* VSTART */
1461 #ifdef VSTOP
1462         tty.main.c_cc[VSTOP] = _POSIX_VDISABLE;
1463 #endif                          /* VSTOP */
1464 #ifdef SET_LINE_DISCIPLINE
1465         /* Need to explicitly request TERMIODISC line discipline or
1466            Ultrix's termios does not work correctly.  */
1467         tty.main.c_line = SET_LINE_DISCIPLINE;
1468 #endif
1469
1470 #ifdef AIX
1471 #ifndef IBMR2AIX
1472         /* AIX enhanced edit loses NULs, so disable it. */
1473         tty.main.c_line = 0;
1474         tty.main.c_iflag &= ~ASCEDIT;
1475 #else
1476         tty.main.c_cc[VSTRT] = 255;
1477         tty.main.c_cc[VSTOP] = 255;
1478         tty.main.c_cc[VSUSP] = 255;
1479         tty.main.c_cc[VDSUSP] = 255;
1480 #endif                          /* IBMR2AIX */
1481         /* Also, PTY overloads NUL and BREAK.
1482            don't ignore break, but don't signal either, so it looks like NUL.
1483            This really serves a purpose only if running in an XTERM window
1484            or via TELNET or the like, but does no harm elsewhere.  */
1485         tty.main.c_iflag &= ~IGNBRK;
1486         tty.main.c_iflag &= ~BRKINT;
1487 #endif                          /* AIX */
1488 #else                           /* if not HAVE_TERMIO */
1489         con->tty_erase_char = make_char(tty.main.sg_erase);
1490         tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1491         if (TTY_FLAGS(con).meta_key)
1492                 tty.main.sg_flags |= ANYP;
1493         /* #### should we be using RAW mode here? */
1494         tty.main.sg_flags |= /* interrupt_input ? RAW : */ CBREAK;
1495 #endif                          /* not HAVE_TERMIO */
1496
1497         /* If going to use CBREAK mode, we must request C-g to interrupt
1498            and turn off start and stop chars, etc.  If not going to use
1499            CBREAK mode, do this anyway so as to turn off local flow
1500            control for user coming over network on 4.2; in this case,
1501            only t_stopc and t_startc really matter.  */
1502 #ifndef HAVE_TERMIO
1503 #ifdef HAVE_TCHARS
1504         /* Note: if not using CBREAK mode, it makes no difference how we
1505            set this */
1506         tty.tchars = new_tchars;
1507         tty.tchars.t_intrc = CONSOLE_QUIT_CHAR(con);
1508         if (TTY_FLAGS(con).flow_control) {
1509                 tty.tchars.t_startc = '\021';
1510                 tty.tchars.t_stopc = '\023';
1511         }
1512
1513         tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH |
1514             CONSOLE_TTY_DATA(con)->old_tty.lmode;
1515
1516 #if defined (ultrix) || defined (__bsdi__)
1517         /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1518            anything, and leaving it in breaks the meta key.  Go figure.  */
1519         /* Turning off ONLCR is enough under BSD/386.  Leave the general
1520            output post-processing flag alone since for some reason it
1521            doesn't get reset after XEmacs goes away. */
1522         tty.lmode &= ~LLITOUT;
1523 #endif
1524
1525 #endif                          /* HAVE_TCHARS */
1526 #endif                          /* not HAVE_TERMIO */
1527
1528 #ifdef HAVE_LTCHARS
1529         tty.ltchars = new_ltchars;
1530 #endif                          /* HAVE_LTCHARS */
1531
1532         emacs_set_tty(input_fd, &tty, 0);
1533
1534         /* This code added to insure that, if flow-control is not to be used,
1535            we have an unlocked terminal at the start. */
1536
1537 #ifdef TCXONC
1538         if (!TTY_FLAGS(con).flow_control)
1539                 ioctl(input_fd, TCXONC, 1);
1540 #endif
1541 #ifdef TIOCSTART
1542         if (!TTY_FLAGS(con).flow_control)
1543                 ioctl(input_fd, TIOCSTART, 0);
1544 #endif
1545
1546 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1547 #ifdef TCOON
1548         if (!TTY_FLAGS(con).flow_control)
1549                 tcflow(input_fd, TCOON);
1550 #endif
1551 #endif
1552 #ifdef AIXHFT
1553         hft_init(con);
1554 #ifdef IBMR2AIX
1555         {
1556                 /* IBM's HFT device usually thinks a ^J should be LF/CR.
1557                    We need it to be only LF.  This is the way that is
1558                    done. */
1559                 struct termio tty;
1560
1561                 if (ioctl(output_fd, HFTGETID, &tty) != -1)
1562                         write(output_fd, "\033[20l", 5);
1563         }
1564 #endif
1565 #endif
1566
1567 #if 0                           /* We do our own buffering with lstreams. */
1568 #ifdef _IOFBF
1569         /* This symbol is defined on recent USG systems.
1570            Someone says without this call USG won't really buffer the file
1571            even with a call to setbuf. */
1572         setvbuf(CONSOLE_TTY_DATA(con)->outfd, (char *)_sobuf, _IOFBF,
1573                 sizeof _sobuf);
1574 #else
1575         setbuf(CONSOLE_TTY_DATA(con)->outfd, (char *)_sobuf);
1576 #endif
1577 #endif
1578         set_tty_modes(con);
1579 }
1580
1581 #endif                          /* HAVE_TTY */
1582
1583 void init_one_device(struct device *d)
1584 {
1585 #ifdef HAVE_TTY
1586         if (DEVICE_TTY_P(d))
1587                 tty_init_sys_modes_on_device(d);
1588 #endif
1589 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
1590         if (!DEVICE_STREAM_P(d)) {
1591                 init_sigio_on_device(d);
1592                 request_sigio_on_device(d);
1593         }
1594 #endif
1595 }
1596
1597 void init_one_console(struct console *con)
1598 {
1599         Lisp_Object devcons;
1600
1601         CONSOLE_DEVICE_LOOP(devcons, con) {
1602                 struct device *d = XDEVICE(XCAR(devcons));
1603
1604                 init_one_device(d);
1605         }
1606 }
1607
1608 void reinit_initial_console(void)
1609 {
1610         munge_process_groups();
1611         if (CONSOLEP(Vcontrolling_terminal) &&
1612             CONSOLE_LIVE_P(XCONSOLE(Vcontrolling_terminal)))
1613                 init_one_console(XCONSOLE(Vcontrolling_terminal));
1614 }
1615 \f
1616 /* ------------------------------------------------------ */
1617 /*                   Other TTY functions                  */
1618 /* ------------------------------------------------------ */
1619
1620 #ifdef HAVE_TTY
1621
1622 #if 0                           /* not currently used */
1623
1624 /* Return nonzero if safe to use tabs in output.
1625    At the time this is called, init_sys_modes has not been done yet.  */
1626
1627 int tabs_safe_p(struct device *d)
1628 {
1629 #ifdef HAVE_TTY
1630         if (DEVICE_TTY_P(d)) {
1631                 struct emacs_tty tty;
1632
1633                 emacs_get_tty(DEVICE_INFD(d), &tty);
1634                 return EMACS_TTY_TABS_OK(&tty);
1635         }
1636 #endif
1637         return 1;
1638 }
1639
1640 #endif                          /* 0 */
1641
1642 /* Get terminal size from system.
1643    Store number of lines into *heightp and width into *widthp.
1644    If zero or a negative number is stored, the value is not valid.  */
1645
1646 void get_tty_device_size(struct device *d, int *widthp, int *heightp)
1647 {
1648         int input_fd = DEVICE_INFD(d);
1649
1650         assert(DEVICE_TTY_P(d));
1651
1652 #ifdef TIOCGWINSZ
1653         {
1654                 /* BSD-style.  */
1655                 struct winsize size;
1656
1657                 if (ioctl(input_fd, TIOCGWINSZ, &size) == -1)
1658                         *widthp = *heightp = 0;
1659                 else {
1660                         *widthp = size.ws_col;
1661                         *heightp = size.ws_row;
1662                 }
1663         }
1664 #elif defined TIOCGSIZE
1665         {
1666                 /* SunOS - style.  */
1667                 struct ttysize size;
1668
1669                 if (ioctl(input_fd, TIOCGSIZE, &size) == -1)
1670                         *widthp = *heightp = 0;
1671                 else {
1672                         *widthp = size.ts_cols;
1673                         *heightp = size.ts_lines;
1674                 }
1675         }
1676 #else                           /* system doesn't know size */
1677
1678         *widthp = 0;
1679         *heightp = 0;
1680
1681 #endif                          /* not !TIOCGWINSZ */
1682 }
1683
1684 #endif                          /* HAVE_TTY */
1685 \f
1686 /* ------------------------------------------------------ */
1687 /*                   Is device 8 bit ?                    */
1688 /* ------------------------------------------------------ */
1689
1690 #ifdef HAVE_TTY
1691
1692 int eight_bit_tty(struct device *d)
1693 {
1694         struct emacs_tty s;
1695         int input_fd;
1696         int eight_bit = 0;
1697
1698         assert(DEVICE_TTY_P(d));
1699         input_fd = DEVICE_INFD(d);
1700
1701         emacs_get_tty(input_fd, &s);
1702
1703 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1704         eight_bit = (s.main.c_cflag & CSIZE) == CS8;
1705 #else
1706         eight_bit = 0;          /* I don't know how to do it */
1707 #endif
1708         return eight_bit;
1709 }
1710
1711 #endif                          /* HAVE_TTY */
1712 \f
1713 /* ------------------------------------------------------ */
1714 /*                   Resetting a device                   */
1715 /* ------------------------------------------------------ */
1716
1717 #ifdef HAVE_TTY
1718
1719 /* Prepare the terminal for exiting Emacs; move the cursor to the
1720    bottom of the frame, turn off interrupt-driven I/O, etc.  */
1721 static void tty_reset_sys_modes_on_device(struct device *d)
1722 {
1723         int input_fd, output_fd;
1724         struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
1725
1726         input_fd = CONSOLE_TTY_DATA(con)->infd;
1727         output_fd = CONSOLE_TTY_DATA(con)->outfd;
1728
1729 #if defined (IBMR2AIX) && defined (AIXHFT)
1730         {
1731                 /* HFT consoles normally use ^J as a LF/CR.  We forced it to
1732                    do the LF only.  Now, we need to reset it. */
1733                 struct termio tty;
1734
1735                 if (ioctl(output_fd, HFTGETID, &tty) != -1)
1736                         write(output_fd, "\033[20h", 5);
1737         }
1738 #endif
1739
1740         tty_redisplay_shutdown(con);
1741         /* reset_tty_modes() flushes the connection at its end. */
1742         reset_tty_modes(con);
1743
1744 #if defined (BSD)
1745         /* Avoid possible loss of output when changing terminal modes.  */
1746         fsync(output_fd);
1747 #endif
1748
1749         while (emacs_set_tty(input_fd, &CONSOLE_TTY_DATA(con)->old_tty, 0)
1750                < 0 && errno == EINTR) ;
1751
1752 #ifdef SET_LINE_DISCIPLINE
1753         /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1754            A different old line discipline is therefore not restored, yet.
1755            Restore the old line discipline by hand.  */
1756         ioctl(input_fd, TIOCSETD, &old_tty.main.c_line);
1757 #endif
1758
1759 #ifdef AIXHFT
1760         hft_reset(con);
1761 #endif
1762
1763 }
1764
1765 #endif                          /* HAVE_TTY */
1766
1767 void reset_one_device(struct device *d)
1768 {
1769 #ifdef HAVE_TTY
1770         if (DEVICE_TTY_P(d))
1771                 tty_reset_sys_modes_on_device(d);
1772         else
1773 #endif
1774         if (DEVICE_STREAM_P(d))
1775                 fflush(CONSOLE_STREAM_DATA(XCONSOLE(DEVICE_CONSOLE(d)))->out);
1776 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
1777         if (!DEVICE_STREAM_P(d)) {
1778                 unrequest_sigio_on_device(d);
1779                 reset_sigio_on_device(d);
1780         }
1781 #endif
1782 }
1783
1784 void reset_one_console(struct console *con)
1785 {
1786         /* Note: this can be called during GC. */
1787         Lisp_Object devcons;
1788
1789         CONSOLE_DEVICE_LOOP(devcons, con) {
1790                 struct device *d = XDEVICE(XCAR(devcons));
1791
1792                 reset_one_device(d);
1793         }
1794 }
1795
1796 void reset_all_consoles(void)
1797 {
1798         /* Note: this can be called during GC. */
1799         Lisp_Object concons;
1800
1801         CONSOLE_LOOP(concons) {
1802                 struct console *con = XCONSOLE(XCAR(concons));
1803
1804                 reset_one_console(con);
1805         }
1806
1807         unmunge_process_groups();
1808 }
1809
1810 void reset_initial_console(void)
1811 {
1812         if (CONSOLEP(Vcontrolling_terminal) &&
1813             CONSOLE_LIVE_P(XCONSOLE(Vcontrolling_terminal)))
1814                 reset_one_console(XCONSOLE(Vcontrolling_terminal));
1815         unmunge_process_groups();
1816 }
1817 \f
1818 /* ------------------------------------------------------ */
1819 /*                 extra TTY stuff under AIX              */
1820 /* ------------------------------------------------------ */
1821
1822 #ifdef AIXHFT
1823
1824 /* Called from init_sys_modes.  */
1825 static void hft_init(struct console *con)
1826 {
1827         int junk;
1828         int input_fd;
1829
1830         assert(CONSOLE_TTY_P(con));
1831         input_fd = CONSOLE_TTY_DATA(con)->infd;
1832
1833         /* If we're not on an HFT we shouldn't do any of this.  We determine
1834            if we are on an HFT by trying to get an HFT error code.  If this
1835            call fails, we're not on an HFT. */
1836 #ifdef IBMR2AIX
1837         if (ioctl(input_fd, HFQERROR, &junk) < 0)
1838                 return;
1839 #else                           /* not IBMR2AIX */
1840         if (ioctl(input_fd, HFQEIO, 0) < 0)
1841                 return;
1842 #endif                          /* not IBMR2AIX */
1843
1844         /* On AIX the default hft keyboard mapping uses backspace rather than delete
1845            as the rubout key's ASCII code.  Here this is changed.  The bug is that
1846            there's no way to determine the old mapping, so in reset_one_console
1847            we need to assume that the normal map had been present.  Of course, this
1848            code also doesn't help if on a terminal emulator which doesn't understand
1849            HFT VTD's. */
1850         {
1851                 struct hfbuf buf;
1852                 struct hfkeymap keymap;
1853
1854                 buf.hf_bufp = (char *)&keymap;
1855                 buf.hf_buflen = sizeof(keymap);
1856                 keymap.hf_nkeys = 2;
1857                 keymap.hfkey[0].hf_kpos = 15;
1858                 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
1859 #ifdef IBMR2AIX
1860                 keymap.hfkey[0].hf_keyidh = '<';
1861 #else                           /* not IBMR2AIX */
1862                 keymap.hfkey[0].hf_page = '<';
1863 #endif                          /* not IBMR2AIX */
1864                 keymap.hfkey[0].hf_char = 127;
1865                 keymap.hfkey[1].hf_kpos = 15;
1866                 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
1867 #ifdef IBMR2AIX
1868                 keymap.hfkey[1].hf_keyidh = '<';
1869 #else                           /* not IBMR2AIX */
1870                 keymap.hfkey[1].hf_page = '<';
1871 #endif                          /* not IBMR2AIX */
1872                 keymap.hfkey[1].hf_char = 127;
1873                 hftctl(input_fd, HFSKBD, &buf);
1874         }
1875         /* #### Should probably set a console TTY flag here. */
1876 #if 0
1877         /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
1878            at times. */
1879         line_ins_del_ok = char_ins_del_ok = 0;
1880 #endif                          /* 0 */
1881 }
1882
1883 /* Reset the rubout key to backspace. */
1884
1885 static void hft_reset(struct console *con)
1886 {
1887         struct hfbuf buf;
1888         struct hfkeymap keymap;
1889         int junk;
1890         int input_fd;
1891
1892         assert(CONSOLE_TTY_P(con));
1893         input_fd = CONSOLE_TTY_DATA(con)->infd;
1894
1895 #ifdef IBMR2AIX
1896         if (ioctl(input_fd, HFQERROR, &junk) < 0)
1897                 return;
1898 #else                           /* not IBMR2AIX */
1899         if (ioctl(input_fd, HFQEIO, 0) < 0)
1900                 return;
1901 #endif                          /* not IBMR2AIX */
1902
1903         buf.hf_bufp = (char *)&keymap;
1904         buf.hf_buflen = sizeof(keymap);
1905         keymap.hf_nkeys = 2;
1906         keymap.hfkey[0].hf_kpos = 15;
1907         keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
1908 #ifdef IBMR2AIX
1909         keymap.hfkey[0].hf_keyidh = '<';
1910 #else                           /* not IBMR2AIX */
1911         keymap.hfkey[0].hf_page = '<';
1912 #endif                          /* not IBMR2AIX */
1913         keymap.hfkey[0].hf_char = 8;
1914         keymap.hfkey[1].hf_kpos = 15;
1915         keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
1916 #ifdef IBMR2AIX
1917         keymap.hfkey[1].hf_keyidh = '<';
1918 #else                           /* not IBMR2AIX */
1919         keymap.hfkey[1].hf_page = '<';
1920 #endif                          /* not IBMR2AIX */
1921         keymap.hfkey[1].hf_char = 8;
1922         hftctl(input_fd, HFSKBD, &buf);
1923 }
1924
1925 #endif                          /* AIXHFT */
1926 \f
1927 /************************************************************************/
1928 /*                    limits of text/data segments                      */
1929 /************************************************************************/
1930
1931 #if !defined(CANNOT_DUMP) && !defined(PDUMP)
1932 #define NEED_STARTS
1933 #endif
1934
1935 #ifndef SYSTEM_MALLOC
1936 #ifndef NEED_STARTS
1937 #define NEED_STARTS
1938 #endif
1939 #endif
1940
1941 #ifdef NEED_STARTS
1942 /* Some systems that cannot dump also cannot implement these.  */
1943
1944 /*
1945  *      Return the address of the start of the text segment prior to
1946  *      doing an unexec.  After unexec the return value is undefined.
1947  *      See crt0.c for further explanation and _start.
1948  *
1949  */
1950
1951 #if !defined(HAVE_TEXT_START) && !defined(PDUMP)
1952
1953 EXTERN_C int _start(void);
1954
1955 char *start_of_text(void)
1956 {
1957 #ifdef TEXT_START
1958         return (char *)TEXT_START;
1959 #else
1960         return (char *)_start;
1961 #endif                          /* TEXT_START */
1962 }
1963 #endif                          /* !defined(HAVE_TEXT_START) && !defined(PDUMP) */
1964
1965 /*
1966  *      Return the address of the start of the data segment prior to
1967  *      doing an unexec.  After unexec the return value is undefined.
1968  *      See ecrt0.c for further information and definition of data_start.
1969  *
1970  *      Apparently, on BSD systems this is etext at startup.  On
1971  *      USG systems (swapping) this is highly mmu dependent and
1972  *      is also dependent on whether or not the program is running
1973  *      with shared text.  Generally there is a (possibly large)
1974  *      gap between end of text and start of data with shared text.
1975  *
1976  *      On Uniplus+ systems with shared text, data starts at a
1977  *      fixed address.  Each port (from a given oem) is generally
1978  *      different, and the specific value of the start of data can
1979  *      be obtained via the UniPlus+ specific "uvar" system call,
1980  *      however the method outlined in crt0.c seems to be more portable.
1981  *
1982  *      Probably what will have to happen when a USG unexec is available,
1983  *      at least on UniPlus, is temacs will have to be made unshared so
1984  *      that text and data are contiguous.  Then once loadup is complete,
1985  *      unexec will produce a shared executable where the data can be
1986  *      at the normal shared text boundary and the startofdata variable
1987  *      will be patched by unexec to the correct value.
1988  *
1989  */
1990
1991 #if defined(ORDINARY_LINK)
1992 extern char **environ;
1993 #endif
1994
1995 void *start_of_data(void)
1996 {
1997 #ifdef DATA_START
1998         return ((char *)DATA_START);
1999 #else
2000 #if defined (ORDINARY_LINK) || defined(PDUMP)
2001         /*
2002          * This is a hack.  Since we're not linking crt0.c or pre_crt0.c,
2003          * data_start isn't defined.  We take the address of environ, which
2004          * is known to live at or near the start of the system crt0.c, and
2005          * we don't sweat the handful of bytes that might lose.
2006          */
2007 #if defined (HEAP_IN_DATA) && !defined(PDUMP)
2008         extern char *static_heap_base;
2009         if (!initialized)
2010                 return static_heap_base;
2011 #endif
2012         return ((char *)&environ);
2013 #else
2014         extern int data_start;
2015         return ((char *)&data_start);
2016 #endif                          /* ORDINARY_LINK */
2017 #endif                          /* DATA_START */
2018 }
2019 #endif                          /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2020
2021 #if !defined(CANNOT_DUMP) && !defined(PDUMP)
2022 /* Some systems that cannot dump also cannot implement these.  */
2023
2024 /*
2025  *      Return the address of the end of the text segment prior to
2026  *      doing an unexec.  After unexec the return value is undefined.
2027  */
2028
2029 char *end_of_text(void)
2030 {
2031 #ifdef TEXT_END
2032         return ((char *)TEXT_END);
2033 #else
2034         extern int etext;
2035         return ((char *)&etext);
2036 #endif
2037 }
2038
2039 /*
2040  *      Return the address of the end of the data segment prior to
2041  *      doing an unexec.  After unexec the return value is undefined.
2042  */
2043
2044 char *end_of_data(void)
2045 {
2046 #ifdef DATA_END
2047         return ((char *)DATA_END);
2048 #else
2049         extern int edata;
2050         return ((char *)&edata);
2051 #endif
2052 }
2053
2054 #endif                          /* !defined(CANNOT_DUMP) && !defined(PDUMP) */
2055 \f
2056 /************************************************************************/
2057 /*                          get the system name                         */
2058 /************************************************************************/
2059
2060 /* init_system_name sets up the string for the Lisp function
2061    system-name to return. */
2062
2063 extern Lisp_Object Vsystem_name;
2064
2065 void init_system_name(void)
2066 {
2067 #if !defined (HAVE_GETHOSTNAME)
2068         struct utsname uts;
2069         uname(&uts);
2070         Vsystem_name = build_string(uts.nodename);
2071 #else                           /* HAVE_GETHOSTNAME */
2072         unsigned int hostname_size = 256;
2073         char *hostname = (char *)alloca(hostname_size);
2074
2075         /* Try to get the host name; if the buffer is too short, try
2076            again.  Apparently, the only indication gethostname gives of
2077            whether the buffer was large enough is the presence or absence
2078            of a '\0' in the string.  Eech.  */
2079         for (;;) {
2080                 gethostname(hostname, hostname_size - 1);
2081                 hostname[hostname_size - 1] = '\0';
2082
2083                 /* Was the buffer large enough for the '\0'?  */
2084                 if (strlen(hostname) < (size_t) (hostname_size - 1))
2085                         break;
2086
2087                 hostname_size <<= 1;
2088                 hostname = (char *)alloca(hostname_size);
2089         }
2090 # if defined( HAVE_SOCKETS)
2091         /* Turn the hostname into the official, fully-qualified hostname.
2092            Don't do this if we're going to dump; this can confuse system
2093            libraries on some machines and make the dumped emacs core dump. */
2094 #  ifndef CANNOT_DUMP
2095         if (initialized)
2096 #  endif                        /* not CANNOT_DUMP */
2097                 if (!strchr(hostname, '.')) {
2098 #  if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETNAMEINFO))
2099                         struct hostent *hp = NULL;
2100                         int count;
2101 #   ifdef TRY_AGAIN
2102                         for (count = 0; count < 10; count++) {
2103                                 h_errno = 0;
2104 #   endif
2105                                 /* Some systems can't handle SIGALARM/SIGIO in gethostbyname(). */
2106                                 stop_interrupts();
2107                                 hp = gethostbyname(hostname);
2108                                 start_interrupts();
2109 #   ifdef TRY_AGAIN
2110                                 if (!(hp == 0 && h_errno == TRY_AGAIN))
2111                                         break;
2112                                 Fsleep_for(make_int(1));
2113                         }
2114 #   endif
2115                         if (hp) {
2116                                 const char *fqdn = (const char *)hp->h_name;
2117                                 size_t len = 0;
2118
2119                                 if (!strchr(fqdn, '.')) {
2120                                         /* We still don't have a fully qualified domain name.
2121                                            Try to find one in the list of alternate names */
2122                                         char **alias = hp->h_aliases;
2123                                         while (*alias && !strchr(*alias, '.'))
2124                                                 alias++;
2125                                         if (*alias)
2126                                                 fqdn = *alias;
2127                                 }
2128                                 len = strlen(fqdn) + 1;
2129                                 hostname = (char *)alloca(len);
2130                                 xstrncpy(hostname, fqdn,len);
2131                         }
2132 #  else                         /* !(HAVE_GETADDRINFO && HAVE_GETNAMEINFO) */
2133                         struct addrinfo hints, *res;
2134
2135                         xzero(hints);
2136                         hints.ai_flags = AI_CANONNAME;
2137 #ifdef IPV6_CANONICALIZE
2138                         hints.ai_family = AF_UNSPEC;
2139 #else
2140                         hints.ai_family = PF_INET;
2141 #endif
2142                         hints.ai_socktype = SOCK_STREAM;
2143                         hints.ai_protocol = 0;
2144                         if (!getaddrinfo(hostname, NULL, &hints, &res)) {
2145                                 ssize_t canon_len=strlen(res->ai_canonname)+1;
2146
2147                                 hostname = (char *)alloca(canon_len);
2148                                 xstrncpy(hostname, res->ai_canonname, canon_len);
2149                                 freeaddrinfo(res);
2150                         }
2151 #  endif                        /* !(HAVE_GETADDRINFO && HAVE_GETNAMEINFO) */
2152                 }
2153 # endif                         /* HAVE_SOCKETS */
2154         Vsystem_name = build_string(hostname);
2155 #endif                          /* HAVE_GETHOSTNAME  */
2156         {
2157                 Bufbyte *p;
2158                 Bytecount i;
2159
2160                 for (i = 0, p = XSTRING_DATA(Vsystem_name);
2161                      i < XSTRING_LENGTH(Vsystem_name); i++, p++) {
2162                         if (*p == ' ' || *p == '\t')
2163                                 *p = '-';
2164                 }
2165         }
2166 }
2167 \f
2168 /************************************************************************/
2169 /*                        Emulation of select()                         */
2170 /************************************************************************/
2171
2172 #ifndef HAVE_SELECT
2173
2174 ERROR:XEmacs requires a working select().
2175 #endif                          /* not HAVE_SELECT */
2176 \f/************************************************************************/
2177 /*                      Emulation of signal stuff                       */
2178 /************************************************************************/
2179 /* BSD 4.1 crap deleted.  4.2 was released in 1983, for God's sake!  I
2180    can't imagine that anyone is actually running that OS any more.
2181    You can't use X under it (I think) because there's no select().
2182    Anyway, the signal stuff has all been changed.  If someone wants to
2183    get this stuff working again, look in the FSF Emacs sources. */
2184 /* POSIX signals support - DJB */
2185 #ifdef HAVE_SIGPROCMASK
2186 /* #### Is there any reason this is static global rather than local? */
2187 static struct sigaction new_action, old_action;
2188
2189 signal_handler_t sys_do_signal(int signal_number, signal_handler_t action)
2190 {
2191 #if 0
2192
2193         /* XEmacs works better if system calls are *not* restarted.
2194            This allows C-g to interrupt reads and writes, on most systems.
2195
2196            #### Another possibility is to just longjmp() out of the signal
2197            handler.  According to W.R. Stevens, this should be OK on all
2198            systems.  However, I don't want to deal with the potential
2199            evil ramifications of this at this point. */
2200
2201 #ifdef DGUX
2202         /* This gets us restartable system calls for efficiency.
2203            The "else" code will work as well. */
2204         return (berk_signal(signal_number, action));
2205 #else
2206         sigemptyset(&new_action.sa_mask);
2207         new_action.sa_handler = action;
2208 #if defined (SA_RESTART)
2209         /* Emacs mostly works better with restartable system services. If this
2210          * flag exists, we probably want to turn it on here.
2211          */
2212         new_action.sa_flags = SA_RESTART;
2213 #else
2214         new_action.sa_flags = 0;
2215 #endif
2216         sigaction(signal_number, &new_action, &old_action);
2217         return (old_action.sa_handler);
2218 #endif                          /* DGUX */
2219
2220 #else                           /* not 0 */
2221
2222         sigemptyset(&new_action.sa_mask);
2223         new_action.sa_handler = action;
2224 #if defined (SA_INTERRUPT)      /* don't restart system calls, under SunOS */
2225         new_action.sa_flags = SA_INTERRUPT;
2226 #else
2227         new_action.sa_flags = 0;
2228 #endif
2229         sigaction(signal_number, &new_action, &old_action);
2230         return (signal_handler_t) (old_action.sa_handler);
2231
2232 #endif                          /* not 0 */
2233 }
2234
2235 #elif defined (HAVE_SIGBLOCK)
2236 /* We use sigvec() rather than signal() if we have it, because
2237    it lets us specify interruptible system calls. */
2238 signal_handler_t sys_do_signal(int signal_number, signal_handler_t action)
2239 {
2240         struct sigvec vec, ovec;
2241
2242         vec.sv_handler = action;
2243         vec.sv_mask = 0;
2244 #ifdef SV_INTERRUPT             /* don't restart system calls */
2245         vec.sv_flags = SV_INTERRUPT;
2246 #else
2247         vec.sv_flags = 0;
2248 #endif
2249
2250         sigvec(signal_number, &vec, &ovec);
2251
2252         return (ovec.sv_handler);
2253 }
2254
2255 #endif                          /* HAVE_SIGBLOCK (HAVE_SIGPROCMASK) */
2256 \f
2257 /************************************************************************/
2258 /*           Emulation of strerror() and errno support                  */
2259 /************************************************************************/
2260
2261 #ifndef HAVE_STRERROR
2262
2263 #if !defined(NeXT) && !defined(__alpha) && !defined(MACH) && !defined(LINUX) && !defined(IRIX) && !defined(__NetBSD__)
2264 /* Linux added here by Raymond L. Toy <toy@alydar.crd.ge.com> for XEmacs. */
2265 /* Irix added here by gparker@sni-usa.com for XEmacs. */
2266 /* NetBSD added here by James R Grinter <jrg@doc.ic.ac.uk> for XEmacs */
2267 extern const char *sys_errlist[];
2268 extern int sys_nerr;
2269 #endif
2270
2271 #ifdef __NetBSD__
2272 extern char *sys_errlist[];
2273 extern int sys_nerr;
2274 #endif
2275
2276 const char *strerror(int errnum)
2277 {
2278         if (errnum >= 0 && errnum < sys_nerr)
2279                 return sys_errlist[errnum];
2280         return ((const char *)GETTEXT("Unknown error"));
2281 }
2282
2283 #endif                          /* ! HAVE_STRERROR */
2284 \f
2285 /************************************************************************/
2286 /*                    Encapsulations of system calls                    */
2287 /************************************************************************/
2288
2289 #define PATHNAME_CONVERT_OUT(path, pathout)             \
2290         TO_EXTERNAL_FORMAT(C_STRING, (path),            \
2291                            C_STRING_ALLOCA, (pathout),  \
2292                            Qfile_name);
2293
2294 /***************** low-level calls ****************/
2295
2296 /*
2297  *      On USG systems the system calls are INTERRUPTIBLE by signals
2298  *      that the user program has elected to catch.  Thus the system call
2299  *      must be retried in these cases.  To handle this without massive
2300  *      changes in the source code, we remap the standard system call names
2301  *      to names for our own functions in sysdep.c that do the system call
2302  *      with retries.  Actually, for portability reasons, it is good
2303  *      programming practice, as this example shows, to limit all actual
2304  *      system calls to a single occurrence in the source.  Sure, this
2305  *      adds an extra level of function call overhead but it is almost
2306  *      always negligible.   Fred Fish, Unisoft Systems Inc.
2307  */
2308
2309 /* Ben sez: read Dick Gabriel's essay about the Worse Is Better
2310    approach to programming and its connection to the silly
2311    interruptible-system-call business.  To find it, look on
2312    Jamie's home page (http://www.jwz.org/worse-is-better.html). */
2313
2314 #ifdef ENCAPSULATE_OPEN
2315
2316 int raw_open(const char *path, int oflag, ...)
2317 {
2318         int mode;
2319         va_list ap;
2320
2321         va_start(ap, oflag);
2322         mode = va_arg(ap, int);
2323         va_end(ap);
2324         return open(path, oflag, mode);
2325 }
2326
2327 int sys_open(const char *path, int oflag, ...)
2328 {
2329         int mode;
2330         va_list ap;
2331         char *pout;
2332
2333         va_start(ap, oflag);
2334         mode = va_arg(ap, int);
2335         va_end(ap);
2336
2337         PATHNAME_CONVERT_OUT(path, pout);
2338
2339 #ifdef INTERRUPTIBLE_OPEN
2340         {
2341                 int rtnval;
2342                 while ((rtnval = open(pout, oflag, mode)) == -1
2343                        && (errno == EINTR))
2344                         DO_NOTHING;
2345                 return rtnval;
2346         }
2347 #else
2348         return open(pout, oflag, mode);
2349 #endif
2350 }
2351 #endif                          /* ENCAPSULATE_OPEN */
2352
2353 /* Like sys_open, only when open() is interrupted by EINTR, check for
2354    QUIT.  This allows the callers of this function to be interrupted
2355    with C-g when, say, reading from named pipes.  However, this should
2356    be used with caution, as it can GC.
2357
2358    This function will not function as expected on systems where open()
2359    is not interrupted by C-g.  However, the worst that can happen is
2360    the fallback to simple open().  */
2361 int interruptible_open(const char *path, int oflag, int mode)
2362 {
2363         /* This function can GC */
2364         char *nrout;
2365
2366         PATHNAME_CONVERT_OUT(path, nrout);
2367
2368         for (;;) {
2369                 int rtnval = open(nrout, oflag, mode);
2370                 if (!(rtnval == -1 && errno == EINTR))
2371                         return rtnval;
2372                 /* open() was interrupted.  Was QUIT responsible?  */
2373                 QUIT;
2374         }
2375 }
2376
2377 #ifdef ENCAPSULATE_CLOSE
2378 int sys_close(int filedes)
2379 {
2380 #ifdef INTERRUPTIBLE_CLOSE
2381         int did_retry = 0;
2382         REGISTER int rtnval;
2383
2384         while ((rtnval = close(filedes)) == -1 && (errno == EINTR))
2385                 did_retry = 1;
2386
2387         /* If close is interrupted SunOS 4.1 may or may not have closed the
2388            file descriptor.  If it did the second close will fail with
2389            errno = EBADF.  That means we have succeeded.  */
2390         if (rtnval == -1 && did_retry && errno == EBADF)
2391                 return 0;
2392
2393         return rtnval;
2394 #else
2395         return close(filedes);
2396 #endif
2397 }
2398 #endif                          /* ENCAPSULATE_CLOSE */
2399
2400 ssize_t sys_read_1(int fildes, void *buf, size_t nbyte, int allow_quit)
2401 {
2402         ssize_t rtnval;
2403
2404         /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */
2405         while ((rtnval = read(fildes, buf, nbyte)) == -1 && (errno == EINTR)) {
2406                 if (allow_quit)
2407                         REALLY_QUIT;
2408         }
2409         return rtnval;
2410 }
2411
2412 #ifdef ENCAPSULATE_READ
2413 ssize_t sys_read(int fildes, void *buf, size_t nbyte)
2414 {
2415         return sys_read_1(fildes, buf, nbyte, 0);
2416 }
2417 #endif                          /* ENCAPSULATE_READ */
2418
2419 ssize_t sys_write_1(int fildes, const void *buf, size_t nbyte, int allow_quit)
2420 {
2421         ssize_t bytes_written = 0;
2422         const char *b = (const char *)buf;
2423
2424         /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */
2425         while (nbyte > 0) {
2426                 ssize_t rtnval = write(fildes, b, nbyte);
2427
2428                 if (allow_quit)
2429                         REALLY_QUIT;
2430
2431                 if (rtnval == -1) {
2432                         if (errno == EINTR)
2433                                 continue;
2434                         else
2435                                 return bytes_written ? bytes_written : -1;
2436                 }
2437                 b += rtnval;
2438                 nbyte -= rtnval;
2439                 bytes_written += rtnval;
2440         }
2441         return bytes_written;
2442 }
2443
2444 #ifdef ENCAPSULATE_WRITE
2445 ssize_t sys_write(int fildes, const void *buf, size_t nbyte)
2446 {
2447         return sys_write_1(fildes, buf, nbyte, 0);
2448 }
2449 #endif                          /* ENCAPSULATE_WRITE */
2450
2451 /**************** stdio calls ****************/
2452
2453 /* There is at least some evidence that the stdio calls are interruptible
2454    just like the normal system calls, at least on some systems.  In any
2455    case, it doesn't hurt to encapsulate them. */
2456
2457 /* #### Should also encapsulate fflush().
2458    #### Should conceivably encapsulate getchar() etc.  What a pain! */
2459
2460 #ifdef ENCAPSULATE_FOPEN
2461 FILE *sys_fopen(const char *path, const char *type)
2462 {
2463         char *pout;
2464
2465         PATHNAME_CONVERT_OUT(path, pout);
2466 #if defined (INTERRUPTIBLE_OPEN)
2467         {
2468                 FILE *rtnval;
2469                 while (!(rtnval = fopen(pout, type)) && (errno == EINTR))
2470                         DO_NOTHING;
2471                 return rtnval;
2472         }
2473 #else
2474         return fopen(pout, type);
2475 #endif
2476 }
2477 #endif                          /* ENCAPSULATE_FOPEN */
2478
2479 #ifdef ENCAPSULATE_FCLOSE
2480 int sys_fclose(FILE * stream)
2481 {
2482 #ifdef INTERRUPTIBLE_CLOSE
2483         int fd     = fileno(stream);
2484         int rtnval = fclose(stream);
2485
2486         if (rtnval == EOF && (errno == EINTR))
2487                 while (((rtnval=close(fd))<0) && (errno == EINTR));
2488         return rtnval;
2489 #else
2490         return fclose(stream);
2491 #endif
2492 }
2493 #endif                          /* ENCAPSULATE_FCLOSE */
2494
2495 #ifdef ENCAPSULATE_FREAD
2496 size_t sys_fread(void *ptr, size_t size, size_t nitem, FILE * stream)
2497 {
2498 #ifdef INTERRUPTIBLE_IO
2499         size_t rtnval;
2500         size_t items_read = 0;
2501         char *b = (char *)ptr;
2502
2503         while (nitem > 0) {
2504                 rtnval = fread(b, size, nitem, stream);
2505                 if (rtnval == 0) {
2506                         if (ferror(stream) && errno == EINTR)
2507                                 continue;
2508                         else
2509                                 return items_read;
2510                 }
2511                 b += size * rtnval;
2512                 nitem -= rtnval;
2513                 items_read += rtnval;
2514         }
2515         return (items_read);
2516 #else
2517         return fread(ptr, size, nitem, stream);
2518 #endif
2519 }
2520 #endif                          /* ENCAPSULATE_FREAD */
2521
2522 #ifdef ENCAPSULATE_FWRITE
2523 size_t sys_fwrite(const void *ptr, size_t size, size_t nitem, FILE * stream)
2524 {
2525 #ifdef INTERRUPTIBLE_IO
2526         size_t rtnval;
2527         size_t items_written = 0;
2528         const char *b = (const char *)ptr;
2529
2530         while (nitem > 0) {
2531                 rtnval = fwrite(b, size, nitem, stream);
2532                 if (rtnval == 0) {
2533                         if (ferror(stream) && errno == EINTR)
2534                                 continue;
2535                         else
2536                                 return items_written;
2537                 }
2538                 b += size * rtnval;
2539                 nitem -= rtnval;
2540                 items_written += rtnval;
2541         }
2542         return (items_written);
2543 #else
2544         return fwrite(ptr, size, nitem, stream);
2545 #endif
2546 }
2547 #endif                          /* ENCAPSULATE_FWRITE */
2548
2549 /********************* directory calls *******************/
2550
2551 #ifdef ENCAPSULATE_CHDIR
2552 int sys_chdir(const char *path)
2553 {
2554         char *pout;
2555         PATHNAME_CONVERT_OUT(path, pout);
2556         return chdir(pout);
2557 }
2558 #endif                          /* ENCAPSULATE_CHDIR */
2559
2560 #ifdef ENCAPSULATE_MKDIR
2561 int sys_mkdir(const char *path, mode_t mode)
2562 {
2563         char *pout;
2564         PATHNAME_CONVERT_OUT(path, pout);
2565         return mkdir(pout, mode);
2566 }
2567 #endif                          /* ENCAPSULATE_MKDIR */
2568
2569 #ifdef ENCAPSULATE_OPENDIR
2570 DIR *sys_opendir(const char *filename)
2571 {
2572         DIR *rtnval;
2573         char *fout;
2574         PATHNAME_CONVERT_OUT(filename, fout);
2575
2576         while (!(rtnval = opendir(fout))
2577                && (errno == EINTR)) ;
2578         return rtnval;
2579 }
2580 #endif                          /* ENCAPSULATE_OPENDIR */
2581
2582 #ifdef ENCAPSULATE_READDIR
2583 DIRENTRY *sys_readdir(DIR * dirp)
2584 {
2585         DIRENTRY *rtnval;
2586
2587         /* Apparently setting errno is necessary on some systems?
2588            Maybe readdir() doesn't always set errno ?! */
2589         while (!(errno = 0, rtnval = readdir(dirp))
2590                && (errno == EINTR)) ;
2591 #ifndef MULE
2592         return rtnval;
2593 #else                           /* MULE */
2594         if (rtnval == NULL)     /* End of directory */
2595                 return NULL;
2596         {
2597                 const Extbyte *const external_name =
2598                     (const Extbyte *)rtnval->d_name;
2599                 Extcount external_len = strlen(rtnval->d_name);
2600                 const Bufbyte *internal_name;
2601                 Bytecount internal_len;
2602
2603                 TO_INTERNAL_FORMAT(DATA, (external_name, external_len),
2604                                    ALLOCA, (internal_name, internal_len),
2605                                    Qfile_name);
2606
2607                 /* check for common case of ASCII filename */
2608                 if (internal_len == external_len &&
2609                     !memcmp(external_name, internal_name, internal_len))
2610                         return rtnval;
2611
2612                 {               /* Non-ASCII filename */
2613                         static Bufbyte_dynarr *internal_DIRENTRY;
2614                         if (!internal_DIRENTRY)
2615                                 internal_DIRENTRY = Dynarr_new(Bufbyte);
2616                         else
2617                                 Dynarr_reset(internal_DIRENTRY);
2618
2619                         Dynarr_add_many(internal_DIRENTRY, (Bufbyte *) rtnval,
2620                                         offsetof(DIRENTRY, d_name));
2621
2622                         Dynarr_add_many(internal_DIRENTRY, internal_name,
2623                                         internal_len);
2624                         Dynarr_add(internal_DIRENTRY, '\0');    /* NUL-terminate */
2625                         return (DIRENTRY *) Dynarr_atp(internal_DIRENTRY, 0);
2626                 }
2627         }
2628 #endif                          /* MULE */
2629 }
2630 #endif                          /* ENCAPSULATE_READDIR */
2631
2632 #ifdef ENCAPSULATE_CLOSEDIR
2633 int sys_closedir(DIR * dirp)
2634 {
2635         int rtnval;
2636
2637         while ((rtnval = closedir(dirp)) == -1 && (errno == EINTR)) ;
2638         return rtnval;
2639 }
2640 #endif                          /* ENCAPSULATE_CLOSEDIR */
2641
2642 #ifdef ENCAPSULATE_RMDIR
2643 int sys_rmdir(const char *path)
2644 {
2645         char *pout;
2646         PATHNAME_CONVERT_OUT(path, pout);
2647         return rmdir(pout);
2648 }
2649 #endif                          /* ENCAPSULATE_RMDIR */
2650
2651 /***************** file-information calls ******************/
2652
2653 #ifdef ENCAPSULATE_ACCESS
2654 int sys_access(const char *path, int mode)
2655 {
2656         char *pout;
2657         PATHNAME_CONVERT_OUT(path, pout);
2658         return access(pout, mode);
2659 }
2660 #endif                          /* ENCAPSULATE_ACCESS */
2661
2662 #ifdef HAVE_EACCESS
2663 #ifdef ENCAPSULATE_EACCESS
2664 int sys_eaccess(const char *path, int mode)
2665 {
2666         char *pout;
2667         PATHNAME_CONVERT_OUT(path, pout);
2668         return eaccess(pout, mode);
2669 }
2670 #endif                          /* ENCAPSULATE_EACCESS */
2671 #endif                          /* HAVE_EACCESS */
2672
2673 #ifdef ENCAPSULATE_LSTAT
2674 int sys_lstat(const char *path, struct stat *buf)
2675 {
2676         char *pout;
2677         PATHNAME_CONVERT_OUT(path, pout);
2678         return lstat(pout, buf);
2679 }
2680 #endif                          /* ENCAPSULATE_LSTAT */
2681
2682 #ifdef ENCAPSULATE_READLINK
2683 int sys_readlink(const char *path, char *buf, size_t bufsiz)
2684 {
2685         char *pout;
2686         PATHNAME_CONVERT_OUT(path, pout);
2687         /* #### currently we don't do conversions on the incoming data */
2688         return readlink(pout, buf, bufsiz);
2689 }
2690 #endif                          /* ENCAPSULATE_READLINK */
2691
2692 #ifdef ENCAPSULATE_FSTAT
2693 int sys_fstat(int fd, struct stat *buf)
2694 {
2695         return fstat(fd, buf);
2696 }
2697 #endif                          /* ENCAPSULATE_FSTAT */
2698
2699 int sxemacs_stat(const char *path, struct stat *buf)
2700 {
2701         char *pout;
2702         PATHNAME_CONVERT_OUT(path, pout);
2703         return stat(pout, buf);
2704 }
2705
2706 /****************** file-manipulation calls *****************/
2707
2708 #ifdef ENCAPSULATE_CHMOD
2709 int sys_chmod(const char *path, mode_t mode)
2710 {
2711         char *pout;
2712         PATHNAME_CONVERT_OUT(path, pout);
2713         return chmod(pout, mode);
2714 }
2715 #endif                          /* ENCAPSULATE_CHMOD */
2716
2717 #ifdef ENCAPSULATE_CREAT
2718 int sys_creat(const char *path, mode_t mode)
2719 {
2720         char *pout;
2721         PATHNAME_CONVERT_OUT(path, pout);
2722         return creat(pout, mode);
2723 }
2724 #endif                          /* ENCAPSULATE_CREAT */
2725
2726 #ifdef ENCAPSULATE_LINK
2727 int sys_link(const char *existing, const char *new)
2728 {
2729         char *eout, *nout;
2730         PATHNAME_CONVERT_OUT(existing, eout);
2731         PATHNAME_CONVERT_OUT(new, nout);
2732         return link(eout, nout);
2733 }
2734 #endif                          /* ENCAPSULATE_LINK */
2735
2736 #ifdef ENCAPSULATE_RENAME
2737 int sys_rename(const char *old, const char *new)
2738 {
2739         char *oout, *nout;
2740         PATHNAME_CONVERT_OUT(old, oout);
2741         PATHNAME_CONVERT_OUT(new, nout);
2742         return rename(oout, nout);
2743 }
2744 #endif                          /* ENCAPSULATE_RENAME */
2745
2746 #ifdef ENCAPSULATE_SYMLINK
2747 int sys_symlink(const char *name1, const char *name2)
2748 {
2749         char *n1out, *n2out;
2750         PATHNAME_CONVERT_OUT(name1, n1out);
2751         PATHNAME_CONVERT_OUT(name2, n2out);
2752         return symlink(n1out, n2out);
2753 }
2754 #endif                          /* ENCAPSULATE_SYMLINK */
2755
2756 #ifdef ENCAPSULATE_UNLINK
2757 int sys_unlink(const char *path)
2758 {
2759         char *pout;
2760         PATHNAME_CONVERT_OUT(path, pout);
2761         return unlink(pout);
2762 }
2763 #endif                          /* ENCAPSULATE_UNLINK */
2764
2765 #ifdef ENCAPSULATE_EXECVP
2766 int sys_execvp(const char *path, char *const *argv)
2767 {
2768         int i, argc;
2769         char *pout;
2770
2771         PATHNAME_CONVERT_OUT(path, pout);
2772         for (argc = 0; argv[argc]; argc++);
2773         {
2774                 /* c99ified */
2775                 char *new_argv[argc+1];
2776                 for (i = 0; i < argc; i++) {
2777                         PATHNAME_CONVERT_OUT(argv[i], new_argv[i]);
2778                 }
2779                 new_argv[argc] = NULL;
2780                 return execvp(pout, new_argv);
2781         }
2782 }
2783 #endif                          /* ENCAPSULATE_EXECVP */
2784 \f
2785 /************************************************************************/
2786 /*                  Emulations of missing system calls                  */
2787 /************************************************************************/
2788
2789 /***** (these are primarily required for USG, it seems) *****/
2790
2791 #ifndef HAVE_GETCWD
2792 char *getcwd(char *pathname, size_t size)
2793 {
2794         return getwd(pathname);
2795 }
2796 #endif                          /* emulate getcwd */
2797
2798
2799 /*
2800  *      Emulate rename using unlink/link.  Note that this is
2801  *      only partially correct.  Also, doesn't enforce restriction
2802  *      that files be of same type (regular->regular, dir->dir, etc).
2803  */
2804
2805 #ifndef HAVE_RENAME
2806 int rename(const char *from, const char *to)
2807 {
2808         if (access(from, 0) == 0) {
2809                 unlink(to);
2810                 if (link(from, to) == 0)
2811                         if (unlink(from) == 0)
2812                                 return (0);
2813         }
2814         return (-1);
2815 }
2816 #endif                          /* HAVE_RENAME */
2817
2818 #ifdef HPUX
2819 #ifndef HAVE_PERROR
2820
2821 /* HPUX curses library references perror, but as far as we know
2822    it won't be called.  Anyway this definition will do for now.  */
2823
2824 perror(void)
2825 {
2826 }
2827
2828 #endif                          /* not HAVE_PERROR */
2829 #endif                          /* HPUX */
2830
2831 #ifndef HAVE_DUP2
2832
2833 /*
2834  *      Emulate BSD dup2.  First close newd if it already exists.
2835  *      Then, attempt to dup oldd.  If not successful, call dup2 recursively
2836  *      until we are, then close the unsuccessful ones.
2837  */
2838
2839 int dup2(int oldd, int newd)
2840 {
2841         int fd, ret;
2842
2843         sys_close(newd);
2844
2845 #ifdef F_DUPFD
2846         fd = fcntl(oldd, F_DUPFD, newd);
2847         if (fd != newd)
2848                 error("can't dup2 (%i,%i) : %s", oldd, newd, strerror(errno));
2849 #else
2850         fd = dup(old);
2851         if (fd == -1)
2852                 return -1;
2853         if (fd == new)
2854                 return new;
2855         ret = dup2(old, new);
2856         sys_close(fd);
2857         return ret;
2858 #endif                          /*  F_DUPFD */
2859 }
2860
2861 #endif                          /* not HAVE_DUP2 */
2862
2863 /*
2864  *      Gettimeofday.  Simulate as much as possible.  Only accurate
2865  *      to nearest second.  Emacs doesn't use tzp so ignore it for now.
2866  */
2867
2868 #if !defined (HAVE_GETTIMEOFDAY)
2869
2870 int gettimeofday(struct timeval *tp, struct timezone *tzp)
2871 {
2872         extern long time();
2873
2874         tp->tv_sec = time((long *)0);
2875         tp->tv_usec = 0;
2876         if (tzp != 0)
2877                 tzp->tz_minuteswest = -1;
2878         return (0);
2879 }
2880
2881 #endif                          /* !HAVE_GETTIMEOFDAY */
2882
2883 /* No need to encapsulate utime and utimes explicitly because all
2884    access to those functions goes through the following. */
2885
2886 int set_file_times(Lisp_Object path, EMACS_TIME atime, EMACS_TIME mtime)
2887 {
2888 #if defined (HAVE_UTIME)
2889         struct utimbuf utb;
2890         Extbyte *filename;
2891         utb.actime = EMACS_SECS(atime);
2892         utb.modtime = EMACS_SECS(mtime);
2893         LISP_STRING_TO_EXTERNAL(path, filename, Qfile_name);
2894         return utime(filename, &utb);
2895 #elif defined (HAVE_UTIMES)
2896         struct timeval tv[2];
2897         Extbyte *filename;
2898         tv[0] = atime;
2899         tv[1] = mtime;
2900         LISP_STRING_TO_EXTERNAL(path, filename, Qfile_name);
2901         return utimes(filename, tv);
2902 #else
2903         /* No file times setting function available. */
2904         return -1;
2905 #endif
2906 }
2907
2908 /* */
2909
2910 static long ticks_per_second;
2911 static long orig_user_ticks, orig_system_ticks;
2912 EMACS_TIME orig_real_time;
2913
2914 static int process_times_available;
2915
2916 /* Return the relative user and system tick count.  We try to
2917    maintain calculations in terms of integers as long as possible
2918    for increased accuracy. */
2919
2920 static int get_process_times_1(long *user_ticks, long *system_ticks)
2921 {
2922 #if defined (_SC_CLK_TCK) || defined (CLK_TCK)
2923         /* We have the POSIX times() function available. */
2924         struct tms tttt;
2925         times(&tttt);
2926         *user_ticks = (long)tttt.tms_utime;
2927         *system_ticks = (long)tttt.tms_stime;
2928         return 1;
2929 #elif defined (CLOCKS_PER_SEC)
2930         *user_ticks = (long)clock();
2931         *system_ticks = 0;
2932         return 1;
2933 #else
2934         return 0;
2935 #endif
2936 }
2937
2938 void init_process_times_very_early(void)
2939 {
2940 #if defined (_SC_CLK_TCK)
2941         ticks_per_second = sysconf(_SC_CLK_TCK);
2942 #elif defined (CLK_TCK)
2943         ticks_per_second = CLK_TCK;
2944 #elif defined (CLOCKS_PER_SEC)
2945         ticks_per_second = CLOCKS_PER_SEC;
2946 #endif
2947
2948         process_times_available = get_process_times_1(&orig_user_ticks,
2949                                                       &orig_system_ticks);
2950         EMACS_GET_TIME(orig_real_time);
2951 }
2952
2953 /* Return the user and system times used up by this process so far. */
2954 void
2955 get_process_times(double *user_time, double *system_time, double *real_time)
2956 {
2957         EMACS_TIME curr_real_time;
2958         EMACS_TIME elapsed_time;
2959         long curr_user_ticks, curr_system_ticks;
2960
2961         EMACS_GET_TIME(curr_real_time);
2962         EMACS_SUB_TIME(elapsed_time, curr_real_time, orig_real_time);
2963         *real_time = (EMACS_SECS(elapsed_time)
2964                       + ((double)EMACS_USECS(elapsed_time)) / 1000000);
2965         if (get_process_times_1(&curr_user_ticks, &curr_system_ticks)) {
2966                 *user_time = (((double)(curr_user_ticks - orig_user_ticks))
2967                               / ticks_per_second);
2968                 *system_time =
2969                     (((double)(curr_system_ticks - orig_system_ticks))
2970                      / ticks_per_second);
2971         } else {
2972                 /* A lame OS */
2973                 *user_time = *real_time;
2974                 *system_time = 0;
2975         }
2976 }
2977
2978 #ifndef HAVE_RANDOM
2979 #ifdef random
2980 #define HAVE_RANDOM
2981 #endif
2982 #endif
2983
2984 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
2985 # include "ent/ent-gmp.h"
2986 #endif  /* MPZ && (GMP || MP) */
2987
2988 /* Figure out how many bits the system's random number generator uses.
2989    `random' and `lrand48' are assumed to return 31 usable bits.
2990    BSD `rand' returns a 31 bit value but the low order bits are unusable;
2991    so we'll shift it and treat it like the 15-bit USG `rand'.  */
2992
2993 #ifndef RAND_BITS
2994 # ifdef HAVE_RANDOM
2995 #  define RAND_BITS 31
2996 # else                          /* !HAVE_RANDOM */
2997 #  ifdef HAVE_LRAND48
2998 #   define RAND_BITS 31
2999 #   define random lrand48
3000 #  else                         /* !HAVE_LRAND48 */
3001 #   define RAND_BITS 15
3002 #   if RAND_MAX == 32767
3003 #    define random rand
3004 #   else                        /* RAND_MAX != 32767 */
3005 #    if RAND_MAX == 2147483647
3006 #     define random() (rand () >> 16)
3007 #    else                       /* RAND_MAX != 2147483647 */
3008 #     ifdef USG
3009 #      define random rand
3010 #     else
3011 #      define random() (rand () >> 16)
3012 #     endif                     /* !BSD */
3013 #    endif                      /* RAND_MAX != 2147483647 */
3014 #   endif                       /* RAND_MAX != 32767 */
3015 #  endif                        /* !HAVE_LRAND48 */
3016 # endif                         /* !HAVE_RANDOM */
3017 #endif                          /* !RAND_BITS */
3018
3019 void seed_random(long arg);
3020 void seed_random(long arg)
3021 {
3022 #ifdef HAVE_RANDOM
3023         srandom((unsigned int)arg);
3024 #else
3025 # ifdef HAVE_LRAND48
3026         srand48(arg);
3027 # else
3028         srand((unsigned int)arg);
3029 # endif
3030 #endif
3031 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
3032         bigz_random_seed((unsigned long)arg);
3033 #endif
3034 }
3035
3036 /*
3037  * Build a full Emacs-sized word out of whatever we've got.
3038  * This suffices even for a 64-bit architecture with a 15-bit rand.
3039  */
3040 long get_random(void);
3041 long get_random(void)
3042 {
3043         long val = random();
3044 #if INT_VALBITS > RAND_BITS
3045         val = (val << RAND_BITS) ^ random();
3046 #if INT_VALBITS > 2*RAND_BITS
3047         val = (val << RAND_BITS) ^ random();
3048 #if INT_VALBITS > 3*RAND_BITS
3049         val = (val << RAND_BITS) ^ random();
3050 #if INT_VALBITS > 4*RAND_BITS
3051         val = (val << RAND_BITS) ^ random();
3052 #endif                          /* need at least 5 */
3053 #endif                          /* need at least 4 */
3054 #endif                          /* need at least 3 */
3055 #endif                          /* need at least 2 */
3056         return val & (EMACS_INT) ((1UL << INT_VALBITS) - 1);
3057 }
3058 \f
3059 /************************************************************************/
3060 /*               Strings corresponding to defined signals               */
3061 /************************************************************************/
3062
3063 #if !defined (SYS_SIGLIST_DECLARED) && !defined (HAVE_SYS_SIGLIST) && !defined(HAVE_DECL_SYS_SIGLIST)
3064
3065 #ifdef USG
3066 #ifdef AIX
3067 #define SXE_SYS_SIGLIST_DECLARED 1
3068 const char *sys_siglist[NSIG + 1] = {
3069         /* AIX has changed the signals a bit */
3070         DEFER_GETTEXT("bogus signal"),  /* 0 */
3071         DEFER_GETTEXT("hangup"),        /* 1  SIGHUP */
3072         DEFER_GETTEXT("interrupt"),     /* 2  SIGINT */
3073         DEFER_GETTEXT("quit"),  /* 3  SIGQUIT */
3074         DEFER_GETTEXT("illegal instruction"),   /* 4  SIGILL */
3075         DEFER_GETTEXT("trace trap"),    /* 5  SIGTRAP */
3076         DEFER_GETTEXT("IOT instruction"),       /* 6  SIGIOT */
3077         DEFER_GETTEXT("crash likely"),  /* 7  SIGDANGER */
3078         DEFER_GETTEXT("floating point exception"),      /* 8  SIGFPE */
3079         DEFER_GETTEXT("kill"),  /* 9  SIGKILL */
3080         DEFER_GETTEXT("bus error"),     /* 10 SIGBUS */
3081         DEFER_GETTEXT("segmentation violation"),        /* 11 SIGSEGV */
3082         DEFER_GETTEXT("bad argument to system call"),   /* 12 SIGSYS */
3083         DEFER_GETTEXT("write on a pipe with no one to read it"),        /* 13 SIGPIPE */
3084         DEFER_GETTEXT("alarm clock"),   /* 14 SIGALRM */
3085         DEFER_GETTEXT("software termination signal"),   /* 15 SIGTERM */
3086         DEFER_GETTEXT("user defined signal 1"), /* 16 SIGUSR1 */
3087         DEFER_GETTEXT("user defined signal 2"), /* 17 SIGUSR2 */
3088         DEFER_GETTEXT("death of a child"),      /* 18 SIGCLD */
3089         DEFER_GETTEXT("power-fail restart"),    /* 19 SIGPWR */
3090         DEFER_GETTEXT("bogus signal"),  /* 20 */
3091         DEFER_GETTEXT("bogus signal"),  /* 21 */
3092         DEFER_GETTEXT("bogus signal"),  /* 22 */
3093         DEFER_GETTEXT("bogus signal"),  /* 23 */
3094         DEFER_GETTEXT("bogus signal"),  /* 24 */
3095         DEFER_GETTEXT("LAN I/O interrupt"),     /* 25 SIGAIO */
3096         DEFER_GETTEXT("PTY I/O interrupt"),     /* 26 SIGPTY */
3097         DEFER_GETTEXT("I/O intervention required"),     /* 27 SIGIOINT */
3098 #ifdef AIXHFT
3099         DEFER_GETTEXT("HFT grant"),     /* 28 SIGGRANT */
3100         DEFER_GETTEXT("HFT retract"),   /* 29 SIGRETRACT */
3101         DEFER_GETTEXT("HFT sound done"),        /* 30 SIGSOUND */
3102         DEFER_GETTEXT("HFT input ready"),       /* 31 SIGMSG */
3103 #endif
3104         0
3105 };
3106 #else                           /* USG, not AIX */
3107 #define SXE_SYS_SIGLIST_DECLARED 1
3108 const char *sys_siglist[NSIG + 1] = {
3109         DEFER_GETTEXT("bogus signal"),  /* 0 */
3110         DEFER_GETTEXT("hangup"),        /* 1  SIGHUP */
3111         DEFER_GETTEXT("interrupt"),     /* 2  SIGINT */
3112         DEFER_GETTEXT("quit"),  /* 3  SIGQUIT */
3113         DEFER_GETTEXT("illegal instruction"),   /* 4  SIGILL */
3114         DEFER_GETTEXT("trace trap"),    /* 5  SIGTRAP */
3115         DEFER_GETTEXT("IOT instruction"),       /* 6  SIGIOT */
3116         DEFER_GETTEXT("EMT instruction"),       /* 7  SIGEMT */
3117         DEFER_GETTEXT("floating point exception"),      /* 8  SIGFPE */
3118         DEFER_GETTEXT("kill"),  /* 9  SIGKILL */
3119         DEFER_GETTEXT("bus error"),     /* 10 SIGBUS */
3120         DEFER_GETTEXT("segmentation violation"),        /* 11 SIGSEGV */
3121         DEFER_GETTEXT("bad argument to system call"),   /* 12 SIGSYS */
3122         DEFER_GETTEXT("write on a pipe with no one to read it"),        /* 13 SIGPIPE */
3123         DEFER_GETTEXT("alarm clock"),   /* 14 SIGALRM */
3124         DEFER_GETTEXT("software termination signal"),   /* 15 SIGTERM */
3125         DEFER_GETTEXT("user defined signal 1"), /* 16 SIGUSR1 */
3126         DEFER_GETTEXT("user defined signal 2"), /* 17 SIGUSR2 */
3127         DEFER_GETTEXT("death of a child"),      /* 18 SIGCLD */
3128         DEFER_GETTEXT("power-fail restart"),    /* 19 SIGPWR */
3129 #ifdef sun
3130         DEFER_GETTEXT("window size changed"),   /* 20 SIGWINCH */
3131         DEFER_GETTEXT("urgent socket condition"),       /* 21 SIGURG */
3132         DEFER_GETTEXT("pollable event occurred"),       /* 22 SIGPOLL */
3133         DEFER_GETTEXT("stop (cannot be caught or ignored)"),    /*  23 SIGSTOP */
3134         DEFER_GETTEXT("user stop requested from tty"),  /* 24 SIGTSTP */
3135         DEFER_GETTEXT("stopped process has been continued"),    /* 25 SIGCONT */
3136         DEFER_GETTEXT("background tty read attempted"), /* 26 SIGTTIN */
3137         DEFER_GETTEXT("background tty write attempted"),        /* 27 SIGTTOU */
3138         DEFER_GETTEXT("virtual timer expired"), /* 28 SIGVTALRM */
3139         DEFER_GETTEXT("profiling timer expired"),       /* 29 SIGPROF */
3140         DEFER_GETTEXT("exceeded cpu limit"),    /* 30 SIGXCPU */
3141         DEFER_GETTEXT("exceeded file size limit"),      /* 31 SIGXFSZ */
3142         DEFER_GETTEXT("process's lwps are blocked"),    /* 32 SIGWAITING */
3143         DEFER_GETTEXT("special signal used by thread library"), /* 33 SIGLWP */
3144 #ifdef SIGFREEZE
3145         DEFER_GETTEXT("special signal used by CPR"),    /* 34 SIGFREEZE */
3146 #endif
3147 #ifdef SIGTHAW
3148         DEFER_GETTEXT("special signal used by CPR"),    /* 35 SIGTHAW */
3149 #endif
3150 #endif                          /* sun */
3151         0
3152 };
3153 #endif                          /* not AIX */
3154 #endif                          /* USG */
3155 #ifdef DGUX
3156 #define SXE_SYS_SIGLIST_DECLARED 1
3157 const char *sys_siglist[NSIG + 1] = {
3158         DEFER_GETTEXT("null signal"),   /*  0 SIGNULL   */
3159         DEFER_GETTEXT("hangup"),        /*  1 SIGHUP    */
3160         DEFER_GETTEXT("interrupt"),     /*  2 SIGINT    */
3161         DEFER_GETTEXT("quit"),  /*  3 SIGQUIT   */
3162         DEFER_GETTEXT("illegal instruction"),   /*  4 SIGILL    */
3163         DEFER_GETTEXT("trace trap"),    /*  5 SIGTRAP   */
3164         DEFER_GETTEXT("abort termination"),     /*  6 SIGABRT   */
3165         DEFER_GETTEXT("SIGEMT"),        /*  7 SIGEMT    */
3166         DEFER_GETTEXT("floating point exception"),      /*  8 SIGFPE    */
3167         DEFER_GETTEXT("kill"),  /*  9 SIGKILL   */
3168         DEFER_GETTEXT("bus error"),     /* 10 SIGBUS    */
3169         DEFER_GETTEXT("segmentation violation"),        /* 11 SIGSEGV   */
3170         DEFER_GETTEXT("bad argument to system call"),   /* 12 SIGSYS    */
3171         DEFER_GETTEXT("write on a pipe with no reader"),        /* 13 SIGPIPE   */
3172         DEFER_GETTEXT("alarm clock"),   /* 14 SIGALRM   */
3173         DEFER_GETTEXT("software termination signal"),   /* 15 SIGTERM   */
3174         DEFER_GETTEXT("user defined signal 1"), /* 16 SIGUSR1   */
3175         DEFER_GETTEXT("user defined signal 2"), /* 17 SIGUSR2   */
3176         DEFER_GETTEXT("child stopped or terminated"),   /* 18 SIGCLD    */
3177         DEFER_GETTEXT("power-fail restart"),    /* 19 SIGPWR    */
3178         DEFER_GETTEXT("window size changed"),   /* 20 SIGWINCH  */
3179         DEFER_GETTEXT("undefined"),     /* 21           */
3180         DEFER_GETTEXT("pollable event occurred"),       /* 22 SIGPOLL   */
3181         DEFER_GETTEXT("sendable stop signal not from tty"),     /* 23 SIGSTOP   */
3182         DEFER_GETTEXT("stop signal from tty"),  /* 24 SIGSTP    */
3183         DEFER_GETTEXT("continue a stopped process"),    /* 25 SIGCONT   */
3184         DEFER_GETTEXT("attempted background tty read"), /* 26 SIGTTIN   */
3185         DEFER_GETTEXT("attempted background tty write"),        /* 27 SIGTTOU   */
3186         DEFER_GETTEXT("undefined"),     /* 28           */
3187         DEFER_GETTEXT("undefined"),     /* 29           */
3188         DEFER_GETTEXT("undefined"),     /* 30           */
3189         DEFER_GETTEXT("undefined"),     /* 31           */
3190         DEFER_GETTEXT("undefined"),     /* 32           */
3191         DEFER_GETTEXT("socket (TCP/IP) urgent data arrival"),   /* 33 SIGURG    */
3192         DEFER_GETTEXT("I/O is possible"),       /* 34 SIGIO     */
3193         DEFER_GETTEXT("exceeded cpu time limit"),       /* 35 SIGXCPU   */
3194         DEFER_GETTEXT("exceeded file size limit"),      /* 36 SIGXFSZ   */
3195         DEFER_GETTEXT("virtual time alarm"),    /* 37 SIGVTALRM */
3196         DEFER_GETTEXT("profiling time alarm"),  /* 38 SIGPROF   */
3197         DEFER_GETTEXT("undefined"),     /* 39           */
3198         DEFER_GETTEXT("file record locks revoked"),     /* 40 SIGLOST   */
3199         DEFER_GETTEXT("undefined"),     /* 41           */
3200         DEFER_GETTEXT("undefined"),     /* 42           */
3201         DEFER_GETTEXT("undefined"),     /* 43           */
3202         DEFER_GETTEXT("undefined"),     /* 44           */
3203         DEFER_GETTEXT("undefined"),     /* 45           */
3204         DEFER_GETTEXT("undefined"),     /* 46           */
3205         DEFER_GETTEXT("undefined"),     /* 47           */
3206         DEFER_GETTEXT("undefined"),     /* 48           */
3207         DEFER_GETTEXT("undefined"),     /* 49           */
3208         DEFER_GETTEXT("undefined"),     /* 50           */
3209         DEFER_GETTEXT("undefined"),     /* 51           */
3210         DEFER_GETTEXT("undefined"),     /* 52           */
3211         DEFER_GETTEXT("undefined"),     /* 53           */
3212         DEFER_GETTEXT("undefined"),     /* 54           */
3213         DEFER_GETTEXT("undefined"),     /* 55           */
3214         DEFER_GETTEXT("undefined"),     /* 56           */
3215         DEFER_GETTEXT("undefined"),     /* 57           */
3216         DEFER_GETTEXT("undefined"),     /* 58           */
3217         DEFER_GETTEXT("undefined"),     /* 59           */
3218         DEFER_GETTEXT("undefined"),     /* 60           */
3219         DEFER_GETTEXT("undefined"),     /* 61           */
3220         DEFER_GETTEXT("undefined"),     /* 62           */
3221         DEFER_GETTEXT("undefined"),     /* 63           */
3222         DEFER_GETTEXT("notification message in mess. queue"),   /* 64 SIGDGNOTIFY */
3223         0
3224 };
3225 #endif                          /* DGUX */
3226
3227 #endif                          /* ! SYS_SIGLIST_DECLARED && ! HAVE_SYS_SIGLIST */
3228 \f
3229 /************************************************************************/
3230 /*         Directory routines for systems that don't have them          */
3231 /************************************************************************/
3232
3233 #ifdef SYSV_SYSTEM_DIR
3234
3235 #include <dirent.h>
3236
3237 #if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
3238 int closedir(DIR * dirp)
3239 {                               /* stream from opendir */
3240         int rtnval;
3241
3242         rtnval = sys_close(dirp->dd_fd);
3243
3244         /* Some systems (like Solaris) allocate the buffer and the DIR all
3245            in one block.  Why in the world are we freeing this ourselves
3246            anyway?  */
3247 #if ! (defined (sun) && defined (USG5_4))
3248         xfree((char *)dirp->dd_buf);    /* directory block defined in <dirent.h> */
3249 #endif
3250         xfree((char *)dirp);
3251         return (rtnval);
3252 }
3253 #endif                          /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3254 #endif                          /* SYSV_SYSTEM_DIR */
3255
3256 #ifdef NONSYSTEM_DIR_LIBRARY
3257
3258 DIR *opendir(const char *filename)
3259 {                               /* name of directory */
3260         DIR *dirp;              /* -> malloc'ed storage */
3261         int fd;                 /* file descriptor for read */
3262         struct stat sbuf;       /* result of fstat */
3263
3264         fd = sys_open(filename, O_RDONLY);
3265         if (fd < 0)
3266                 return 0;
3267
3268         if (fstat(fd, &sbuf) < 0
3269             || (sbuf.st_mode & S_IFMT) != S_IFDIR
3270             || (dirp = xnew(DIR)) == 0) {
3271                 sys_close(fd);
3272                 return 0;       /* bad luck today */
3273         }
3274
3275         dirp->dd_fd = fd;
3276         dirp->dd_loc = dirp->dd_size = 0;       /* refill needed */
3277
3278         return dirp;
3279 }
3280
3281 void closedir(DIR * dirp)
3282 {                               /* stream from opendir */
3283         sys_close(dirp->dd_fd);
3284         xfree(dirp);
3285 }
3286
3287 #define DIRSIZ  14
3288 struct olddir {
3289         ino_t od_ino;           /* inode */
3290         char od_name[DIRSIZ];   /* filename */
3291 };
3292
3293 static struct direct dir_static;        /* simulated directory contents */
3294
3295 /* ARGUSED */
3296 struct direct *readdir(DIR * dirp)
3297 {                               /* stream from opendir */
3298         struct olddir *dp;      /* -> directory data */
3299
3300         for (;;) {
3301                 if (dirp->dd_loc >= dirp->dd_size)
3302                         dirp->dd_loc = dirp->dd_size = 0;
3303
3304                 if (dirp->dd_size == 0  /* refill buffer */
3305                     && (dirp->dd_size =
3306                         sys_read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3307                         return 0;
3308
3309                 dp = (struct olddir *)&dirp->dd_buf[dirp->dd_loc];
3310                 dirp->dd_loc += sizeof(struct olddir);
3311
3312                 if (dp->od_ino != 0) {  /* not deleted entry */
3313                         dir_static.d_ino = dp->od_ino;
3314                         xstrncpy(dir_static.d_name, dp->od_name, DIRSIZ);
3315                         dir_static.d_name[DIRSIZ] = '\0';
3316                         dir_static.d_namlen = strlen(dir_static.d_name);
3317                         dir_static.d_reclen = sizeof(struct direct)
3318                             - MAXNAMLEN + 3
3319                             + dir_static.d_namlen - dir_static.d_namlen % 4;
3320                         return &dir_static;     /* -> simulated structure */
3321                 }
3322         }
3323 }
3324
3325 #endif                          /* NONSYSTEM_DIR_LIBRARY */
3326 \f
3327 /* mkdir and rmdir functions, for systems which don't have them.  */
3328
3329 #ifndef HAVE_MKDIR
3330 /*
3331  * Written by Robert Rother, Mariah Corporation, August 1985.
3332  *
3333  * If you want it, it's yours.  All I ask in return is that if you
3334  * figure out how to do this in a Bourne Shell script you send me
3335  * a copy.
3336  *                                      sdcsvax!rmr or rmr@uscd
3337  *
3338  * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3339  * subroutine.  11Mar86; hoptoad!gnu
3340  *
3341  * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3342  * subroutine didn't return EEXIST.  It does now.
3343  */
3344
3345 /*
3346  * Make a directory.
3347  */
3348 #ifdef MKDIR_PROTOTYPE
3349 MKDIR_PROTOTYPE
3350 #else
3351 int mkdir(const char *dpath, int dmode)
3352 #endif
3353 {
3354         int cpid, status, fd;
3355         struct stat statbuf;
3356
3357         if (stat(dpath, &statbuf) == 0) {       /* we do want stat() here */
3358                 errno = EEXIST; /* Stat worked, so it already exists */
3359                 return -1;
3360         }
3361
3362         /* If stat fails for a reason other than non-existence, return error */
3363         if (errno != ENOENT)
3364                 return -1;
3365
3366         synch_process_alive = 1;
3367         switch (cpid = fork()) {
3368
3369         case -1:                /* Error in fork() */
3370                 return -1;      /* Errno is set already */
3371
3372         case 0:         /* Child process */
3373                 {
3374                         /*
3375                          * Cheap hack to set mode of new directory.  Since this
3376                          * child process is going away anyway, we zap its umask.
3377                          * ####, this won't suffice to set SUID, SGID, etc. on this
3378                          * directory.  Does anybody care?
3379                          */
3380                         status = umask(0);      /* Get current umask */
3381                         status = umask(status | (0777 & ~dmode));       /* Set for mkdir */
3382                         fd = sys_open("/dev/null", O_RDWR);
3383                         if (fd >= 0) {
3384                                 if (fd != STDIN_FILENO)
3385                                         dup2(fd, STDIN_FILENO);
3386                                 if (fd != STDOUT_FILENO)
3387                                         dup2(fd, STDOUT_FILENO);
3388                                 if (fd != STDERR_FILENO)
3389                                         dup2(fd, STDERR_FILENO);
3390                         }
3391                         execl("/bin/mkdir", "mkdir", dpath, (char *)0);
3392                         _exit(-1);      /* Can't exec /bin/mkdir */
3393                 }
3394
3395         default:                /* Parent process */
3396                 wait_for_termination(cpid);
3397         }
3398
3399         if (synch_process_death != 0 || synch_process_retcode != 0) {
3400                 errno = EIO;    /* We don't know why, but */
3401                 return -1;      /* /bin/mkdir failed */
3402         }
3403
3404         return 0;
3405 }
3406 #endif                          /* not HAVE_MKDIR */
3407
3408 #ifndef HAVE_RMDIR
3409 int rmdir(const char *dpath)
3410 {
3411         int cpid, status, fd;
3412         struct stat statbuf;
3413
3414         if (stat(dpath, &statbuf) != 0) {       /* we do want stat() here */
3415                 /* Stat just set errno.  We don't have to */
3416                 return -1;
3417         }
3418
3419         synch_process_alive = 1;
3420         switch (cpid = fork()) {
3421
3422         case -1:                /* Error in fork() */
3423                 return (-1);    /* Errno is set already */
3424
3425         case 0:         /* Child process */
3426                 fd = sys_open("/dev/null", O_RDWR);
3427                 if (fd >= 0) {
3428                         if (fd != STDIN_FILENO)
3429                                 dup2(fd, STDIN_FILENO);
3430                         if (fd != STDOUT_FILENO)
3431                                 dup2(fd, STDOUT_FILENO);
3432                         if (fd != STDERR_FILENO)
3433                                 dup2(fd, STDERR_FILENO);
3434                 }
3435                 execl("/bin/rmdir", "rmdir", dpath, (char *)0);
3436                 _exit(-1);      /* Can't exec /bin/mkdir */
3437
3438         default:                /* Parent process */
3439                 wait_for_termination(cpid);
3440         }
3441
3442         if (synch_process_death != 0 || synch_process_retcode != 0) {
3443                 errno = EIO;    /* We don't know why, but */
3444                 return -1;      /* /bin/rmdir failed */
3445         }
3446
3447         return 0;
3448 }
3449 #endif                          /* !HAVE_RMDIR */
3450 \f
3451 /************************************************************************/
3452 /*                            Misc. SunOS crap                          */
3453 /************************************************************************/
3454
3455 #ifdef USE_DL_STUBS
3456
3457 /* These are included on Sunos 4.1 when we do not use shared libraries.
3458    X11 libraries may refer to these functions but (we hope) do not
3459    actually call them.  */
3460
3461 void *dlopen(void)
3462 {
3463         return 0;
3464 }
3465
3466 void *dlsym(void)
3467 {
3468         return 0;
3469 }
3470
3471 int dlclose(void)
3472 {
3473         return -1;
3474 }
3475
3476 #endif                          /* USE_DL_STUBS */
3477
3478 \f
3479 /* big dirname magic */
3480
3481 #if !defined(HAVE_DIRNAME)
3482 /* some coreutils borrows here */
3483 void
3484 x__dirname(restrict char *res, const char *file, size_t len);
3485 {
3486         /* assumes res is malloc'd of size LEN (and >= xstrlen(file)) */
3487         size_t file_len = xstrlen(file);
3488         size_t offs = x__dirlen(file, file_len);
3489         int append_dot = (offs == 0);
3490
3491         xmemcpy(dir, file, offs);
3492         if (append_dot)
3493                 res[offs++] = '.';
3494         res[offs] = '\0';
3495         return res;
3496 }
3497 #endif  /* !HAVE_DIRNAME */
3498
3499 /* sysdep.c ends here */