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