Initial git import
[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
2106                                 if (!strchr(fqdn, '.')) {
2107                                         /* We still don't have a fully qualified domain name.
2108                                            Try to find one in the list of alternate names */
2109                                         char **alias = hp->h_aliases;
2110                                         while (*alias && !strchr(*alias, '.'))
2111                                                 alias++;
2112                                         if (*alias)
2113                                                 fqdn = *alias;
2114                                 }
2115                                 hostname = (char *)alloca(strlen(fqdn) + 1);
2116                                 strcpy(hostname, fqdn);
2117                         }
2118 #  else                         /* !(HAVE_GETADDRINFO && HAVE_GETNAMEINFO) */
2119                         struct addrinfo hints, *res;
2120
2121                         xzero(hints);
2122                         hints.ai_flags = AI_CANONNAME;
2123 #ifdef IPV6_CANONICALIZE
2124                         hints.ai_family = AF_UNSPEC;
2125 #else
2126                         hints.ai_family = PF_INET;
2127 #endif
2128                         hints.ai_socktype = SOCK_STREAM;
2129                         hints.ai_protocol = 0;
2130                         if (!getaddrinfo(hostname, NULL, &hints, &res)) {
2131                                 hostname =
2132                                     (char *)alloca(strlen(res->ai_canonname) +
2133                                                    1);
2134                                 strcpy(hostname, res->ai_canonname);
2135
2136                                 freeaddrinfo(res);
2137                         }
2138 #  endif                        /* !(HAVE_GETADDRINFO && HAVE_GETNAMEINFO) */
2139                 }
2140 # endif                         /* HAVE_SOCKETS */
2141         Vsystem_name = build_string(hostname);
2142 #endif                          /* HAVE_GETHOSTNAME  */
2143         {
2144                 Bufbyte *p;
2145                 Bytecount i;
2146
2147                 for (i = 0, p = XSTRING_DATA(Vsystem_name);
2148                      i < XSTRING_LENGTH(Vsystem_name); i++, p++) {
2149                         if (*p == ' ' || *p == '\t')
2150                                 *p = '-';
2151                 }
2152         }
2153 }
2154 \f
2155 /************************************************************************/
2156 /*                        Emulation of select()                         */
2157 /************************************************************************/
2158
2159 #ifndef HAVE_SELECT
2160
2161 ERROR:XEmacs requires a working select().
2162 #endif                          /* not HAVE_SELECT */
2163 \f/************************************************************************/
2164 /*                      Emulation of signal stuff                       */
2165 /************************************************************************/
2166 /* BSD 4.1 crap deleted.  4.2 was released in 1983, for God's sake!  I
2167    can't imagine that anyone is actually running that OS any more.
2168    You can't use X under it (I think) because there's no select().
2169    Anyway, the signal stuff has all been changed.  If someone wants to
2170    get this stuff working again, look in the FSF Emacs sources. */
2171 /* POSIX signals support - DJB */
2172 #ifdef HAVE_SIGPROCMASK
2173 /* #### Is there any reason this is static global rather than local? */
2174 static struct sigaction new_action, old_action;
2175
2176 signal_handler_t sys_do_signal(int signal_number, signal_handler_t action)
2177 {
2178 #if 0
2179
2180         /* XEmacs works better if system calls are *not* restarted.
2181            This allows C-g to interrupt reads and writes, on most systems.
2182
2183            #### Another possibility is to just longjmp() out of the signal
2184            handler.  According to W.R. Stevens, this should be OK on all
2185            systems.  However, I don't want to deal with the potential
2186            evil ramifications of this at this point. */
2187
2188 #ifdef DGUX
2189         /* This gets us restartable system calls for efficiency.
2190            The "else" code will work as well. */
2191         return (berk_signal(signal_number, action));
2192 #else
2193         sigemptyset(&new_action.sa_mask);
2194         new_action.sa_handler = action;
2195 #if defined (SA_RESTART)
2196         /* Emacs mostly works better with restartable system services. If this
2197          * flag exists, we probably want to turn it on here.
2198          */
2199         new_action.sa_flags = SA_RESTART;
2200 #else
2201         new_action.sa_flags = 0;
2202 #endif
2203         sigaction(signal_number, &new_action, &old_action);
2204         return (old_action.sa_handler);
2205 #endif                          /* DGUX */
2206
2207 #else                           /* not 0 */
2208
2209         sigemptyset(&new_action.sa_mask);
2210         new_action.sa_handler = action;
2211 #if defined (SA_INTERRUPT)      /* don't restart system calls, under SunOS */
2212         new_action.sa_flags = SA_INTERRUPT;
2213 #else
2214         new_action.sa_flags = 0;
2215 #endif
2216         sigaction(signal_number, &new_action, &old_action);
2217         return (signal_handler_t) (old_action.sa_handler);
2218
2219 #endif                          /* not 0 */
2220 }
2221
2222 #elif defined (HAVE_SIGBLOCK)
2223 /* We use sigvec() rather than signal() if we have it, because
2224    it lets us specify interruptible system calls. */
2225 signal_handler_t sys_do_signal(int signal_number, signal_handler_t action)
2226 {
2227         struct sigvec vec, ovec;
2228
2229         vec.sv_handler = action;
2230         vec.sv_mask = 0;
2231 #ifdef SV_INTERRUPT             /* don't restart system calls */
2232         vec.sv_flags = SV_INTERRUPT;
2233 #else
2234         vec.sv_flags = 0;
2235 #endif
2236
2237         sigvec(signal_number, &vec, &ovec);
2238
2239         return (ovec.sv_handler);
2240 }
2241
2242 #endif                          /* HAVE_SIGBLOCK (HAVE_SIGPROCMASK) */
2243 \f
2244 /************************************************************************/
2245 /*           Emulation of strerror() and errno support                  */
2246 /************************************************************************/
2247
2248 #ifndef HAVE_STRERROR
2249
2250 #if !defined(NeXT) && !defined(__alpha) && !defined(MACH) && !defined(LINUX) && !defined(IRIX) && !defined(__NetBSD__)
2251 /* Linux added here by Raymond L. Toy <toy@alydar.crd.ge.com> for XEmacs. */
2252 /* Irix added here by gparker@sni-usa.com for XEmacs. */
2253 /* NetBSD added here by James R Grinter <jrg@doc.ic.ac.uk> for XEmacs */
2254 extern const char *sys_errlist[];
2255 extern int sys_nerr;
2256 #endif
2257
2258 #ifdef __NetBSD__
2259 extern char *sys_errlist[];
2260 extern int sys_nerr;
2261 #endif
2262
2263 const char *strerror(int errnum)
2264 {
2265         if (errnum >= 0 && errnum < sys_nerr)
2266                 return sys_errlist[errnum];
2267         return ((const char *)GETTEXT("Unknown error"));
2268 }
2269
2270 #endif                          /* ! HAVE_STRERROR */
2271 \f
2272 /************************************************************************/
2273 /*                    Encapsulations of system calls                    */
2274 /************************************************************************/
2275
2276 #define PATHNAME_CONVERT_OUT(path, pathout)             \
2277         TO_EXTERNAL_FORMAT(C_STRING, (path),            \
2278                            C_STRING_ALLOCA, (pathout),  \
2279                            Qfile_name);
2280
2281 /***************** low-level calls ****************/
2282
2283 /*
2284  *      On USG systems the system calls are INTERRUPTIBLE by signals
2285  *      that the user program has elected to catch.  Thus the system call
2286  *      must be retried in these cases.  To handle this without massive
2287  *      changes in the source code, we remap the standard system call names
2288  *      to names for our own functions in sysdep.c that do the system call
2289  *      with retries.  Actually, for portability reasons, it is good
2290  *      programming practice, as this example shows, to limit all actual
2291  *      system calls to a single occurrence in the source.  Sure, this
2292  *      adds an extra level of function call overhead but it is almost
2293  *      always negligible.   Fred Fish, Unisoft Systems Inc.
2294  */
2295
2296 /* Ben sez: read Dick Gabriel's essay about the Worse Is Better
2297    approach to programming and its connection to the silly
2298    interruptible-system-call business.  To find it, look on
2299    Jamie's home page (http://www.jwz.org/worse-is-better.html). */
2300
2301 #ifdef ENCAPSULATE_OPEN
2302 int sys_open(const char *path, int oflag, ...)
2303 {
2304         int mode;
2305         va_list ap;
2306         char *pout;
2307
2308         va_start(ap, oflag);
2309         mode = va_arg(ap, int);
2310         va_end(ap);
2311
2312         PATHNAME_CONVERT_OUT(path, pout);
2313
2314 #ifdef INTERRUPTIBLE_OPEN
2315         {
2316                 int rtnval;
2317                 while ((rtnval = open(pout, oflag, mode)) == -1
2318                        && (errno == EINTR))
2319                         DO_NOTHING;
2320                 return rtnval;
2321         }
2322 #else
2323         return open(pout, oflag, mode);
2324 #endif
2325 }
2326 #endif                          /* ENCAPSULATE_OPEN */
2327
2328 /* Like sys_open, only when open() is interrupted by EINTR, check for
2329    QUIT.  This allows the callers of this function to be interrupted
2330    with C-g when, say, reading from named pipes.  However, this should
2331    be used with caution, as it can GC.
2332
2333    This function will not function as expected on systems where open()
2334    is not interrupted by C-g.  However, the worst that can happen is
2335    the fallback to simple open().  */
2336 int interruptible_open(const char *path, int oflag, int mode)
2337 {
2338         /* This function can GC */
2339         char *nrout;
2340
2341         PATHNAME_CONVERT_OUT(path, nrout);
2342
2343         for (;;) {
2344                 int rtnval = open(nrout, oflag, mode);
2345                 if (!(rtnval == -1 && errno == EINTR))
2346                         return rtnval;
2347                 /* open() was interrupted.  Was QUIT responsible?  */
2348                 QUIT;
2349         }
2350 }
2351
2352 #ifdef ENCAPSULATE_CLOSE
2353 int sys_close(int filedes)
2354 {
2355 #ifdef INTERRUPTIBLE_CLOSE
2356         int did_retry = 0;
2357         REGISTER int rtnval;
2358
2359         while ((rtnval = close(filedes)) == -1 && (errno == EINTR))
2360                 did_retry = 1;
2361
2362         /* If close is interrupted SunOS 4.1 may or may not have closed the
2363            file descriptor.  If it did the second close will fail with
2364            errno = EBADF.  That means we have succeeded.  */
2365         if (rtnval == -1 && did_retry && errno == EBADF)
2366                 return 0;
2367
2368         return rtnval;
2369 #else
2370         return close(filedes);
2371 #endif
2372 }
2373 #endif                          /* ENCAPSULATE_CLOSE */
2374
2375 ssize_t sys_read_1(int fildes, void *buf, size_t nbyte, int allow_quit)
2376 {
2377         ssize_t rtnval;
2378
2379         /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */
2380         while ((rtnval = read(fildes, buf, nbyte)) == -1 && (errno == EINTR)) {
2381                 if (allow_quit)
2382                         REALLY_QUIT;
2383         }
2384         return rtnval;
2385 }
2386
2387 #ifdef ENCAPSULATE_READ
2388 ssize_t sys_read(int fildes, void *buf, size_t nbyte)
2389 {
2390         return sys_read_1(fildes, buf, nbyte, 0);
2391 }
2392 #endif                          /* ENCAPSULATE_READ */
2393
2394 ssize_t sys_write_1(int fildes, const void *buf, size_t nbyte, int allow_quit)
2395 {
2396         ssize_t bytes_written = 0;
2397         const char *b = (const char *)buf;
2398
2399         /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */
2400         while (nbyte > 0) {
2401                 ssize_t rtnval = write(fildes, b, nbyte);
2402
2403                 if (allow_quit)
2404                         REALLY_QUIT;
2405
2406                 if (rtnval == -1) {
2407                         if (errno == EINTR)
2408                                 continue;
2409                         else
2410                                 return bytes_written ? bytes_written : -1;
2411                 }
2412                 b += rtnval;
2413                 nbyte -= rtnval;
2414                 bytes_written += rtnval;
2415         }
2416         return bytes_written;
2417 }
2418
2419 #ifdef ENCAPSULATE_WRITE
2420 ssize_t sys_write(int fildes, const void *buf, size_t nbyte)
2421 {
2422         return sys_write_1(fildes, buf, nbyte, 0);
2423 }
2424 #endif                          /* ENCAPSULATE_WRITE */
2425
2426 /**************** stdio calls ****************/
2427
2428 /* There is at least some evidence that the stdio calls are interruptible
2429    just like the normal system calls, at least on some systems.  In any
2430    case, it doesn't hurt to encapsulate them. */
2431
2432 /* #### Should also encapsulate fflush().
2433    #### Should conceivably encapsulate getchar() etc.  What a pain! */
2434
2435 #ifdef ENCAPSULATE_FOPEN
2436 FILE *sys_fopen(const char *path, const char *type)
2437 {
2438         char *pout;
2439
2440         PATHNAME_CONVERT_OUT(path, pout);
2441 #if defined (INTERRUPTIBLE_OPEN)
2442         {
2443                 FILE *rtnval;
2444                 while (!(rtnval = fopen(pout, type)) && (errno == EINTR))
2445                         DO_NOTHING;
2446                 return rtnval;
2447         }
2448 #else
2449         return fopen(pout, type);
2450 #endif
2451 }
2452 #endif                          /* ENCAPSULATE_FOPEN */
2453
2454 #ifdef ENCAPSULATE_FCLOSE
2455 int sys_fclose(FILE * stream)
2456 {
2457 #ifdef INTERRUPTIBLE_CLOSE
2458         int rtnval;
2459
2460         while ((rtnval = fclose(stream)) == EOF && (errno == EINTR)) ;
2461         return rtnval;
2462 #else
2463         return fclose(stream);
2464 #endif
2465 }
2466 #endif                          /* ENCAPSULATE_FCLOSE */
2467
2468 #ifdef ENCAPSULATE_FREAD
2469 size_t sys_fread(void *ptr, size_t size, size_t nitem, FILE * stream)
2470 {
2471 #ifdef INTERRUPTIBLE_IO
2472         size_t rtnval;
2473         size_t items_read = 0;
2474         char *b = (char *)ptr;
2475
2476         while (nitem > 0) {
2477                 rtnval = fread(b, size, nitem, stream);
2478                 if (rtnval == 0) {
2479                         if (ferror(stream) && errno == EINTR)
2480                                 continue;
2481                         else
2482                                 return items_read;
2483                 }
2484                 b += size * rtnval;
2485                 nitem -= rtnval;
2486                 items_read += rtnval;
2487         }
2488         return (items_read);
2489 #else
2490         return fread(ptr, size, nitem, stream);
2491 #endif
2492 }
2493 #endif                          /* ENCAPSULATE_FREAD */
2494
2495 #ifdef ENCAPSULATE_FWRITE
2496 size_t sys_fwrite(const void *ptr, size_t size, size_t nitem, FILE * stream)
2497 {
2498 #ifdef INTERRUPTIBLE_IO
2499         size_t rtnval;
2500         size_t items_written = 0;
2501         const char *b = (const char *)ptr;
2502
2503         while (nitem > 0) {
2504                 rtnval = fwrite(b, size, nitem, stream);
2505                 if (rtnval == 0) {
2506                         if (ferror(stream) && errno == EINTR)
2507                                 continue;
2508                         else
2509                                 return items_written;
2510                 }
2511                 b += size * rtnval;
2512                 nitem -= rtnval;
2513                 items_written += rtnval;
2514         }
2515         return (items_written);
2516 #else
2517         return fwrite(ptr, size, nitem, stream);
2518 #endif
2519 }
2520 #endif                          /* ENCAPSULATE_FWRITE */
2521
2522 /********************* directory calls *******************/
2523
2524 #ifdef ENCAPSULATE_CHDIR
2525 int sys_chdir(const char *path)
2526 {
2527         char *pout;
2528         PATHNAME_CONVERT_OUT(path, pout);
2529         return chdir(pout);
2530 }
2531 #endif                          /* ENCAPSULATE_CHDIR */
2532
2533 #ifdef ENCAPSULATE_MKDIR
2534 int sys_mkdir(const char *path, mode_t mode)
2535 {
2536         char *pout;
2537         PATHNAME_CONVERT_OUT(path, pout);
2538         return mkdir(pout, mode);
2539 }
2540 #endif                          /* ENCAPSULATE_MKDIR */
2541
2542 #ifdef ENCAPSULATE_OPENDIR
2543 DIR *sys_opendir(const char *filename)
2544 {
2545         DIR *rtnval;
2546         char *fout;
2547         PATHNAME_CONVERT_OUT(filename, fout);
2548
2549         while (!(rtnval = opendir(fout))
2550                && (errno == EINTR)) ;
2551         return rtnval;
2552 }
2553 #endif                          /* ENCAPSULATE_OPENDIR */
2554
2555 #ifdef ENCAPSULATE_READDIR
2556 DIRENTRY *sys_readdir(DIR * dirp)
2557 {
2558         DIRENTRY *rtnval;
2559
2560         /* Apparently setting errno is necessary on some systems?
2561            Maybe readdir() doesn't always set errno ?! */
2562         while (!(errno = 0, rtnval = readdir(dirp))
2563                && (errno == EINTR)) ;
2564 #ifndef MULE
2565         return rtnval;
2566 #else                           /* MULE */
2567         if (rtnval == NULL)     /* End of directory */
2568                 return NULL;
2569         {
2570                 const Extbyte *const external_name =
2571                     (const Extbyte *)rtnval->d_name;
2572                 Extcount external_len = strlen(rtnval->d_name);
2573                 const Bufbyte *internal_name;
2574                 Bytecount internal_len;
2575
2576                 TO_INTERNAL_FORMAT(DATA, (external_name, external_len),
2577                                    ALLOCA, (internal_name, internal_len),
2578                                    Qfile_name);
2579
2580                 /* check for common case of ASCII filename */
2581                 if (internal_len == external_len &&
2582                     !memcmp(external_name, internal_name, internal_len))
2583                         return rtnval;
2584
2585                 {               /* Non-ASCII filename */
2586                         static Bufbyte_dynarr *internal_DIRENTRY;
2587                         if (!internal_DIRENTRY)
2588                                 internal_DIRENTRY = Dynarr_new(Bufbyte);
2589                         else
2590                                 Dynarr_reset(internal_DIRENTRY);
2591
2592                         Dynarr_add_many(internal_DIRENTRY, (Bufbyte *) rtnval,
2593                                         offsetof(DIRENTRY, d_name));
2594
2595                         Dynarr_add_many(internal_DIRENTRY, internal_name,
2596                                         internal_len);
2597                         Dynarr_add(internal_DIRENTRY, '\0');    /* NUL-terminate */
2598                         return (DIRENTRY *) Dynarr_atp(internal_DIRENTRY, 0);
2599                 }
2600         }
2601 #endif                          /* MULE */
2602 }
2603 #endif                          /* ENCAPSULATE_READDIR */
2604
2605 #ifdef ENCAPSULATE_CLOSEDIR
2606 int sys_closedir(DIR * dirp)
2607 {
2608         int rtnval;
2609
2610         while ((rtnval = closedir(dirp)) == -1 && (errno == EINTR)) ;
2611         return rtnval;
2612 }
2613 #endif                          /* ENCAPSULATE_CLOSEDIR */
2614
2615 #ifdef ENCAPSULATE_RMDIR
2616 int sys_rmdir(const char *path)
2617 {
2618         char *pout;
2619         PATHNAME_CONVERT_OUT(path, pout);
2620         return rmdir(pout);
2621 }
2622 #endif                          /* ENCAPSULATE_RMDIR */
2623
2624 /***************** file-information calls ******************/
2625
2626 #ifdef ENCAPSULATE_ACCESS
2627 int sys_access(const char *path, int mode)
2628 {
2629         char *pout;
2630         PATHNAME_CONVERT_OUT(path, pout);
2631         return access(pout, mode);
2632 }
2633 #endif                          /* ENCAPSULATE_ACCESS */
2634
2635 #ifdef HAVE_EACCESS
2636 #ifdef ENCAPSULATE_EACCESS
2637 int sys_eaccess(const char *path, int mode)
2638 {
2639         char *pout;
2640         PATHNAME_CONVERT_OUT(path, pout);
2641         return eaccess(pout, mode);
2642 }
2643 #endif                          /* ENCAPSULATE_EACCESS */
2644 #endif                          /* HAVE_EACCESS */
2645
2646 #ifdef ENCAPSULATE_LSTAT
2647 int sys_lstat(const char *path, struct stat *buf)
2648 {
2649         char *pout;
2650         PATHNAME_CONVERT_OUT(path, pout);
2651         return lstat(pout, buf);
2652 }
2653 #endif                          /* ENCAPSULATE_LSTAT */
2654
2655 #ifdef ENCAPSULATE_READLINK
2656 int sys_readlink(const char *path, char *buf, size_t bufsiz)
2657 {
2658         char *pout;
2659         PATHNAME_CONVERT_OUT(path, pout);
2660         /* #### currently we don't do conversions on the incoming data */
2661         return readlink(pout, buf, bufsiz);
2662 }
2663 #endif                          /* ENCAPSULATE_READLINK */
2664
2665 #ifdef ENCAPSULATE_FSTAT
2666 int sys_fstat(int fd, struct stat *buf)
2667 {
2668         return fstat(fd, buf);
2669 }
2670 #endif                          /* ENCAPSULATE_FSTAT */
2671
2672 int sxemacs_stat(const char *path, struct stat *buf)
2673 {
2674         char *pout;
2675         PATHNAME_CONVERT_OUT(path, pout);
2676         return stat(pout, buf);
2677 }
2678
2679 /****************** file-manipulation calls *****************/
2680
2681 #ifdef ENCAPSULATE_CHMOD
2682 int sys_chmod(const char *path, mode_t mode)
2683 {
2684         char *pout;
2685         PATHNAME_CONVERT_OUT(path, pout);
2686         return chmod(pout, mode);
2687 }
2688 #endif                          /* ENCAPSULATE_CHMOD */
2689
2690 #ifdef ENCAPSULATE_CREAT
2691 int sys_creat(const char *path, mode_t mode)
2692 {
2693         char *pout;
2694         PATHNAME_CONVERT_OUT(path, pout);
2695         return creat(pout, mode);
2696 }
2697 #endif                          /* ENCAPSULATE_CREAT */
2698
2699 #ifdef ENCAPSULATE_LINK
2700 int sys_link(const char *existing, const char *new)
2701 {
2702         char *eout, *nout;
2703         PATHNAME_CONVERT_OUT(existing, eout);
2704         PATHNAME_CONVERT_OUT(new, nout);
2705         return link(eout, nout);
2706 }
2707 #endif                          /* ENCAPSULATE_LINK */
2708
2709 #ifdef ENCAPSULATE_RENAME
2710 int sys_rename(const char *old, const char *new)
2711 {
2712         char *oout, *nout;
2713         PATHNAME_CONVERT_OUT(old, oout);
2714         PATHNAME_CONVERT_OUT(new, nout);
2715         return rename(oout, nout);
2716 }
2717 #endif                          /* ENCAPSULATE_RENAME */
2718
2719 #ifdef ENCAPSULATE_SYMLINK
2720 int sys_symlink(const char *name1, const char *name2)
2721 {
2722         char *n1out, *n2out;
2723         PATHNAME_CONVERT_OUT(name1, n1out);
2724         PATHNAME_CONVERT_OUT(name2, n2out);
2725         return symlink(n1out, n2out);
2726 }
2727 #endif                          /* ENCAPSULATE_SYMLINK */
2728
2729 #ifdef ENCAPSULATE_UNLINK
2730 int sys_unlink(const char *path)
2731 {
2732         char *pout;
2733         PATHNAME_CONVERT_OUT(path, pout);
2734         return unlink(pout);
2735 }
2736 #endif                          /* ENCAPSULATE_UNLINK */
2737
2738 #ifdef ENCAPSULATE_EXECVP
2739 int sys_execvp(const char *path, char *const *argv)
2740 {
2741         int i, argc;
2742         char *pout;
2743
2744         PATHNAME_CONVERT_OUT(path, pout);
2745         for (argc = 0; argv[argc]; argc++);
2746         {
2747                 /* c99ified */
2748                 char *new_argv[argc+1];
2749                 for (i = 0; i < argc; i++) {
2750                         PATHNAME_CONVERT_OUT(argv[i], new_argv[i]);
2751                 }
2752                 new_argv[argc] = NULL;
2753                 return execvp(pout, new_argv);
2754         }
2755 }
2756 #endif                          /* ENCAPSULATE_EXECVP */
2757 \f
2758 /************************************************************************/
2759 /*                  Emulations of missing system calls                  */
2760 /************************************************************************/
2761
2762 /***** (these are primarily required for USG, it seems) *****/
2763
2764 #ifndef HAVE_GETCWD
2765 char *getcwd(char *pathname, size_t size)
2766 {
2767         return getwd(pathname);
2768 }
2769 #endif                          /* emulate getcwd */
2770
2771
2772 /*
2773  *      Emulate rename using unlink/link.  Note that this is
2774  *      only partially correct.  Also, doesn't enforce restriction
2775  *      that files be of same type (regular->regular, dir->dir, etc).
2776  */
2777
2778 #ifndef HAVE_RENAME
2779 int rename(const char *from, const char *to)
2780 {
2781         if (access(from, 0) == 0) {
2782                 unlink(to);
2783                 if (link(from, to) == 0)
2784                         if (unlink(from) == 0)
2785                                 return (0);
2786         }
2787         return (-1);
2788 }
2789 #endif                          /* HAVE_RENAME */
2790
2791 #ifdef HPUX
2792 #ifndef HAVE_PERROR
2793
2794 /* HPUX curses library references perror, but as far as we know
2795    it won't be called.  Anyway this definition will do for now.  */
2796
2797 perror(void)
2798 {
2799 }
2800
2801 #endif                          /* not HAVE_PERROR */
2802 #endif                          /* HPUX */
2803
2804 #ifndef HAVE_DUP2
2805
2806 /*
2807  *      Emulate BSD dup2.  First close newd if it already exists.
2808  *      Then, attempt to dup oldd.  If not successful, call dup2 recursively
2809  *      until we are, then close the unsuccessful ones.
2810  */
2811
2812 int dup2(int oldd, int newd)
2813 {
2814         int fd, ret;
2815
2816         sys_close(newd);
2817
2818 #ifdef F_DUPFD
2819         fd = fcntl(oldd, F_DUPFD, newd);
2820         if (fd != newd)
2821                 error("can't dup2 (%i,%i) : %s", oldd, newd, strerror(errno));
2822 #else
2823         fd = dup(old);
2824         if (fd == -1)
2825                 return -1;
2826         if (fd == new)
2827                 return new;
2828         ret = dup2(old, new);
2829         sys_close(fd);
2830         return ret;
2831 #endif                          /*  F_DUPFD */
2832 }
2833
2834 #endif                          /* not HAVE_DUP2 */
2835
2836 /*
2837  *      Gettimeofday.  Simulate as much as possible.  Only accurate
2838  *      to nearest second.  Emacs doesn't use tzp so ignore it for now.
2839  */
2840
2841 #if !defined (HAVE_GETTIMEOFDAY)
2842
2843 int gettimeofday(struct timeval *tp, struct timezone *tzp)
2844 {
2845         extern long time();
2846
2847         tp->tv_sec = time((long *)0);
2848         tp->tv_usec = 0;
2849         if (tzp != 0)
2850                 tzp->tz_minuteswest = -1;
2851         return (0);
2852 }
2853
2854 #endif                          /* !HAVE_GETTIMEOFDAY */
2855
2856 /* No need to encapsulate utime and utimes explicitly because all
2857    access to those functions goes through the following. */
2858
2859 int set_file_times(Lisp_Object path, EMACS_TIME atime, EMACS_TIME mtime)
2860 {
2861 #if defined (HAVE_UTIME)
2862         struct utimbuf utb;
2863         Extbyte *filename;
2864         utb.actime = EMACS_SECS(atime);
2865         utb.modtime = EMACS_SECS(mtime);
2866         LISP_STRING_TO_EXTERNAL(path, filename, Qfile_name);
2867         return utime(filename, &utb);
2868 #elif defined (HAVE_UTIMES)
2869         struct timeval tv[2];
2870         Extbyte *filename;
2871         tv[0] = atime;
2872         tv[1] = mtime;
2873         LISP_STRING_TO_EXTERNAL(path, filename, Qfile_name);
2874         return utimes(filename, tv);
2875 #else
2876         /* No file times setting function available. */
2877         return -1;
2878 #endif
2879 }
2880
2881 /* */
2882
2883 static long ticks_per_second;
2884 static long orig_user_ticks, orig_system_ticks;
2885 EMACS_TIME orig_real_time;
2886
2887 static int process_times_available;
2888
2889 /* Return the relative user and system tick count.  We try to
2890    maintain calculations in terms of integers as long as possible
2891    for increased accuracy. */
2892
2893 static int get_process_times_1(long *user_ticks, long *system_ticks)
2894 {
2895 #if defined (_SC_CLK_TCK) || defined (CLK_TCK) 
2896         /* We have the POSIX times() function available. */
2897         struct tms tttt;
2898         times(&tttt);
2899         *user_ticks = (long)tttt.tms_utime;
2900         *system_ticks = (long)tttt.tms_stime;
2901         return 1;
2902 #elif defined (CLOCKS_PER_SEC)
2903         *user_ticks = (long)clock();
2904         *system_ticks = 0;
2905         return 1;
2906 #else
2907         return 0;
2908 #endif
2909 }
2910
2911 void init_process_times_very_early(void)
2912 {
2913 #if defined (_SC_CLK_TCK)
2914         ticks_per_second = sysconf(_SC_CLK_TCK);
2915 #elif defined (CLK_TCK)
2916         ticks_per_second = CLK_TCK;
2917 #elif defined (CLOCKS_PER_SEC)
2918         ticks_per_second = CLOCKS_PER_SEC;
2919 #endif
2920
2921         process_times_available = get_process_times_1(&orig_user_ticks,
2922                                                       &orig_system_ticks);
2923         EMACS_GET_TIME(orig_real_time);
2924 }
2925
2926 /* Return the user and system times used up by this process so far. */
2927 void
2928 get_process_times(double *user_time, double *system_time, double *real_time)
2929 {
2930         EMACS_TIME curr_real_time;
2931         EMACS_TIME elapsed_time;
2932         long curr_user_ticks, curr_system_ticks;
2933
2934         EMACS_GET_TIME(curr_real_time);
2935         EMACS_SUB_TIME(elapsed_time, curr_real_time, orig_real_time);
2936         *real_time = (EMACS_SECS(elapsed_time)
2937                       + ((double)EMACS_USECS(elapsed_time)) / 1000000);
2938         if (get_process_times_1(&curr_user_ticks, &curr_system_ticks)) {
2939                 *user_time = (((double)(curr_user_ticks - orig_user_ticks))
2940                               / ticks_per_second);
2941                 *system_time =
2942                     (((double)(curr_system_ticks - orig_system_ticks))
2943                      / ticks_per_second);
2944         } else {
2945                 /* A lame OS */
2946                 *user_time = *real_time;
2947                 *system_time = 0;
2948         }
2949 }
2950
2951 #ifndef HAVE_RANDOM
2952 #ifdef random
2953 #define HAVE_RANDOM
2954 #endif
2955 #endif
2956
2957 /* Figure out how many bits the system's random number generator uses.
2958    `random' and `lrand48' are assumed to return 31 usable bits.
2959    BSD `rand' returns a 31 bit value but the low order bits are unusable;
2960    so we'll shift it and treat it like the 15-bit USG `rand'.  */
2961
2962 #ifndef RAND_BITS
2963 # ifdef HAVE_RANDOM
2964 #  define RAND_BITS 31
2965 # else                          /* !HAVE_RANDOM */
2966 #  ifdef HAVE_LRAND48
2967 #   define RAND_BITS 31
2968 #   define random lrand48
2969 #  else                         /* !HAVE_LRAND48 */
2970 #   define RAND_BITS 15
2971 #   if RAND_MAX == 32767
2972 #    define random rand
2973 #   else                        /* RAND_MAX != 32767 */
2974 #    if RAND_MAX == 2147483647
2975 #     define random() (rand () >> 16)
2976 #    else                       /* RAND_MAX != 2147483647 */
2977 #     ifdef USG
2978 #      define random rand
2979 #     else
2980 #      define random() (rand () >> 16)
2981 #     endif                     /* !BSD */
2982 #    endif                      /* RAND_MAX != 2147483647 */
2983 #   endif                       /* RAND_MAX != 32767 */
2984 #  endif                        /* !HAVE_LRAND48 */
2985 # endif                         /* !HAVE_RANDOM */
2986 #endif                          /* !RAND_BITS */
2987
2988 void seed_random(long arg);
2989 void seed_random(long arg)
2990 {
2991 #ifdef HAVE_RANDOM
2992         srandom((unsigned int)arg);
2993 #else
2994 # ifdef HAVE_LRAND48
2995         srand48(arg);
2996 # else
2997         srand((unsigned int)arg);
2998 # endif
2999 #endif
3000 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
3001         bigz_random_seed((unsigned long)arg);
3002 #endif
3003 }
3004
3005 /*
3006  * Build a full Emacs-sized word out of whatever we've got.
3007  * This suffices even for a 64-bit architecture with a 15-bit rand.
3008  */
3009 long get_random(void);
3010 long get_random(void)
3011 {
3012         long val = random();
3013 #if INT_VALBITS > RAND_BITS
3014         val = (val << RAND_BITS) ^ random();
3015 #if INT_VALBITS > 2*RAND_BITS
3016         val = (val << RAND_BITS) ^ random();
3017 #if INT_VALBITS > 3*RAND_BITS
3018         val = (val << RAND_BITS) ^ random();
3019 #if INT_VALBITS > 4*RAND_BITS
3020         val = (val << RAND_BITS) ^ random();
3021 #endif                          /* need at least 5 */
3022 #endif                          /* need at least 4 */
3023 #endif                          /* need at least 3 */
3024 #endif                          /* need at least 2 */
3025         return val & (EMACS_INT) ((1UL << INT_VALBITS) - 1);
3026 }
3027 \f
3028 /************************************************************************/
3029 /*               Strings corresponding to defined signals               */
3030 /************************************************************************/
3031
3032 #if !defined (SYS_SIGLIST_DECLARED) && !defined (HAVE_SYS_SIGLIST) && !defined(HAVE_DECL_SYS_SIGLIST)
3033
3034 #ifdef USG
3035 #ifdef AIX
3036 #define SXE_SYS_SIGLIST_DECLARED 1
3037 const char *sys_siglist[NSIG + 1] = {
3038         /* AIX has changed the signals a bit */
3039         DEFER_GETTEXT("bogus signal"),  /* 0 */
3040         DEFER_GETTEXT("hangup"),        /* 1  SIGHUP */
3041         DEFER_GETTEXT("interrupt"),     /* 2  SIGINT */
3042         DEFER_GETTEXT("quit"),  /* 3  SIGQUIT */
3043         DEFER_GETTEXT("illegal instruction"),   /* 4  SIGILL */
3044         DEFER_GETTEXT("trace trap"),    /* 5  SIGTRAP */
3045         DEFER_GETTEXT("IOT instruction"),       /* 6  SIGIOT */
3046         DEFER_GETTEXT("crash likely"),  /* 7  SIGDANGER */
3047         DEFER_GETTEXT("floating point exception"),      /* 8  SIGFPE */
3048         DEFER_GETTEXT("kill"),  /* 9  SIGKILL */
3049         DEFER_GETTEXT("bus error"),     /* 10 SIGBUS */
3050         DEFER_GETTEXT("segmentation violation"),        /* 11 SIGSEGV */
3051         DEFER_GETTEXT("bad argument to system call"),   /* 12 SIGSYS */
3052         DEFER_GETTEXT("write on a pipe with no one to read it"),        /* 13 SIGPIPE */
3053         DEFER_GETTEXT("alarm clock"),   /* 14 SIGALRM */
3054         DEFER_GETTEXT("software termination signal"),   /* 15 SIGTERM */
3055         DEFER_GETTEXT("user defined signal 1"), /* 16 SIGUSR1 */
3056         DEFER_GETTEXT("user defined signal 2"), /* 17 SIGUSR2 */
3057         DEFER_GETTEXT("death of a child"),      /* 18 SIGCLD */
3058         DEFER_GETTEXT("power-fail restart"),    /* 19 SIGPWR */
3059         DEFER_GETTEXT("bogus signal"),  /* 20 */
3060         DEFER_GETTEXT("bogus signal"),  /* 21 */
3061         DEFER_GETTEXT("bogus signal"),  /* 22 */
3062         DEFER_GETTEXT("bogus signal"),  /* 23 */
3063         DEFER_GETTEXT("bogus signal"),  /* 24 */
3064         DEFER_GETTEXT("LAN I/O interrupt"),     /* 25 SIGAIO */
3065         DEFER_GETTEXT("PTY I/O interrupt"),     /* 26 SIGPTY */
3066         DEFER_GETTEXT("I/O intervention required"),     /* 27 SIGIOINT */
3067 #ifdef AIXHFT
3068         DEFER_GETTEXT("HFT grant"),     /* 28 SIGGRANT */
3069         DEFER_GETTEXT("HFT retract"),   /* 29 SIGRETRACT */
3070         DEFER_GETTEXT("HFT sound done"),        /* 30 SIGSOUND */
3071         DEFER_GETTEXT("HFT input ready"),       /* 31 SIGMSG */
3072 #endif
3073         0
3074 };
3075 #else                           /* USG, not AIX */
3076 #define SXE_SYS_SIGLIST_DECLARED 1
3077 const char *sys_siglist[NSIG + 1] = {
3078         DEFER_GETTEXT("bogus signal"),  /* 0 */
3079         DEFER_GETTEXT("hangup"),        /* 1  SIGHUP */
3080         DEFER_GETTEXT("interrupt"),     /* 2  SIGINT */
3081         DEFER_GETTEXT("quit"),  /* 3  SIGQUIT */
3082         DEFER_GETTEXT("illegal instruction"),   /* 4  SIGILL */
3083         DEFER_GETTEXT("trace trap"),    /* 5  SIGTRAP */
3084         DEFER_GETTEXT("IOT instruction"),       /* 6  SIGIOT */
3085         DEFER_GETTEXT("EMT instruction"),       /* 7  SIGEMT */
3086         DEFER_GETTEXT("floating point exception"),      /* 8  SIGFPE */
3087         DEFER_GETTEXT("kill"),  /* 9  SIGKILL */
3088         DEFER_GETTEXT("bus error"),     /* 10 SIGBUS */
3089         DEFER_GETTEXT("segmentation violation"),        /* 11 SIGSEGV */
3090         DEFER_GETTEXT("bad argument to system call"),   /* 12 SIGSYS */
3091         DEFER_GETTEXT("write on a pipe with no one to read it"),        /* 13 SIGPIPE */
3092         DEFER_GETTEXT("alarm clock"),   /* 14 SIGALRM */
3093         DEFER_GETTEXT("software termination signal"),   /* 15 SIGTERM */
3094         DEFER_GETTEXT("user defined signal 1"), /* 16 SIGUSR1 */
3095         DEFER_GETTEXT("user defined signal 2"), /* 17 SIGUSR2 */
3096         DEFER_GETTEXT("death of a child"),      /* 18 SIGCLD */
3097         DEFER_GETTEXT("power-fail restart"),    /* 19 SIGPWR */
3098 #ifdef sun
3099         DEFER_GETTEXT("window size changed"),   /* 20 SIGWINCH */
3100         DEFER_GETTEXT("urgent socket condition"),       /* 21 SIGURG */
3101         DEFER_GETTEXT("pollable event occurred"),       /* 22 SIGPOLL */
3102         DEFER_GETTEXT("stop (cannot be caught or ignored)"),    /*  23 SIGSTOP */
3103         DEFER_GETTEXT("user stop requested from tty"),  /* 24 SIGTSTP */
3104         DEFER_GETTEXT("stopped process has been continued"),    /* 25 SIGCONT */
3105         DEFER_GETTEXT("background tty read attempted"), /* 26 SIGTTIN */
3106         DEFER_GETTEXT("background tty write attempted"),        /* 27 SIGTTOU */
3107         DEFER_GETTEXT("virtual timer expired"), /* 28 SIGVTALRM */
3108         DEFER_GETTEXT("profiling timer expired"),       /* 29 SIGPROF */
3109         DEFER_GETTEXT("exceeded cpu limit"),    /* 30 SIGXCPU */
3110         DEFER_GETTEXT("exceeded file size limit"),      /* 31 SIGXFSZ */
3111         DEFER_GETTEXT("process's lwps are blocked"),    /* 32 SIGWAITING */
3112         DEFER_GETTEXT("special signal used by thread library"), /* 33 SIGLWP */
3113 #ifdef SIGFREEZE
3114         DEFER_GETTEXT("special signal used by CPR"),    /* 34 SIGFREEZE */
3115 #endif
3116 #ifdef SIGTHAW
3117         DEFER_GETTEXT("special signal used by CPR"),    /* 35 SIGTHAW */
3118 #endif
3119 #endif                          /* sun */
3120         0
3121 };
3122 #endif                          /* not AIX */
3123 #endif                          /* USG */
3124 #ifdef DGUX
3125 #define SXE_SYS_SIGLIST_DECLARED 1
3126 const char *sys_siglist[NSIG + 1] = {
3127         DEFER_GETTEXT("null signal"),   /*  0 SIGNULL   */
3128         DEFER_GETTEXT("hangup"),        /*  1 SIGHUP    */
3129         DEFER_GETTEXT("interrupt"),     /*  2 SIGINT    */
3130         DEFER_GETTEXT("quit"),  /*  3 SIGQUIT   */
3131         DEFER_GETTEXT("illegal instruction"),   /*  4 SIGILL    */
3132         DEFER_GETTEXT("trace trap"),    /*  5 SIGTRAP   */
3133         DEFER_GETTEXT("abort termination"),     /*  6 SIGABRT   */
3134         DEFER_GETTEXT("SIGEMT"),        /*  7 SIGEMT    */
3135         DEFER_GETTEXT("floating point exception"),      /*  8 SIGFPE    */
3136         DEFER_GETTEXT("kill"),  /*  9 SIGKILL   */
3137         DEFER_GETTEXT("bus error"),     /* 10 SIGBUS    */
3138         DEFER_GETTEXT("segmentation violation"),        /* 11 SIGSEGV   */
3139         DEFER_GETTEXT("bad argument to system call"),   /* 12 SIGSYS    */
3140         DEFER_GETTEXT("write on a pipe with no reader"),        /* 13 SIGPIPE   */
3141         DEFER_GETTEXT("alarm clock"),   /* 14 SIGALRM   */
3142         DEFER_GETTEXT("software termination signal"),   /* 15 SIGTERM   */
3143         DEFER_GETTEXT("user defined signal 1"), /* 16 SIGUSR1   */
3144         DEFER_GETTEXT("user defined signal 2"), /* 17 SIGUSR2   */
3145         DEFER_GETTEXT("child stopped or terminated"),   /* 18 SIGCLD    */
3146         DEFER_GETTEXT("power-fail restart"),    /* 19 SIGPWR    */
3147         DEFER_GETTEXT("window size changed"),   /* 20 SIGWINCH  */
3148         DEFER_GETTEXT("undefined"),     /* 21           */
3149         DEFER_GETTEXT("pollable event occurred"),       /* 22 SIGPOLL   */
3150         DEFER_GETTEXT("sendable stop signal not from tty"),     /* 23 SIGSTOP   */
3151         DEFER_GETTEXT("stop signal from tty"),  /* 24 SIGSTP    */
3152         DEFER_GETTEXT("continue a stopped process"),    /* 25 SIGCONT   */
3153         DEFER_GETTEXT("attempted background tty read"), /* 26 SIGTTIN   */
3154         DEFER_GETTEXT("attempted background tty write"),        /* 27 SIGTTOU   */
3155         DEFER_GETTEXT("undefined"),     /* 28           */
3156         DEFER_GETTEXT("undefined"),     /* 29           */
3157         DEFER_GETTEXT("undefined"),     /* 30           */
3158         DEFER_GETTEXT("undefined"),     /* 31           */
3159         DEFER_GETTEXT("undefined"),     /* 32           */
3160         DEFER_GETTEXT("socket (TCP/IP) urgent data arrival"),   /* 33 SIGURG    */
3161         DEFER_GETTEXT("I/O is possible"),       /* 34 SIGIO     */
3162         DEFER_GETTEXT("exceeded cpu time limit"),       /* 35 SIGXCPU   */
3163         DEFER_GETTEXT("exceeded file size limit"),      /* 36 SIGXFSZ   */
3164         DEFER_GETTEXT("virtual time alarm"),    /* 37 SIGVTALRM */
3165         DEFER_GETTEXT("profiling time alarm"),  /* 38 SIGPROF   */
3166         DEFER_GETTEXT("undefined"),     /* 39           */
3167         DEFER_GETTEXT("file record locks revoked"),     /* 40 SIGLOST   */
3168         DEFER_GETTEXT("undefined"),     /* 41           */
3169         DEFER_GETTEXT("undefined"),     /* 42           */
3170         DEFER_GETTEXT("undefined"),     /* 43           */
3171         DEFER_GETTEXT("undefined"),     /* 44           */
3172         DEFER_GETTEXT("undefined"),     /* 45           */
3173         DEFER_GETTEXT("undefined"),     /* 46           */
3174         DEFER_GETTEXT("undefined"),     /* 47           */
3175         DEFER_GETTEXT("undefined"),     /* 48           */
3176         DEFER_GETTEXT("undefined"),     /* 49           */
3177         DEFER_GETTEXT("undefined"),     /* 50           */
3178         DEFER_GETTEXT("undefined"),     /* 51           */
3179         DEFER_GETTEXT("undefined"),     /* 52           */
3180         DEFER_GETTEXT("undefined"),     /* 53           */
3181         DEFER_GETTEXT("undefined"),     /* 54           */
3182         DEFER_GETTEXT("undefined"),     /* 55           */
3183         DEFER_GETTEXT("undefined"),     /* 56           */
3184         DEFER_GETTEXT("undefined"),     /* 57           */
3185         DEFER_GETTEXT("undefined"),     /* 58           */
3186         DEFER_GETTEXT("undefined"),     /* 59           */
3187         DEFER_GETTEXT("undefined"),     /* 60           */
3188         DEFER_GETTEXT("undefined"),     /* 61           */
3189         DEFER_GETTEXT("undefined"),     /* 62           */
3190         DEFER_GETTEXT("undefined"),     /* 63           */
3191         DEFER_GETTEXT("notification message in mess. queue"),   /* 64 SIGDGNOTIFY */
3192         0
3193 };
3194 #endif                          /* DGUX */
3195
3196 #endif                          /* ! SYS_SIGLIST_DECLARED && ! HAVE_SYS_SIGLIST */
3197 \f
3198 /************************************************************************/
3199 /*         Directory routines for systems that don't have them          */
3200 /************************************************************************/
3201
3202 #ifdef SYSV_SYSTEM_DIR
3203
3204 #include <dirent.h>
3205
3206 #if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
3207 int closedir(DIR * dirp)
3208 {                               /* stream from opendir */
3209         int rtnval;
3210
3211         rtnval = sys_close(dirp->dd_fd);
3212
3213         /* Some systems (like Solaris) allocate the buffer and the DIR all
3214            in one block.  Why in the world are we freeing this ourselves
3215            anyway?  */
3216 #if ! (defined (sun) && defined (USG5_4))
3217         xfree((char *)dirp->dd_buf);    /* directory block defined in <dirent.h> */
3218 #endif
3219         xfree((char *)dirp);
3220         return (rtnval);
3221 }
3222 #endif                          /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3223 #endif                          /* SYSV_SYSTEM_DIR */
3224
3225 #ifdef NONSYSTEM_DIR_LIBRARY
3226
3227 DIR *opendir(const char *filename)
3228 {                               /* name of directory */
3229         DIR *dirp;              /* -> malloc'ed storage */
3230         int fd;                 /* file descriptor for read */
3231         struct stat sbuf;       /* result of fstat */
3232
3233         fd = sys_open(filename, O_RDONLY);
3234         if (fd < 0)
3235                 return 0;
3236
3237         if (fstat(fd, &sbuf) < 0
3238             || (sbuf.st_mode & S_IFMT) != S_IFDIR
3239             || (dirp = xnew(DIR)) == 0) {
3240                 sys_close(fd);
3241                 return 0;       /* bad luck today */
3242         }
3243
3244         dirp->dd_fd = fd;
3245         dirp->dd_loc = dirp->dd_size = 0;       /* refill needed */
3246
3247         return dirp;
3248 }
3249
3250 void closedir(DIR * dirp)
3251 {                               /* stream from opendir */
3252         sys_close(dirp->dd_fd);
3253         xfree(dirp);
3254 }
3255
3256 #define DIRSIZ  14
3257 struct olddir {
3258         ino_t od_ino;           /* inode */
3259         char od_name[DIRSIZ];   /* filename */
3260 };
3261
3262 static struct direct dir_static;        /* simulated directory contents */
3263
3264 /* ARGUSED */
3265 struct direct *readdir(DIR * dirp)
3266 {                               /* stream from opendir */
3267         struct olddir *dp;      /* -> directory data */
3268
3269         for (;;) {
3270                 if (dirp->dd_loc >= dirp->dd_size)
3271                         dirp->dd_loc = dirp->dd_size = 0;
3272
3273                 if (dirp->dd_size == 0  /* refill buffer */
3274                     && (dirp->dd_size =
3275                         sys_read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3276                         return 0;
3277
3278                 dp = (struct olddir *)&dirp->dd_buf[dirp->dd_loc];
3279                 dirp->dd_loc += sizeof(struct olddir);
3280
3281                 if (dp->od_ino != 0) {  /* not deleted entry */
3282                         dir_static.d_ino = dp->od_ino;
3283                         strncpy(dir_static.d_name, dp->od_name, DIRSIZ);
3284                         dir_static.d_name[DIRSIZ] = '\0';
3285                         dir_static.d_namlen = strlen(dir_static.d_name);
3286                         dir_static.d_reclen = sizeof(struct direct)
3287                             - MAXNAMLEN + 3
3288                             + dir_static.d_namlen - dir_static.d_namlen % 4;
3289                         return &dir_static;     /* -> simulated structure */
3290                 }
3291         }
3292 }
3293
3294 #endif                          /* NONSYSTEM_DIR_LIBRARY */
3295 \f
3296 /* mkdir and rmdir functions, for systems which don't have them.  */
3297
3298 #ifndef HAVE_MKDIR
3299 /*
3300  * Written by Robert Rother, Mariah Corporation, August 1985.
3301  *
3302  * If you want it, it's yours.  All I ask in return is that if you
3303  * figure out how to do this in a Bourne Shell script you send me
3304  * a copy.
3305  *                                      sdcsvax!rmr or rmr@uscd
3306  *
3307  * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3308  * subroutine.  11Mar86; hoptoad!gnu
3309  *
3310  * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3311  * subroutine didn't return EEXIST.  It does now.
3312  */
3313
3314 /*
3315  * Make a directory.
3316  */
3317 #ifdef MKDIR_PROTOTYPE
3318 MKDIR_PROTOTYPE
3319 #else
3320 int mkdir(const char *dpath, int dmode)
3321 #endif
3322 {
3323         int cpid, status, fd;
3324         struct stat statbuf;
3325
3326         if (stat(dpath, &statbuf) == 0) {       /* we do want stat() here */
3327                 errno = EEXIST; /* Stat worked, so it already exists */
3328                 return -1;
3329         }
3330
3331         /* If stat fails for a reason other than non-existence, return error */
3332         if (errno != ENOENT)
3333                 return -1;
3334
3335         synch_process_alive = 1;
3336         switch (cpid = fork()) {
3337
3338         case -1:                /* Error in fork() */
3339                 return -1;      /* Errno is set already */
3340
3341         case 0:         /* Child process */
3342                 {
3343                         /*
3344                          * Cheap hack to set mode of new directory.  Since this
3345                          * child process is going away anyway, we zap its umask.
3346                          * ####, this won't suffice to set SUID, SGID, etc. on this
3347                          * directory.  Does anybody care?
3348                          */
3349                         status = umask(0);      /* Get current umask */
3350                         status = umask(status | (0777 & ~dmode));       /* Set for mkdir */
3351                         fd = sys_open("/dev/null", O_RDWR);
3352                         if (fd >= 0) {
3353                                 if (fd != STDIN_FILENO)
3354                                         dup2(fd, STDIN_FILENO);
3355                                 if (fd != STDOUT_FILENO)
3356                                         dup2(fd, STDOUT_FILENO);
3357                                 if (fd != STDERR_FILENO)
3358                                         dup2(fd, STDERR_FILENO);
3359                         }
3360                         execl("/bin/mkdir", "mkdir", dpath, (char *)0);
3361                         _exit(-1);      /* Can't exec /bin/mkdir */
3362                 }
3363
3364         default:                /* Parent process */
3365                 wait_for_termination(cpid);
3366         }
3367
3368         if (synch_process_death != 0 || synch_process_retcode != 0) {
3369                 errno = EIO;    /* We don't know why, but */
3370                 return -1;      /* /bin/mkdir failed */
3371         }
3372
3373         return 0;
3374 }
3375 #endif                          /* not HAVE_MKDIR */
3376
3377 #ifndef HAVE_RMDIR
3378 int rmdir(const char *dpath)
3379 {
3380         int cpid, status, fd;
3381         struct stat statbuf;
3382
3383         if (stat(dpath, &statbuf) != 0) {       /* we do want stat() here */
3384                 /* Stat just set errno.  We don't have to */
3385                 return -1;
3386         }
3387
3388         synch_process_alive = 1;
3389         switch (cpid = fork()) {
3390
3391         case -1:                /* Error in fork() */
3392                 return (-1);    /* Errno is set already */
3393
3394         case 0:         /* Child process */
3395                 fd = sys_open("/dev/null", O_RDWR);
3396                 if (fd >= 0) {
3397                         if (fd != STDIN_FILENO)
3398                                 dup2(fd, STDIN_FILENO);
3399                         if (fd != STDOUT_FILENO)
3400                                 dup2(fd, STDOUT_FILENO);
3401                         if (fd != STDERR_FILENO)
3402                                 dup2(fd, STDERR_FILENO);
3403                 }
3404                 execl("/bin/rmdir", "rmdir", dpath, (char *)0);
3405                 _exit(-1);      /* Can't exec /bin/mkdir */
3406
3407         default:                /* Parent process */
3408                 wait_for_termination(cpid);
3409         }
3410
3411         if (synch_process_death != 0 || synch_process_retcode != 0) {
3412                 errno = EIO;    /* We don't know why, but */
3413                 return -1;      /* /bin/rmdir failed */
3414         }
3415
3416         return 0;
3417 }
3418 #endif                          /* !HAVE_RMDIR */
3419 \f
3420 /************************************************************************/
3421 /*                            Misc. SunOS crap                          */
3422 /************************************************************************/
3423
3424 #ifdef USE_DL_STUBS
3425
3426 /* These are included on Sunos 4.1 when we do not use shared libraries.
3427    X11 libraries may refer to these functions but (we hope) do not
3428    actually call them.  */
3429
3430 void *dlopen(void)
3431 {
3432         return 0;
3433 }
3434
3435 void *dlsym(void)
3436 {
3437         return 0;
3438 }
3439
3440 int dlclose(void)
3441 {
3442         return -1;
3443 }
3444
3445 #endif                          /* USE_DL_STUBS */
3446
3447 \f
3448 /* big dirname magic */
3449
3450 #if !defined(HAVE_DIRNAME)
3451 /* some coreutils borrows here */
3452 void
3453 x__dirname(restrict char *res, const char *file, size_t len);
3454 {
3455         /* assumes res is malloc'd of size LEN (and >= xstrlen(file)) */
3456         size_t file_len = xstrlen(file);
3457         size_t offs = x__dirlen(file, file_len);
3458         int append_dot = (offs == 0);
3459
3460         xmemcpy(dir, file, offs);
3461         if (append_dot)
3462                 res[offs++] = '.';
3463         res[offs] = '\0';
3464         return res;
3465 }
3466 #endif  /* !HAVE_DIRNAME */
3467
3468 /* sysdep.c ends here */