Insert bug number.
[bpt/emacs.git] / src / sysdep.c
CommitLineData
86a5659e 1/* Interfaces to system-dependent kernel and library entries.
275464e7 2 Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
114f9c96 3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
8cabe764 4 Free Software Foundation, Inc.
86a5659e
JB
5
6This file is part of GNU Emacs.
7
9ec0b715 8GNU Emacs is free software: you can redistribute it and/or modify
86a5659e 9it under the terms of the GNU General Public License as published by
9ec0b715
GM
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
86a5659e
JB
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9ec0b715 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
86a5659e 20
4838e624 21#include <config.h>
2c55aacf 22#include <ctype.h>
86a5659e 23#include <signal.h>
5890e9f7 24#include <stdio.h>
86a5659e 25#include <setjmp.h>
06e111a6
DN
26#ifdef HAVE_PWD_H
27#include <pwd.h>
28#include <grp.h>
29#endif /* HAVE_PWD_H */
30#ifdef HAVE_LIMITS_H
31#include <limits.h>
32#endif /* HAVE_LIMITS_H */
d3eb3bfa
DL
33#ifdef HAVE_UNISTD_H
34#include <unistd.h>
35#endif
53934c98 36
86a5659e 37#include "lisp.h"
8296bbf8
DL
38/* Including stdlib.h isn't necessarily enough to get srandom
39 declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2. */
8296bbf8 40
4d395425
EZ
41/* The w32 build defines select stuff in w32.h, which is included by
42 sys/select.h (included below). */
43#ifndef WINDOWSNT
819b8f00 44#include "sysselect.h"
4d395425 45#endif
819b8f00 46
9ac0d9e0 47#include "blockinput.h"
86a5659e 48
fe03522b 49#ifdef WINDOWSNT
e15b6288
JR
50#define read sys_read
51#define write sys_write
fe03522b 52#include <windows.h>
e36ec798
AI
53#ifndef NULL
54#define NULL 0
55#endif
fe03522b
RS
56#endif /* not WINDOWSNT */
57
86a5659e
JB
58#include <sys/types.h>
59#include <sys/stat.h>
60#include <errno.h>
61
f95c3f91 62#ifdef HAVE_SETPGID
58eb6cf0 63#if !defined (USG)
c8875a65 64#undef setpgrp
f95c3f91
GM
65#define setpgrp setpgid
66#endif
2b7e8799 67#endif
f95c3f91 68
b05af5d3
PE
69/* Get SI_SRPC_DOMAIN, if it is available. */
70#ifdef HAVE_SYS_SYSTEMINFO_H
71#include <sys/systeminfo.h>
72#endif
73
207bdbdb
RS
74#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
75#include <dos.h>
76#include "dosfns.h"
77#include "msdos.h"
78#include <sys/param.h>
15614e61 79#endif
207bdbdb 80
bb4bc8e2 81#include <sys/file.h>
7ce1c4de 82
612221ab 83#ifdef HAVE_FCNTL_H
bb4bc8e2
RM
84#include <fcntl.h>
85#endif
86a5659e 86
207bdbdb 87#ifndef MSDOS
86a5659e 88#include <sys/ioctl.h>
207bdbdb 89#endif
2a633456 90
e04a4e0d 91#include "systty.h"
94c8642a 92#include "syswait.h"
86a5659e 93
e39a993c 94#if defined (USG)
86a5659e 95#include <sys/utsname.h>
86a5659e 96#include <memory.h>
e39a993c 97#endif /* USG */
86a5659e 98
e36ec798 99#include "keyboard.h"
0137dbf7 100#include "frame.h"
86a5659e
JB
101#include "window.h"
102#include "termhooks.h"
103#include "termchar.h"
104#include "termopts.h"
105#include "dispextern.h"
106#include "process.h"
0a125897 107#include "cm.h" /* for reset_sys_modes */
8646d999
J
108#ifdef HAVE_TERM_H
109/* Include this last. If it is ncurses header file, it adds a lot of
110 defines that interfere with stuff in other headers. Someone responsible
111 for ncurses messed up bigtime. See bug#6812. */
112#include <term.h>
113#endif
86a5659e 114
fe03522b
RS
115#ifdef WINDOWSNT
116#include <direct.h>
117/* In process.h which conflicts with the local copy. */
118#define _P_WAIT 0
43db14bb
JB
119int _cdecl _spawnlp (int, const char *, const char *, ...);
120int _cdecl _getpid (void);
b6682dd9 121extern char *getwd (char *);
fe03522b
RS
122#endif
123
91bac16a
JB
124#include "syssignal.h"
125#include "systime.h"
d79998bc
KH
126#ifdef HAVE_UTIME_H
127#include <utime.h>
128#endif
129
130#ifndef HAVE_UTIMES
131#ifndef HAVE_STRUCT_UTIMBUF
132/* We want to use utime rather than utimes, but we couldn't find the
133 structure declaration. We'll use the traditional one. */
134struct utimbuf {
135 long actime;
136 long modtime;
137};
138#endif
139#endif
86a5659e 140
a00d5589
RS
141/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
142#ifndef LPASS8
143#define LPASS8 0
144#endif
145
91433552 146static const int baud_convert[] =
86a5659e
JB
147 {
148 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
149 1800, 2400, 4800, 9600, 19200, 38400
150 };
86a5659e 151
f0d21750
GM
152#ifdef HAVE_SPEED_T
153#include <termios.h>
f0d21750 154#else
ba5971b3 155#if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
ba5971b3 156#else
8a2a6032 157#if defined (HAVE_TERMIOS_H) && defined (GNU_LINUX)
515b04d0 158#include <termios.h>
f2361c60 159#endif
ba5971b3 160#endif
f0d21750 161#endif
86a5659e 162
5bdd7bdd
GM
163int emacs_ospeed;
164
f57e2426 165void croak (char *) NO_RETURN;
b9c4113e 166
89723395
GM
167/* Temporary used by `sigblock' when defined in terms of signprocmask. */
168
169SIGMASKTYPE sigprocmask_set;
170
f78f1a83 171
3480d92b 172#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
f78f1a83 173
b6682dd9 174/* Return the current working directory. Returns NULL on errors.
f78f1a83
EZ
175 Any other returned value must be freed with free. This is used
176 only when get_current_dir_name is not defined on the system. */
177char*
cf84bb53 178get_current_dir_name (void)
f78f1a83
EZ
179{
180 char *buf;
181 char *pwd;
182 struct stat dotstat, pwdstat;
183 /* If PWD is accurate, use it instead of calling getwd. PWD is
184 sometimes a nicer name, and using it may avoid a fatal error if a
185 parent directory is searchable but not readable. */
186 if ((pwd = getenv ("PWD")) != 0
187 && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
188 && stat (pwd, &pwdstat) == 0
189 && stat (".", &dotstat) == 0
190 && dotstat.st_ino == pwdstat.st_ino
191 && dotstat.st_dev == pwdstat.st_dev
192#ifdef MAXPATHLEN
193 && strlen (pwd) < MAXPATHLEN
194#endif
195 )
196 {
197 buf = (char *) malloc (strlen (pwd) + 1);
198 if (!buf)
199 return NULL;
200 strcpy (buf, pwd);
201 }
202#ifdef HAVE_GETCWD
203 else
204 {
205 size_t buf_size = 1024;
b6682dd9 206 buf = (char *) malloc (buf_size);
f78f1a83
EZ
207 if (!buf)
208 return NULL;
209 for (;;)
210 {
211 if (getcwd (buf, buf_size) == buf)
212 break;
213 if (errno != ERANGE)
214 {
215 int tmp_errno = errno;
216 free (buf);
217 errno = tmp_errno;
218 return NULL;
219 }
220 buf_size *= 2;
221 buf = (char *) realloc (buf, buf_size);
222 if (!buf)
223 return NULL;
224 }
225 }
226#else
227 else
228 {
229 /* We need MAXPATHLEN here. */
230 buf = (char *) malloc (MAXPATHLEN + 1);
231 if (!buf)
232 return NULL;
233 if (getwd (buf) == NULL)
234 {
235 int tmp_errno = errno;
236 free (buf);
237 errno = tmp_errno;
238 return NULL;
239 }
240 }
241#endif
242 return buf;
243}
244#endif
245
64e971c3 246\f
9628b887 247/* Discard pending input on all input descriptors. */
91bac16a 248
08633194 249void
971de7fb 250discard_tty_input (void)
86a5659e 251{
fe03522b 252#ifndef WINDOWSNT
91bac16a 253 struct emacs_tty buf;
86a5659e
JB
254
255 if (noninteractive)
256 return;
257
fe03522b 258#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
207bdbdb 259 while (dos_keyread () != -1)
fe03522b 260 ;
207bdbdb 261#else /* not MSDOS */
9628b887 262 {
28d7d09f 263 struct tty_display_info *tty;
9628b887
KL
264 for (tty = tty_list; tty; tty = tty->next)
265 {
0b0d3e0b
KL
266 if (tty->input) /* Is the device suspended? */
267 {
268 EMACS_GET_TTY (fileno (tty->input), &buf);
269 EMACS_SET_TTY (fileno (tty->input), &buf, 0);
270 }
9628b887
KL
271 }
272 }
207bdbdb 273#endif /* not MSDOS */
fe03522b 274#endif /* not WINDOWSNT */
86a5659e
JB
275}
276
16c290d8 277\f
86a5659e
JB
278#ifdef SIGTSTP
279
64e971c3 280/* Arrange for character C to be read as the next input from
16c290d8
KL
281 the terminal.
282 XXX What if we have multiple ttys?
283*/
64e971c3 284
dfcf069d 285void
0c2338d8 286stuff_char (char c)
86a5659e 287{
428a555e 288 if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
23dab951
RS
289 return;
290
86a5659e
JB
291/* Should perhaps error if in batch mode */
292#ifdef TIOCSTI
0b0d3e0b 293 ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
86a5659e 294#else /* no TIOCSTI */
71f06467 295 error ("Cannot stuff terminal input characters in this version of Unix");
86a5659e
JB
296#endif /* no TIOCSTI */
297}
298
299#endif /* SIGTSTP */
64e971c3 300\f
08633194 301void
16c290d8 302init_baud_rate (int fd)
86a5659e 303{
86a5659e 304 if (noninteractive)
5bdd7bdd 305 emacs_ospeed = 0;
86a5659e
JB
306 else
307 {
fe03522b 308#ifdef DOS_NT
5bdd7bdd 309 emacs_ospeed = 15;
fe03522b 310#else /* not DOS_NT */
e04a4e0d
JB
311#ifdef HAVE_TERMIOS
312 struct termios sg;
91bac16a 313
71f06467 314 sg.c_cflag = B9600;
16c290d8 315 tcgetattr (fd, &sg);
5bdd7bdd 316 emacs_ospeed = cfgetospeed (&sg);
7c2fb837 317#else /* not TERMIOS */
e04a4e0d
JB
318#ifdef HAVE_TERMIO
319 struct termio sg;
91bac16a 320
71f06467 321 sg.c_cflag = B9600;
e04a4e0d 322#ifdef HAVE_TCATTR
16c290d8 323 tcgetattr (fd, &sg);
e04a4e0d 324#else
16c290d8 325 ioctl (fd, TCGETA, &sg);
e04a4e0d 326#endif
5bdd7bdd 327 emacs_ospeed = sg.c_cflag & CBAUD;
7c2fb837 328#else /* neither TERMIOS nor TERMIO */
91bac16a 329 struct sgttyb sg;
177c0ea7 330
91bac16a 331 sg.sg_ospeed = B9600;
16c290d8 332 if (ioctl (fd, TIOCGETP, &sg) < 0)
d7272cff 333 abort ();
5bdd7bdd 334 emacs_ospeed = sg.sg_ospeed;
91bac16a 335#endif /* not HAVE_TERMIO */
e04a4e0d 336#endif /* not HAVE_TERMIOS */
fe03522b 337#endif /* not DOS_NT */
86a5659e 338 }
177c0ea7 339
5bdd7bdd
GM
340 baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
341 ? baud_convert[emacs_ospeed] : 9600);
86a5659e
JB
342 if (baud_rate == 0)
343 baud_rate = 1200;
344}
345
16c290d8 346\f
86a5659e 347/*ARGSUSED*/
dfcf069d 348void
971de7fb 349set_exclusive_use (int fd)
86a5659e
JB
350{
351#ifdef FIOCLEX
352 ioctl (fd, FIOCLEX, 0);
353#endif
354 /* Ok to do nothing if this feature does not exist */
355}
64e971c3 356\f
86a5659e
JB
357
358int wait_debugging; /* Set nonzero to make following function work under dbx
fe03522b 359 (at least for bsd). */
86a5659e
JB
360
361SIGTYPE
971de7fb 362wait_for_termination_signal (void)
86a5659e
JB
363{}
364
77defa9a 365#ifndef MSDOS
86a5659e
JB
366/* Wait for subprocess with process id `pid' to terminate and
367 make sure it will get eliminated (not remain forever as a zombie) */
368
08633194 369void
971de7fb 370wait_for_termination (int pid)
86a5659e
JB
371{
372 while (1)
373 {
f2a77c3a 374#if defined (BSD_SYSTEM) || defined (HPUX)
4c8975ad
RS
375 /* Note that kill returns -1 even if the process is just a zombie now.
376 But inevitably a SIGCHLD interrupt should be generated
377 and child_sig will do wait3 and make the process go away. */
378 /* There is some indication that there is a bug involved with
379 termination of subprocesses, perhaps involving a kernel bug too,
380 but no idea what it is. Just as a hunch we signal SIGCHLD to see
381 if that causes the problem to go away or get worse. */
382 sigsetmask (sigmask (SIGCHLD));
383 if (0 > kill (pid, 0))
fe03522b 384 {
4c8975ad
RS
385 sigsetmask (SIGEMPTYMASK);
386 kill (getpid (), SIGCHLD);
387 break;
388 }
389 if (wait_debugging)
390 sleep (1);
391 else
392 sigpause (SIGEMPTYMASK);
2a633456 393#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
d6dae14b
EZ
394#ifdef WINDOWSNT
395 wait (0);
396 break;
397#else /* not WINDOWSNT */
9ab714c7 398 sigblock (sigmask (SIGCHLD));
59957f85
GM
399 errno = 0;
400 if (kill (pid, 0) == -1 && errno == ESRCH)
9ab714c7
RS
401 {
402 sigunblock (sigmask (SIGCHLD));
403 break;
404 }
ac3ac859 405
0fdcb867 406 sigsuspend (&empty_mask);
d6dae14b 407#endif /* not WINDOWSNT */
2a633456 408#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
86a5659e
JB
409 }
410}
411
86a5659e
JB
412/*
413 * flush any pending output
414 * (may flush input as well; it does not matter the way we use it)
415 */
177c0ea7 416
08633194 417void
971de7fb 418flush_pending_output (int channel)
86a5659e
JB
419{
420#ifdef HAVE_TERMIOS
421 /* If we try this, we get hit with SIGTTIN, because
422 the child's tty belongs to the child's pgrp. */
423#else
424#ifdef TCFLSH
425 ioctl (channel, TCFLSH, 1);
426#else
427#ifdef TIOCFLUSH
428 int zero = 0;
429 /* 3rd arg should be ignored
430 but some 4.2 kernels actually want the address of an int
431 and nonzero means something different. */
432 ioctl (channel, TIOCFLUSH, &zero);
433#endif
434#endif
435#endif
436}
64e971c3 437\f
86a5659e
JB
438/* Set up the terminal at the other end of a pseudo-terminal that
439 we will be controlling an inferior through.
440 It should not echo or do line-editing, since that is done
441 in Emacs. No padding needed for insertion into an Emacs buffer. */
442
08633194 443void
971de7fb 444child_setup_tty (int out)
86a5659e 445{
77defa9a 446#ifndef WINDOWSNT
91bac16a
JB
447 struct emacs_tty s;
448
449 EMACS_GET_TTY (out, &s);
86a5659e 450
31be8d24 451#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
91bac16a
JB
452 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
453 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
9d4e5eea 454#ifdef NLDLY
07cfc4e7
GM
455 /* http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00406.html
456 Some versions of GNU Hurd do not have FFDLY? */
457#ifdef FFDLY
91bac16a
JB
458 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
459 /* No output delays */
07cfc4e7
GM
460#else
461 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
462 /* No output delays */
463#endif
9d4e5eea 464#endif
91bac16a
JB
465 s.main.c_lflag &= ~ECHO; /* Disable echo */
466 s.main.c_lflag |= ISIG; /* Enable signals */
9d4e5eea
RS
467#ifdef IUCLC
468 s.main.c_iflag &= ~IUCLC; /* Disable downcasing on input. */
469#endif
f7097b2a
RS
470#ifdef ISTRIP
471 s.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
472#endif
23e4c8be 473#ifdef OLCUC
9d4e5eea
RS
474 s.main.c_oflag &= ~OLCUC; /* Disable upcasing on output. */
475#endif
f7097b2a 476 s.main.c_oflag &= ~TAB3; /* Disable tab expansion */
1bf96fb5 477 s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
441f6399
RS
478 s.main.c_cc[VERASE] = CDISABLE; /* disable erase processing */
479 s.main.c_cc[VKILL] = CDISABLE; /* disable kill processing */
91bac16a 480
86a5659e 481#ifdef HPUX
91bac16a 482 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
86a5659e 483#endif /* HPUX */
91bac16a 484
dfe598b5
RS
485#ifdef SIGNALS_VIA_CHARACTERS
486 /* the QUIT and INTR character are used in process_send_signal
487 so set them here to something useful. */
fa51fa32 488 if (s.main.c_cc[VQUIT] == CDISABLE)
dfe598b5 489 s.main.c_cc[VQUIT] = '\\'&037; /* Control-\ */
fa51fa32 490 if (s.main.c_cc[VINTR] == CDISABLE)
dfe598b5
RS
491 s.main.c_cc[VINTR] = 'C'&037; /* Control-C */
492#endif /* not SIGNALS_VIA_CHARACTERS */
493
86a5659e 494#ifdef AIX
86a5659e
JB
495 /* Also, PTY overloads NUL and BREAK.
496 don't ignore break, but don't signal either, so it looks like NUL. */
91bac16a
JB
497 s.main.c_iflag &= ~IGNBRK;
498 s.main.c_iflag &= ~BRKINT;
dfe598b5
RS
499 /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
500 unconditionally. Then a SIGNALS_VIA_CHARACTERS conditional
501 would force it to 0377. That looks like duplicated code. */
91bac16a 502 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
86a5659e
JB
503#endif /* AIX */
504
aaa0a19a
SM
505 /* We originally enabled ICANON (and set VEOF to 04), and then had
506 proces.c send additional EOF chars to flush the output when faced
507 with long lines, but this leads to weird effects when the
2b0a91e7
SM
508 subprocess has disabled ICANON and ends up seeing those spurious
509 extra EOFs. So we don't send EOFs any more in
aaa0a19a
SM
510 process.c:send_process. First we tried to disable ICANON by
511 default, so if a subsprocess sets up ICANON, it's his problem (or
512 the Elisp package that talks to it) to deal with lines that are
513 too long. But this disables some features, such as the ability
514 to send EOF signals. So we re-enabled ICANON but there is no
515 more "send eof to flush" going on (which is wrong and unportable
516 in itself). The correct way to handle too much output is to
517 buffer what could not be written and then write it again when
518 select returns ok for writing. This has it own set of
519 problems. Write is now asynchronous, is that a problem? How much
520 do we buffer, and what do we do when that limit is reached? */
9a747ba6
JD
521
522 s.main.c_lflag |= ICANON; /* Enable line editing and eof processing */
523 s.main.c_cc[VEOF] = 'D'&037; /* Control-D */
3d15fe78 524#if 0 /* These settings only apply to non-ICANON mode. */
2b0a91e7
SM
525 s.main.c_cc[VMIN] = 1;
526 s.main.c_cc[VTIME] = 0;
aaa0a19a 527#endif
2b0a91e7 528
06ac62b4
SM
529#else /* not HAVE_TERMIO */
530
531 s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
532 | CBREAK | TANDEM);
533 s.main.sg_flags |= LPASS8;
534 s.main.sg_erase = 0377;
535 s.main.sg_kill = 0377;
536 s.lmode = LLITOUT | s.lmode; /* Don't strip 8th bit */
537
86a5659e
JB
538#endif /* not HAVE_TERMIO */
539
91bac16a 540 EMACS_SET_TTY (out, &s, 0);
86a5659e 541
77defa9a 542#endif /* not WINDOWSNT */
86a5659e 543}
77defa9a 544#endif /* MSDOS */
86a5659e 545
64e971c3 546\f
86a5659e
JB
547/* Record a signal code and the handler for it. */
548struct save_signal
549{
550 int code;
f57e2426 551 SIGTYPE (*handler) (int);
86a5659e
JB
552};
553
f57e2426
J
554static void save_signal_handlers (struct save_signal *);
555static void restore_signal_handlers (struct save_signal *);
35a05cca 556
86a5659e
JB
557/* Suspend the Emacs process; give terminal to its superior. */
558
08633194 559void
971de7fb 560sys_suspend (void)
86a5659e 561{
c4ea52a6 562#if defined (SIGTSTP) && !defined (MSDOS)
86a5659e 563
5a570e37 564 {
e89a2cd5 565 int pgrp = EMACS_GETPGRP (0);
5a570e37
JB
566 EMACS_KILLPG (pgrp, SIGTSTP);
567 }
86a5659e
JB
568
569#else /* No SIGTSTP */
86a5659e
JB
570/* On a system where suspending is not implemented,
571 instead fork a subshell and let it talk directly to the terminal
572 while we wait. */
a0932daa
KH
573 sys_subshell ();
574
a0932daa 575#endif /* no SIGTSTP */
a0932daa
KH
576}
577
578/* Fork a subshell. */
579
08633194 580void
971de7fb 581sys_subshell (void)
a0932daa 582{
ad00c243 583#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
a0932daa
KH
584 int st;
585 char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
586#endif
efa04277 587 int pid;
86a5659e 588 struct save_signal saved_handlers[5];
efa04277
RS
589 Lisp_Object dir;
590 unsigned char *str = 0;
591 int len;
86a5659e
JB
592
593 saved_handlers[0].code = SIGINT;
594 saved_handlers[1].code = SIGQUIT;
595 saved_handlers[2].code = SIGTERM;
596#ifdef SIGIO
597 saved_handlers[3].code = SIGIO;
598 saved_handlers[4].code = 0;
599#else
600 saved_handlers[3].code = 0;
601#endif
602
efa04277
RS
603 /* Mentioning current_buffer->buffer would mean including buffer.h,
604 which somehow wedges the hp compiler. So instead... */
605
606 dir = intern ("default-directory");
0e7e7a58 607 if (NILP (Fboundp (dir)))
efa04277
RS
608 goto xyzzy;
609 dir = Fsymbol_value (dir);
914e81a2 610 if (!STRINGP (dir))
efa04277
RS
611 goto xyzzy;
612
613 dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
d5db4077
KR
614 str = (unsigned char *) alloca (SCHARS (dir) + 2);
615 len = SCHARS (dir);
72af86bd 616 memcpy (str, SDATA (dir), len);
efa04277
RS
617 if (str[len - 1] != '/') str[len++] = '/';
618 str[len] = 0;
619 xyzzy:
620
ad00c243 621#ifdef DOS_NT
7964ba9e 622 pid = 0;
718ca3cf
RS
623 save_signal_handlers (saved_handlers);
624 synch_process_alive = 1;
177c0ea7 625#else
efa04277 626 pid = vfork ();
86a5659e
JB
627 if (pid == -1)
628 error ("Can't spawn subshell");
7964ba9e
RS
629#endif
630
86a5659e
JB
631 if (pid == 0)
632 {
8ea90aa3 633 const char *sh = 0;
86a5659e 634
ad00c243 635#ifdef DOS_NT /* MW, Aug 1993 */
207bdbdb 636 getwd (oldwd);
7964ba9e
RS
637 if (sh == 0)
638 sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
207bdbdb 639#endif
7964ba9e
RS
640 if (sh == 0)
641 sh = (char *) egetenv ("SHELL");
86a5659e
JB
642 if (sh == 0)
643 sh = "sh";
207bdbdb 644
86a5659e 645 /* Use our buffer's default directory for the subshell. */
efa04277 646 if (str)
074c438c 647 chdir ((char *) str);
efa04277 648
86a5659e 649 close_process_descs (); /* Close Emacs's pipes/ptys */
1593c2fe 650
6f8b4d01 651#ifdef SET_EMACS_PRIORITY
1593c2fe 652 {
31ade731 653 extern EMACS_INT emacs_priority;
1593c2fe 654
6f8b4d01 655 if (emacs_priority < 0)
1593c2fe
JB
656 nice (-emacs_priority);
657 }
658#endif
659
fe03522b 660#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
c0917202 661 {
48178f9a
EZ
662 char *epwd = getenv ("PWD");
663 char old_pwd[MAXPATHLEN+1+4];
c0917202
EZ
664
665 /* If PWD is set, pass it with corrected value. */
48178f9a 666 if (epwd)
c0917202 667 {
48178f9a 668 strcpy (old_pwd, epwd);
c0917202
EZ
669 if (str[len - 1] == '/')
670 str[len - 1] = '\0';
671 setenv ("PWD", str, 1);
672 }
673 st = system (sh);
674 chdir (oldwd);
48178f9a 675 if (epwd)
c0917202
EZ
676 putenv (old_pwd); /* restore previous value */
677 }
207bdbdb 678#else /* not MSDOS */
fe03522b 679#ifdef WINDOWSNT
fe03522b
RS
680 /* Waits for process completion */
681 pid = _spawnlp (_P_WAIT, sh, sh, NULL);
ad00c243 682 chdir (oldwd);
fe03522b
RS
683 if (pid == -1)
684 write (1, "Can't execute subshell", 22);
fe03522b 685#else /* not WINDOWSNT */
e120ea40 686 execlp (sh, sh, (char *) 0);
86a5659e
JB
687 write (1, "Can't execute subshell", 22);
688 _exit (1);
fe03522b 689#endif /* not WINDOWSNT */
207bdbdb 690#endif /* not MSDOS */
86a5659e
JB
691 }
692
718ca3cf 693 /* Do this now if we did not do it before. */
ed68db4d 694#ifndef MSDOS
86a5659e 695 save_signal_handlers (saved_handlers);
ffafc793 696 synch_process_alive = 1;
718ca3cf
RS
697#endif
698
ad00c243 699#ifndef DOS_NT
86a5659e 700 wait_for_termination (pid);
7964ba9e 701#endif
86a5659e 702 restore_signal_handlers (saved_handlers);
718ca3cf 703 synch_process_alive = 0;
86a5659e
JB
704}
705
35a05cca 706static void
971de7fb 707save_signal_handlers (struct save_signal *saved_handlers)
86a5659e
JB
708{
709 while (saved_handlers->code)
710 {
508b171c 711 saved_handlers->handler
f57e2426 712 = (SIGTYPE (*) (int)) signal (saved_handlers->code, SIG_IGN);
86a5659e
JB
713 saved_handlers++;
714 }
715}
716
35a05cca 717static void
971de7fb 718restore_signal_handlers (struct save_signal *saved_handlers)
86a5659e
JB
719{
720 while (saved_handlers->code)
721 {
722 signal (saved_handlers->code, saved_handlers->handler);
723 saved_handlers++;
724 }
725}
726\f
4d553a13
KL
727#ifndef SIGIO
728/* If SIGIO is broken, don't do anything. */
729void
730init_sigio (int fd)
731{
732}
733
734void
735reset_sigio (int fd)
736{
737}
738
739void
740request_sigio (void)
741{
742}
743
744void
745unrequest_sigio (void)
746{
747}
748
749#else
86a5659e
JB
750#ifdef F_SETFL
751
819b8f00 752int old_fcntl_flags[MAXDESC];
86a5659e 753
08633194 754void
971de7fb 755init_sigio (int fd)
86a5659e
JB
756{
757#ifdef FASYNC
819b8f00
KL
758 old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
759 fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
86a5659e 760#endif
23dab951 761 interrupts_deferred = 0;
86a5659e
JB
762}
763
590034f9 764void
971de7fb 765reset_sigio (int fd)
86a5659e 766{
4d553a13 767#ifdef FASYNC
819b8f00 768 fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
4d553a13 769#endif
86a5659e
JB
770}
771
eb8c3be9 772#ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
428a555e 773/* XXX Uhm, FASYNC is not used anymore here. */
6d8cf830 774/* XXX Yeah, but you need it for SIGIO, don't you? */
86a5659e 775
08633194 776void
971de7fb 777request_sigio (void)
86a5659e 778{
6bbba5a6 779 if (noninteractive)
23dab951
RS
780 return;
781
86a5659e 782#ifdef SIGWINCH
e065a56e 783 sigunblock (sigmask (SIGWINCH));
86a5659e 784#endif
0a125897 785 sigunblock (sigmask (SIGIO));
86a5659e
JB
786
787 interrupts_deferred = 0;
788}
789
08633194 790void
0a125897 791unrequest_sigio (void)
cf84bb53 792{
6bbba5a6
KL
793 if (noninteractive)
794 return;
795
796#if 0 /* XXX What's wrong with blocking SIGIO under X? */
797 if (x_display_list)
23dab951 798 return;
428a555e 799#endif
6bbba5a6 800
86a5659e 801#ifdef SIGWINCH
e065a56e 802 sigblock (sigmask (SIGWINCH));
86a5659e 803#endif
0a125897 804 sigblock (sigmask (SIGIO));
86a5659e
JB
805 interrupts_deferred = 1;
806}
807
808#else /* no FASYNC */
feb67dfe 809#ifndef MSDOS
25ab68af 810
08633194 811void
cf84bb53 812request_sigio (void)
86a5659e 813{
6e5b2385 814 if (noninteractive || read_socket_hook)
23dab951
RS
815 return;
816
86a5659e
JB
817 croak ("request_sigio");
818}
177c0ea7 819
08633194 820void
cf84bb53 821unrequest_sigio (void)
86a5659e 822{
6e5b2385 823 if (noninteractive || read_socket_hook)
23dab951
RS
824 return;
825
86a5659e
JB
826 croak ("unrequest_sigio");
827}
feb67dfe
EZ
828
829#endif /* MSDOS */
86a5659e
JB
830#endif /* FASYNC */
831#endif /* F_SETFL */
4d553a13 832#endif /* SIGIO */
9ae8f997 833
9ae8f997 834\f
68936329
JB
835/* Getting and setting emacs_tty structures. */
836
837/* Set *TC to the parameters associated with the terminal FD.
838 Return zero if all's well, or -1 if we ran into an error we
839 couldn't deal with. */
840int
971de7fb 841emacs_get_tty (int fd, struct emacs_tty *settings)
68936329
JB
842{
843 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
844#ifdef HAVE_TCATTR
845 /* We have those nifty POSIX tcmumbleattr functions. */
72af86bd 846 memset (&settings->main, 0, sizeof (settings->main));
68936329
JB
847 if (tcgetattr (fd, &settings->main) < 0)
848 return -1;
849
850#else
851#ifdef HAVE_TERMIO
852 /* The SYSV-style interface? */
853 if (ioctl (fd, TCGETA, &settings->main) < 0)
854 return -1;
855
68936329 856#else
fe03522b 857#ifndef DOS_NT
68936329
JB
858 /* I give up - I hope you have the BSD ioctls. */
859 if (ioctl (fd, TIOCGETP, &settings->main) < 0)
860 return -1;
fe03522b 861#endif /* not DOS_NT */
68936329 862#endif
68936329
JB
863#endif
864
865 /* Suivant - Do we have to get struct ltchars data? */
50b8cf60 866#ifdef HAVE_LTCHARS
68936329
JB
867 if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
868 return -1;
869#endif
870
871 /* How about a struct tchars and a wordful of lmode bits? */
50b8cf60 872#ifdef HAVE_TCHARS
68936329
JB
873 if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
874 || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
875 return -1;
876#endif
877
878 /* We have survived the tempest. */
879 return 0;
880}
881
882
883/* Set the parameters of the tty on FD according to the contents of
394049ec 884 *SETTINGS. If FLUSHP is non-zero, we discard input.
68936329 885 Return 0 if all went well, and -1 if anything failed. */
394049ec 886
68936329 887int
971de7fb 888emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
68936329
JB
889{
890 /* Set the primary parameters - baud rate, character size, etcetera. */
891#ifdef HAVE_TCATTR
e6cc3307 892 int i;
68936329
JB
893 /* We have those nifty POSIX tcmumbleattr functions.
894 William J. Smith <wjs@wiis.wang.com> writes:
c4ea52a6 895 "POSIX 1003.1 defines tcsetattr to return success if it was
68936329
JB
896 able to perform any of the requested actions, even if some
897 of the requested actions could not be performed.
898 We must read settings back to ensure tty setup properly.
899 AIX requires this to keep tty from hanging occasionally." */
eb8c3be9 900 /* This make sure that we don't loop indefinitely in here. */
e6cc3307 901 for (i = 0 ; i < 10 ; i++)
394049ec 902 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
68936329
JB
903 {
904 if (errno == EINTR)
905 continue;
906 else
907 return -1;
908 }
909 else
910 {
911 struct termios new;
912
72af86bd 913 memset (&new, 0, sizeof (new));
68936329
JB
914 /* Get the current settings, and see if they're what we asked for. */
915 tcgetattr (fd, &new);
e6cc3307
RS
916 /* We cannot use memcmp on the whole structure here because under
917 * aix386 the termios structure has some reserved field that may
918 * not be filled in.
919 */
920 if ( new.c_iflag == settings->main.c_iflag
921 && new.c_oflag == settings->main.c_oflag
922 && new.c_cflag == settings->main.c_cflag
923 && new.c_lflag == settings->main.c_lflag
c4ea52a6 924 && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
68936329 925 break;
e6cc3307
RS
926 else
927 continue;
68936329
JB
928 }
929
930#else
931#ifdef HAVE_TERMIO
932 /* The SYSV-style interface? */
394049ec 933 if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
68936329
JB
934 return -1;
935
68936329 936#else
fe03522b 937#ifndef DOS_NT
68936329 938 /* I give up - I hope you have the BSD ioctls. */
394049ec 939 if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
68936329 940 return -1;
fe03522b 941#endif /* not DOS_NT */
68936329 942
68936329
JB
943#endif
944#endif
945
946 /* Suivant - Do we have to get struct ltchars data? */
50b8cf60 947#ifdef HAVE_LTCHARS
68936329
JB
948 if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
949 return -1;
950#endif
951
952 /* How about a struct tchars and a wordful of lmode bits? */
50b8cf60 953#ifdef HAVE_TCHARS
68936329
JB
954 if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
955 || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
956 return -1;
957#endif
177c0ea7 958
68936329
JB
959 /* We have survived the tempest. */
960 return 0;
961}
962
963\f
86a5659e
JB
964
965#ifdef F_SETOWN
819b8f00 966int old_fcntl_owner[MAXDESC];
86a5659e
JB
967#endif /* F_SETOWN */
968
86a5659e
JB
969/* This may also be defined in stdio,
970 but if so, this does no harm,
971 and using the same name avoids wasting the other one's space. */
972
9d9a7716 973#if defined (USG)
86a5659e
JB
974unsigned char _sobuf[BUFSIZ+8];
975#else
976char _sobuf[BUFSIZ];
977#endif
177c0ea7 978
50b8cf60 979#ifdef HAVE_LTCHARS
86a5659e
JB
980static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
981#endif
50b8cf60 982#ifdef HAVE_TCHARS
4ec5cb58 983static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
177c0ea7 984#endif
86a5659e 985
da8e1115
KL
986/* Initialize the terminal mode on all tty devices that are currently
987 open. */
988
08633194 989void
28d440ab
KL
990init_all_sys_modes (void)
991{
28d7d09f 992 struct tty_display_info *tty;
16c290d8 993 for (tty = tty_list; tty; tty = tty->next)
28d440ab 994 init_sys_modes (tty);
28d440ab
KL
995}
996
da8e1115
KL
997/* Initialize the terminal mode on the given tty device. */
998
28d440ab 999void
971de7fb 1000init_sys_modes (struct tty_display_info *tty_out)
86a5659e 1001{
91bac16a
JB
1002 struct emacs_tty tty;
1003
4ec5cb58
RS
1004 Vtty_erase_char = Qnil;
1005
86a5659e
JB
1006 if (noninteractive)
1007 return;
1008
0b0d3e0b
KL
1009 if (!tty_out->output)
1010 return; /* The tty is suspended. */
cf84bb53 1011
2246281f
KL
1012 if (! tty_out->old_tty)
1013 tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
cf84bb53 1014
0b0d3e0b 1015 EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty);
23dab951 1016
2246281f 1017 tty = *tty_out->old_tty;
86a5659e 1018
31be8d24 1019#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
2246281f 1020 XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
4ec5cb58 1021
2246281f
KL
1022 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
1023 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
7f371164
RS
1024#ifdef INLCR /* I'm just being cautious,
1025 since I can't check how widespread INLCR is--rms. */
2246281f 1026 tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
7f371164 1027#endif
86a5659e 1028#ifdef ISTRIP
2246281f 1029 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
86a5659e 1030#endif
2246281f
KL
1031 tty.main.c_lflag &= ~ECHO; /* Disable echo */
1032 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
e2b40c23 1033#ifdef IEXTEN
2246281f 1034 tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
e2b40c23 1035#endif
2246281f
KL
1036 tty.main.c_lflag |= ISIG; /* Enable signals */
1037 if (tty_out->flow_control)
1038 {
1039 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
86a5659e 1040#ifdef IXANY
2246281f 1041 tty.main.c_iflag &= ~IXANY;
86a5659e 1042#endif /* IXANY */
2246281f
KL
1043 }
1044 else
1045 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
1046 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
1047 on output */
1048 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
86a5659e 1049#ifdef CS8
2246281f
KL
1050 if (tty_out->meta_key)
1051 {
1052 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
1053 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
1054 }
86a5659e 1055#endif
2246281f
KL
1056 if (tty_out->input == stdin)
1057 {
1058 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
1059 /* Set up C-g for both SIGQUIT and SIGINT.
1060 We don't know which we will get, but we handle both alike
1061 so which one it really gives us does not matter. */
1062 tty.main.c_cc[VQUIT] = quit_char;
1063 }
1064 else
1065 {
1066 /* We normally don't get interrupt or quit signals from tty
1067 devices other than our controlling terminal; therefore,
1068 we must handle C-g as normal input. Unfortunately, this
1069 means that the interrupt and quit feature must be
1070 disabled on secondary ttys, or we would not even see the
1071 keypress.
cf84bb53 1072
2246281f
KL
1073 Note that even though emacsclient could have special code
1074 to pass SIGINT to Emacs, we should _not_ enable
1075 interrupt/quit keys for emacsclient frames. This means
1076 that we can't break out of loops in C code from a
1077 secondary tty frame, but we can always decide what
1078 display the C-g came from, which is more important from a
1079 usability point of view. (Consider the case when two
1080 people work together using the same Emacs instance.) */
1081 tty.main.c_cc[VINTR] = CDISABLE;
1082 tty.main.c_cc[VQUIT] = CDISABLE;
1083 }
1084 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
1085 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
86a5659e 1086#ifdef VSWTCH
2246281f 1087 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
91bac16a 1088 of C-z */
86a5659e 1089#endif /* VSWTCH */
cf84bb53 1090
b8ff87cc 1091#if defined (__mips__) || defined (HAVE_TCATTR)
86a5659e 1092#ifdef VSUSP
2246281f 1093 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
86a5659e
JB
1094#endif /* VSUSP */
1095#ifdef V_DSUSP
2246281f 1096 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
86a5659e 1097#endif /* V_DSUSP */
e2b40c23 1098#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
2246281f 1099 tty.main.c_cc[VDSUSP] = CDISABLE;
e2b40c23 1100#endif /* VDSUSP */
92c995de 1101#ifdef VLNEXT
2246281f 1102 tty.main.c_cc[VLNEXT] = CDISABLE;
92c995de
RS
1103#endif /* VLNEXT */
1104#ifdef VREPRINT
2246281f 1105 tty.main.c_cc[VREPRINT] = CDISABLE;
92c995de
RS
1106#endif /* VREPRINT */
1107#ifdef VWERASE
2246281f 1108 tty.main.c_cc[VWERASE] = CDISABLE;
92c995de
RS
1109#endif /* VWERASE */
1110#ifdef VDISCARD
2246281f 1111 tty.main.c_cc[VDISCARD] = CDISABLE;
92c995de 1112#endif /* VDISCARD */
c179a6d1 1113
2246281f
KL
1114 if (tty_out->flow_control)
1115 {
421dd92f 1116#ifdef VSTART
2246281f 1117 tty.main.c_cc[VSTART] = '\021';
421dd92f
RS
1118#endif /* VSTART */
1119#ifdef VSTOP
2246281f 1120 tty.main.c_cc[VSTOP] = '\023';
421dd92f 1121#endif /* VSTOP */
2246281f
KL
1122 }
1123 else
1124 {
c179a6d1 1125#ifdef VSTART
2246281f 1126 tty.main.c_cc[VSTART] = CDISABLE;
c179a6d1
RS
1127#endif /* VSTART */
1128#ifdef VSTOP
2246281f 1129 tty.main.c_cc[VSTOP] = CDISABLE;
c179a6d1 1130#endif /* VSTOP */
2246281f 1131 }
86a5659e 1132#endif /* mips or HAVE_TCATTR */
c179a6d1 1133
86a5659e 1134#ifdef AIX
f5272227
KL
1135 tty.main.c_cc[VSTRT] = CDISABLE;
1136 tty.main.c_cc[VSTOP] = CDISABLE;
1137 tty.main.c_cc[VSUSP] = CDISABLE;
1138 tty.main.c_cc[VDSUSP] = CDISABLE;
2246281f
KL
1139 if (tty_out->flow_control)
1140 {
ac567c95 1141#ifdef VSTART
2246281f 1142 tty.main.c_cc[VSTART] = '\021';
ac567c95
RS
1143#endif /* VSTART */
1144#ifdef VSTOP
2246281f 1145 tty.main.c_cc[VSTOP] = '\023';
ac567c95 1146#endif /* VSTOP */
2246281f
KL
1147 }
1148 /* Also, PTY overloads NUL and BREAK.
1149 don't ignore break, but don't signal either, so it looks like NUL.
1150 This really serves a purpose only if running in an XTERM window
1151 or via TELNET or the like, but does no harm elsewhere. */
1152 tty.main.c_iflag &= ~IGNBRK;
1153 tty.main.c_iflag &= ~BRKINT;
86a5659e
JB
1154#endif
1155#else /* if not HAVE_TERMIO */
fe03522b 1156#ifndef DOS_NT
2246281f
KL
1157 XSETINT (Vtty_erase_char, tty.main.sg_erase);
1158 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1159 if (meta_key)
1160 tty.main.sg_flags |= ANYP;
1161 tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
fe03522b 1162#endif /* not DOS_NT */
86a5659e
JB
1163#endif /* not HAVE_TERMIO */
1164
2246281f
KL
1165 /* If going to use CBREAK mode, we must request C-g to interrupt
1166 and turn off start and stop chars, etc. If not going to use
1167 CBREAK mode, do this anyway so as to turn off local flow
1168 control for user coming over network on 4.2; in this case,
1169 only t_stopc and t_startc really matter. */
91bac16a 1170#ifndef HAVE_TERMIO
50b8cf60 1171#ifdef HAVE_TCHARS
2246281f
KL
1172 /* Note: if not using CBREAK mode, it makes no difference how we
1173 set this */
1174 tty.tchars = new_tchars;
1175 tty.tchars.t_intrc = quit_char;
1176 if (tty_out->flow_control)
1177 {
1178 tty.tchars.t_startc = '\021';
1179 tty.tchars.t_stopc = '\023';
1180 }
cf84bb53 1181
2246281f 1182 tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->old_tty.lmode;
cf84bb53 1183
50b8cf60 1184#endif /* HAVE_TCHARS */
91bac16a
JB
1185#endif /* not HAVE_TERMIO */
1186
50b8cf60 1187#ifdef HAVE_LTCHARS
2246281f 1188 tty.ltchars = new_ltchars;
50b8cf60 1189#endif /* HAVE_LTCHARS */
207bdbdb 1190#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
2246281f
KL
1191 if (!tty_out->term_initted)
1192 internal_terminal_init ();
4e389d32 1193 dos_ttraw (tty_out);
207bdbdb 1194#endif
91bac16a 1195
0b0d3e0b 1196 EMACS_SET_TTY (fileno (tty_out->input), &tty, 0);
86a5659e 1197
2246281f
KL
1198 /* This code added to insure that, if flow-control is not to be used,
1199 we have an unlocked terminal at the start. */
91bac16a 1200
86a5659e 1201#ifdef TCXONC
0b0d3e0b 1202 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
86a5659e 1203#endif
86a5659e 1204#ifdef TIOCSTART
0b0d3e0b 1205 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
86a5659e 1206#endif
86a5659e 1207
f2a77c3a 1208#if defined (HAVE_TERMIOS) || defined (HPUX)
51417996 1209#ifdef TCOON
0b0d3e0b 1210 if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
d228f207 1211#endif
51417996 1212#endif
d228f207 1213
86a5659e 1214#ifdef F_SETFL
eb8c3be9 1215#ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
2246281f 1216 if (interrupt_input)
86a5659e 1217 {
0b0d3e0b
KL
1218 old_fcntl_owner[fileno (tty_out->input)] =
1219 fcntl (fileno (tty_out->input), F_GETOWN, 0);
1220 fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
1221 init_sigio (fileno (tty_out->input));
7e5a23bd 1222#ifdef HAVE_GPM
75a8734b 1223 if (gpm_tty == tty_out)
3e748bcb 1224 {
75a8734b 1225 /* Arrange for mouse events to give us SIGIO signals. */
3e748bcb 1226 fcntl (gpm_fd, F_SETOWN, getpid ());
57669cf1 1227 fcntl (gpm_fd, F_SETFL, fcntl (gpm_fd, F_GETFL, 0) | O_NONBLOCK);
3e748bcb
NR
1228 init_sigio (gpm_fd);
1229 }
7e5a23bd 1230#endif /* HAVE_GPM */
86a5659e
JB
1231 }
1232#endif /* F_GETOWN */
1233#endif /* F_SETFL */
1234
86a5659e
JB
1235#ifdef _IOFBF
1236 /* This symbol is defined on recent USG systems.
1237 Someone says without this call USG won't really buffer the file
1238 even with a call to setbuf. */
0b0d3e0b 1239 setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf);
86a5659e 1240#else
0b0d3e0b 1241 setbuf (tty_out->output, (char *) _sobuf);
86a5659e 1242#endif
4d553a13 1243
69fb5031
JR
1244 if (tty_out->terminal->set_terminal_modes_hook)
1245 tty_out->terminal->set_terminal_modes_hook (tty_out->terminal);
4b311aaf 1246
9628b887
KL
1247 if (!tty_out->term_initted)
1248 {
1249 Lisp_Object tail, frame;
1250 FOR_EACH_FRAME (tail, frame)
1251 {
daf01701 1252 /* XXX This needs to be revised. */
9628b887
KL
1253 if (FRAME_TERMCAP_P (XFRAME (frame))
1254 && FRAME_TTY (XFRAME (frame)) == tty_out)
1255 init_frame_faces (XFRAME (frame));
1256 }
1257 }
045942b2 1258
9628b887 1259 if (tty_out->term_initted && no_redraw_on_reenter)
86a5659e 1260 {
855a0da7
SM
1261 /* We used to call "direct_output_forward_char(0)" here,
1262 but it's not clear why, since it may not do anything anyway. */
86a5659e
JB
1263 }
1264 else
1265 {
9628b887 1266 Lisp_Object tail, frame;
0137dbf7 1267 frame_garbaged = 1;
9628b887
KL
1268 FOR_EACH_FRAME (tail, frame)
1269 {
7ab98847
EZ
1270 if ((FRAME_TERMCAP_P (XFRAME (frame))
1271 || FRAME_MSDOS_P (XFRAME (frame)))
9628b887
KL
1272 && FRAME_TTY (XFRAME (frame)) == tty_out)
1273 FRAME_GARBAGED_P (XFRAME (frame)) = 1;
1274 }
86a5659e 1275 }
91bac16a 1276
9628b887 1277 tty_out->term_initted = 1;
86a5659e
JB
1278}
1279
1280/* Return nonzero if safe to use tabs in output.
1281 At the time this is called, init_sys_modes has not been done yet. */
177c0ea7 1282
dfcf069d 1283int
16c290d8 1284tabs_safe_p (int fd)
86a5659e 1285{
6548cf00 1286 struct emacs_tty etty;
91bac16a 1287
16c290d8 1288 EMACS_GET_TTY (fd, &etty);
6548cf00 1289 return EMACS_TTY_TABS_OK (&etty);
86a5659e 1290}
73d5358f 1291\f
86a5659e 1292/* Get terminal size from system.
73d5358f
RS
1293 Store number of lines into *HEIGHTP and width into *WIDTHP.
1294 We store 0 if there's no valid information. */
86a5659e 1295
08633194 1296void
16c290d8 1297get_tty_size (int fd, int *widthp, int *heightp)
86a5659e 1298{
86a5659e 1299
86a5659e 1300#ifdef TIOCGWINSZ
91bac16a
JB
1301
1302 /* BSD-style. */
86a5659e 1303 struct winsize size;
91bac16a 1304
16c290d8 1305 if (ioctl (fd, TIOCGWINSZ, &size) == -1)
91bac16a
JB
1306 *widthp = *heightp = 0;
1307 else
1308 {
1309 *widthp = size.ws_col;
1310 *heightp = size.ws_row;
1311 }
1312
1313#else
1314#ifdef TIOCGSIZE
1315
1316 /* SunOS - style. */
177c0ea7 1317 struct ttysize size;
91bac16a 1318
16c290d8 1319 if (ioctl (fd, TIOCGSIZE, &size) == -1)
91bac16a
JB
1320 *widthp = *heightp = 0;
1321 else
1322 {
1323 *widthp = size.ts_cols;
1324 *heightp = size.ts_lines;
1325 }
1326
207bdbdb
RS
1327#else
1328#ifdef MSDOS
1329 *widthp = ScreenCols ();
1330 *heightp = ScreenRows ();
86a5659e
JB
1331#else /* system doesn't know size */
1332 *widthp = 0;
1333 *heightp = 0;
207bdbdb 1334#endif
91bac16a
JB
1335#endif /* not SunOS-style */
1336#endif /* not BSD-style */
86a5659e 1337}
91bac16a 1338
73d5358f
RS
1339/* Set the logical window size associated with descriptor FD
1340 to HEIGHT and WIDTH. This is used mainly with ptys. */
1341
1342int
971de7fb 1343set_window_size (int fd, int height, int width)
73d5358f
RS
1344{
1345#ifdef TIOCSWINSZ
1346
1347 /* BSD-style. */
1348 struct winsize size;
1349 size.ws_row = height;
1350 size.ws_col = width;
1351
1352 if (ioctl (fd, TIOCSWINSZ, &size) == -1)
1353 return 0; /* error */
1354 else
1355 return 1;
1356
1357#else
1358#ifdef TIOCSSIZE
1359
1360 /* SunOS - style. */
177c0ea7 1361 struct ttysize size;
73d5358f
RS
1362 size.ts_lines = height;
1363 size.ts_cols = width;
1364
1365 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1366 return 0;
1367 else
1368 return 1;
1369#else
1370 return -1;
1371#endif /* not SunOS-style */
1372#endif /* not BSD-style */
1373}
1374
86a5659e 1375\f
da8e1115
KL
1376
1377/* Prepare all terminal devices for exiting Emacs. */
1378
28d440ab
KL
1379void
1380reset_all_sys_modes (void)
1381{
28d7d09f 1382 struct tty_display_info *tty;
16c290d8 1383 for (tty = tty_list; tty; tty = tty->next)
28d440ab 1384 reset_sys_modes (tty);
28d440ab
KL
1385}
1386
0a125897 1387/* Prepare the terminal for closing it; move the cursor to the
0137dbf7 1388 bottom of the frame, turn off interrupt-driven I/O, etc. */
da8e1115 1389
08633194 1390void
971de7fb 1391reset_sys_modes (struct tty_display_info *tty_out)
86a5659e
JB
1392{
1393 if (noninteractive)
1394 {
1395 fflush (stdout);
1396 return;
1397 }
9628b887 1398 if (!tty_out->term_initted)
86a5659e 1399 return;
da8e1115 1400
0b0d3e0b
KL
1401 if (!tty_out->output)
1402 return; /* The tty is suspended. */
cf84bb53 1403
da8e1115
KL
1404 /* Go to and clear the last line of the terminal. */
1405
0a125897 1406 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
cf84bb53 1407
da8e1115
KL
1408 /* Code adapted from tty_clear_end_of_line. */
1409 if (tty_out->TS_clr_line)
1410 {
1411 emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc);
1412 }
1413 else
1414 { /* have to do it the hard way */
1415 int i;
ed8dad6b 1416 tty_turn_off_insert (tty_out);
cf84bb53 1417
da8e1115 1418 for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
0b0d3e0b
KL
1419 {
1420 fputc (' ', tty_out->output);
1421 }
da8e1115 1422 }
cf84bb53 1423
0a125897 1424 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
819b8f00 1425 fflush (tty_out->output);
cf84bb53 1426
69fb5031
JR
1427 if (tty_out->terminal->reset_terminal_modes_hook)
1428 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
2f98e6e3 1429
2a633456 1430#ifdef BSD_SYSTEM
86a5659e 1431 /* Avoid possible loss of output when changing terminal modes. */
0b0d3e0b 1432 fsync (fileno (tty_out->output));
86a5659e 1433#endif
91bac16a 1434
86a5659e 1435#ifdef F_SETFL
eb8c3be9 1436#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
86a5659e
JB
1437 if (interrupt_input)
1438 {
0b0d3e0b
KL
1439 reset_sigio (fileno (tty_out->input));
1440 fcntl (fileno (tty_out->input), F_SETOWN,
1441 old_fcntl_owner[fileno (tty_out->input)]);
86a5659e
JB
1442 }
1443#endif /* F_SETOWN */
a6b00318 1444#ifdef O_NDELAY
0b0d3e0b
KL
1445 fcntl (fileno (tty_out->input), F_SETFL,
1446 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
a6b00318 1447#endif
86a5659e 1448#endif /* F_SETFL */
91bac16a 1449
fca177d4 1450 if (tty_out->old_tty)
0b0d3e0b 1451 while (EMACS_SET_TTY (fileno (tty_out->input),
fca177d4 1452 tty_out->old_tty, 0) < 0 && errno == EINTR)
7e32a4fb 1453 ;
86a5659e 1454
207bdbdb
RS
1455#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1456 dos_ttcooked ();
1457#endif
1458
86a5659e
JB
1459}
1460\f
1461#ifdef HAVE_PTYS
1462
1463/* Set up the proper status flags for use of a pty. */
1464
08633194 1465void
971de7fb 1466setup_pty (int fd)
86a5659e
JB
1467{
1468 /* I'm told that TOICREMOTE does not mean control chars
1469 "can't be sent" but rather that they don't have
1470 input-editing or signaling effects.
1471 That should be good, because we have other ways
1472 to do those things in Emacs.
1473 However, telnet mode seems not to work on 4.2.
1474 So TIOCREMOTE is turned off now. */
1475
1476 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1477 will hang. In particular, the "timeout" feature (which
1478 causes a read to return if there is no data available)
1479 does this. Also it is known that telnet mode will hang
1480 in such a way that Emacs must be stopped (perhaps this
1481 is the same problem).
177c0ea7 1482
86a5659e
JB
1483 If TIOCREMOTE is turned off, then there is a bug in
1484 hp-ux which sometimes loses data. Apparently the
1485 code which blocks the master process when the internal
1486 buffer fills up does not work. Other than this,
1487 though, everything else seems to work fine.
177c0ea7 1488
86a5659e
JB
1489 Since the latter lossage is more benign, we may as well
1490 lose that way. -- cph */
1491#ifdef FIONBIO
bdee2ef3 1492#if defined(UNIX98_PTYS)
86a5659e
JB
1493 {
1494 int on = 1;
1495 ioctl (fd, FIONBIO, &on);
1496 }
1497#endif
1498#endif
86a5659e
JB
1499}
1500#endif /* HAVE_PTYS */
1501\f
c0c86835
KH
1502/* init_system_name sets up the string for the Lisp function
1503 system-name to return. */
86a5659e 1504
c0c86835 1505extern Lisp_Object Vsystem_name;
86a5659e 1506
f8a80313
RS
1507#ifdef HAVE_SOCKETS
1508#include <sys/socket.h>
1509#include <netdb.h>
1510#endif /* HAVE_SOCKETS */
f8a80313 1511
8581cd64
KH
1512#ifdef TRY_AGAIN
1513#ifndef HAVE_H_ERRNO
1514extern int h_errno;
1515#endif
1516#endif /* TRY_AGAIN */
1517
c0c86835 1518void
971de7fb 1519init_system_name (void)
86a5659e 1520{
210b2b4f 1521#ifndef HAVE_GETHOSTNAME
c0c86835
KH
1522 struct utsname uts;
1523 uname (&uts);
1524 Vsystem_name = build_string (uts.nodename);
67004ffb 1525#else /* HAVE_GETHOSTNAME */
cc6e7269 1526 unsigned int hostname_size = 256;
c0c86835
KH
1527 char *hostname = (char *) alloca (hostname_size);
1528
1529 /* Try to get the host name; if the buffer is too short, try
1530 again. Apparently, the only indication gethostname gives of
1531 whether the buffer was large enough is the presence or absence
1532 of a '\0' in the string. Eech. */
1533 for (;;)
1534 {
1535 gethostname (hostname, hostname_size - 1);
1536 hostname[hostname_size - 1] = '\0';
1537
1538 /* Was the buffer large enough for the '\0'? */
1539 if (strlen (hostname) < hostname_size - 1)
1540 break;
1541
1542 hostname_size <<= 1;
1543 hostname = (char *) alloca (hostname_size);
1544 }
67004ffb 1545#ifdef HAVE_SOCKETS
c0c86835
KH
1546 /* Turn the hostname into the official, fully-qualified hostname.
1547 Don't do this if we're going to dump; this can confuse system
1548 libraries on some machines and make the dumped emacs core dump. */
67004ffb 1549#ifndef CANNOT_DUMP
c0c86835 1550 if (initialized)
67004ffb 1551#endif /* not CANNOT_DUMP */
8966b757 1552 if (! strchr (hostname, '.'))
960d894c 1553 {
960d894c 1554 int count;
3d66b985
JD
1555#ifdef HAVE_GETADDRINFO
1556 struct addrinfo *res;
1557 struct addrinfo hints;
1558 int ret;
1559
cf84bb53 1560 memset (&hints, 0, sizeof (hints));
3d66b985
JD
1561 hints.ai_socktype = SOCK_STREAM;
1562 hints.ai_flags = AI_CANONNAME;
1563
960d894c
KH
1564 for (count = 0;; count++)
1565 {
3d66b985
JD
1566 if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
1567 || ret != EAI_AGAIN)
1568 break;
1569
1570 if (count >= 5)
1571 break;
1572 Fsleep_for (make_number (1), Qnil);
1573 }
1574
1575 if (ret == 0)
1576 {
1577 struct addrinfo *it = res;
1578 while (it)
1579 {
1580 char *fqdn = it->ai_canonname;
8966b757 1581 if (fqdn && strchr (fqdn, '.')
3d66b985
JD
1582 && strcmp (fqdn, "localhost.localdomain") != 0)
1583 break;
1584 it = it->ai_next;
1585 }
1586 if (it)
1587 {
1588 hostname = alloca (strlen (it->ai_canonname) + 1);
1589 strcpy (hostname, it->ai_canonname);
1590 }
1591 freeaddrinfo (res);
1592 }
1593#else /* !HAVE_GETADDRINFO */
1594 struct hostent *hp;
1595 for (count = 0;; count++)
1596 {
1597
e24f1d55 1598#ifdef TRY_AGAIN
960d894c 1599 h_errno = 0;
e24f1d55 1600#endif
960d894c 1601 hp = gethostbyname (hostname);
efa04277 1602#ifdef TRY_AGAIN
960d894c
KH
1603 if (! (hp == 0 && h_errno == TRY_AGAIN))
1604#endif
3d66b985 1605
960d894c 1606 break;
3d66b985 1607
960d894c
KH
1608 if (count >= 5)
1609 break;
1610 Fsleep_for (make_number (1), Qnil);
1611 }
3d66b985 1612
960d894c
KH
1613 if (hp)
1614 {
1615 char *fqdn = (char *) hp->h_name;
960d894c 1616
8966b757 1617 if (!strchr (fqdn, '.'))
960d894c
KH
1618 {
1619 /* We still don't have a fully qualified domain name.
1620 Try to find one in the list of alternate names */
1621 char **alias = hp->h_aliases;
923721f4 1622 while (*alias
8966b757 1623 && (!strchr (*alias, '.')
923721f4 1624 || !strcmp (*alias, "localhost.localdomain")))
960d894c
KH
1625 alias++;
1626 if (*alias)
1627 fqdn = *alias;
1628 }
1629 hostname = fqdn;
960d894c 1630 }
3d66b985 1631#endif /* !HAVE_GETADDRINFO */
960d894c 1632 }
67004ffb 1633#endif /* HAVE_SOCKETS */
c0c86835 1634 Vsystem_name = build_string (hostname);
67004ffb 1635#endif /* HAVE_GETHOSTNAME */
c0c86835
KH
1636 {
1637 unsigned char *p;
d5db4077 1638 for (p = SDATA (Vsystem_name); *p; p++)
c0c86835
KH
1639 if (*p == ' ' || *p == '\t')
1640 *p = '-';
1641 }
67004ffb 1642}
86a5659e 1643\f
7964ba9e 1644#ifndef MSDOS
4624371d 1645#if !defined (HAVE_SELECT)
86a5659e 1646
86d1f23a
KH
1647#include "sysselect.h"
1648#undef select
1649
1650#if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
86a5659e
JB
1651/* Cause explanatory error message at compile time,
1652 since the select emulation is not good enough for X. */
1653int *x = &x_windows_lose_if_no_select_system_call;
1654#endif
1655
1656/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1657 * Only checks read descriptors.
1658 */
1659/* How long to wait between checking fds in select */
1660#define SELECT_PAUSE 1
1661int select_alarmed;
1662
1663/* For longjmp'ing back to read_input_waiting. */
1664
1665jmp_buf read_alarm_throw;
1666
1667/* Nonzero if the alarm signal should throw back to read_input_waiting.
1668 The read_socket_hook function sets this to 1 while it is waiting. */
1669
1670int read_alarm_should_throw;
1671
cf84bb53
JB
1672void
1673select_alarm (int ignore)
86a5659e
JB
1674{
1675 select_alarmed = 1;
86a5659e 1676 signal (SIGALRM, SIG_IGN);
333f1b6f 1677 SIGNAL_THREAD_CHECK (SIGALRM);
86a5659e
JB
1678 if (read_alarm_should_throw)
1679 longjmp (read_alarm_throw, 1);
1680}
1681
9d9f1812 1682#ifndef WINDOWSNT
86a5659e
JB
1683/* Only rfds are checked. */
1684int
cf84bb53
JB
1685sys_select (int nfds,
1686 SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
1687 EMACS_TIME *timeout)
86a5659e 1688{
2246281f 1689 /* XXX This needs to be updated for multi-tty support. Is there
cf84bb53 1690 anybody who needs to emulate select these days? */
2246281f 1691 int ravail = 0;
86d1f23a
KH
1692 SELECT_TYPE orfds;
1693 int timeoutval;
1694 int *local_timeout;
86a5659e 1695 extern int proc_buffered_char[];
86a5659e 1696 extern int process_tick, update_tick;
86a5659e
JB
1697 unsigned char buf;
1698
86d1f23a
KH
1699#if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
1700 /* If we're using X, then the native select will work; we only need the
1701 emulation for non-X usage. */
2246281f 1702 if (!NILP (Vinitial_window_system))
86d1f23a
KH
1703 return select (nfds, rfds, wfds, efds, timeout);
1704#endif
1705 timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
1706 local_timeout = &timeoutval;
1707 FD_ZERO (&orfds);
86a5659e
JB
1708 if (rfds)
1709 {
1710 orfds = *rfds;
86d1f23a 1711 FD_ZERO (rfds);
86a5659e
JB
1712 }
1713 if (wfds)
86d1f23a 1714 FD_ZERO (wfds);
86a5659e 1715 if (efds)
86d1f23a 1716 FD_ZERO (efds);
86a5659e
JB
1717
1718 /* If we are looking only for the terminal, with no timeout,
1719 just read it and wait -- that's more efficient. */
86d1f23a
KH
1720 if (*local_timeout == 100000 && process_tick == update_tick
1721 && FD_ISSET (0, &orfds))
86a5659e 1722 {
86d1f23a
KH
1723 int fd;
1724 for (fd = 1; fd < nfds; ++fd)
1725 if (FD_ISSET (fd, &orfds))
1726 goto hardway;
86a5659e
JB
1727 if (! detect_input_pending ())
1728 read_input_waiting ();
86d1f23a 1729 FD_SET (0, rfds);
86a5659e
JB
1730 return 1;
1731 }
1732
86d1f23a 1733 hardway:
86a5659e
JB
1734 /* Once a second, till the timer expires, check all the flagged read
1735 * descriptors to see if any input is available. If there is some then
1736 * set the corresponding bit in the return copy of rfds.
177c0ea7 1737 */
86a5659e
JB
1738 while (1)
1739 {
86d1f23a 1740 register int to_check, fd;
86a5659e
JB
1741
1742 if (rfds)
1743 {
86d1f23a 1744 for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
86a5659e 1745 {
86d1f23a 1746 if (FD_ISSET (fd, &orfds))
86a5659e
JB
1747 {
1748 int avail = 0, status = 0;
1749
86d1f23a 1750 if (fd == 0)
86a5659e
JB
1751 avail = detect_input_pending (); /* Special keyboard handler */
1752 else
1753 {
1754#ifdef FIONREAD
1755 status = ioctl (fd, FIONREAD, &avail);
1756#else /* no FIONREAD */
1757 /* Hoping it will return -1 if nothing available
1758 or 0 if all 0 chars requested are read. */
1759 if (proc_buffered_char[fd] >= 0)
1760 avail = 1;
1761 else
1762 {
1763 avail = read (fd, &buf, 1);
1764 if (avail > 0)
1765 proc_buffered_char[fd] = buf;
1766 }
1767#endif /* no FIONREAD */
1768 }
1769 if (status >= 0 && avail > 0)
1770 {
86d1f23a 1771 FD_SET (fd, rfds);
86a5659e
JB
1772 ravail++;
1773 }
1774 }
1775 }
1776 }
1777 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
1778 break;
ffdcc91d
GM
1779
1780 turn_on_atimers (0);
1781 signal (SIGALRM, select_alarm);
86a5659e
JB
1782 select_alarmed = 0;
1783 alarm (SELECT_PAUSE);
177c0ea7 1784
86a5659e
JB
1785 /* Wait for a SIGALRM (or maybe a SIGTINT) */
1786 while (select_alarmed == 0 && *local_timeout != 0
1787 && process_tick == update_tick)
1788 {
1789 /* If we are interested in terminal input,
1790 wait by reading the terminal.
1791 That makes instant wakeup for terminal input at least. */
86d1f23a 1792 if (FD_ISSET (0, &orfds))
86a5659e
JB
1793 {
1794 read_input_waiting ();
1795 if (detect_input_pending ())
1796 select_alarmed = 1;
1797 }
1798 else
1799 pause ();
1800 }
1801 (*local_timeout) -= SELECT_PAUSE;
177c0ea7 1802
ffdcc91d
GM
1803 /* Reset the old alarm if there was one. */
1804 turn_on_atimers (1);
177c0ea7 1805
86a5659e
JB
1806 if (*local_timeout == 0) /* Stop on timer being cleared */
1807 break;
1808 }
1809 return ravail;
1810}
30790a37 1811#endif /* not WINDOWSNT */
86a5659e
JB
1812
1813/* Read keyboard input into the standard buffer,
1814 waiting for at least one character. */
1815
dfcf069d 1816void
cf84bb53 1817read_input_waiting (void)
86a5659e 1818{
2246281f
KL
1819 /* XXX This needs to be updated for multi-tty support. Is there
1820 anybody who needs to emulate select these days? */
34567704 1821 int nread, i;
86a5659e
JB
1822
1823 if (read_socket_hook)
1824 {
9f893fc6
KS
1825 struct input_event hold_quit;
1826
1827 EVENT_INIT (hold_quit);
1828 hold_quit.kind = NO_EVENT;
1829
86a5659e
JB
1830 read_alarm_should_throw = 0;
1831 if (! setjmp (read_alarm_throw))
9f893fc6 1832 nread = (*read_socket_hook) (0, 1, &hold_quit);
86a5659e
JB
1833 else
1834 nread = -1;
f4a7e5bd 1835
9f893fc6
KS
1836 if (hold_quit.kind != NO_EVENT)
1837 kbd_buffer_store_event (&hold_quit);
86a5659e
JB
1838 }
1839 else
86a5659e 1840 {
50acda85 1841 struct input_event e;
f4a7e5bd
RS
1842 char buf[3];
1843 nread = read (fileno (stdin), buf, 1);
50acda85 1844 EVENT_INIT (e);
f4a7e5bd
RS
1845
1846 /* Scan the chars for C-g and store them in kbd_buffer. */
e43bd4f5 1847 e.kind = ASCII_KEYSTROKE_EVENT;
2d064114 1848 e.frame_or_window = selected_frame;
f4a7e5bd
RS
1849 e.modifiers = 0;
1850 for (i = 0; i < nread; i++)
a00d5589 1851 {
f4a7e5bd
RS
1852 /* Convert chars > 0177 to meta events if desired.
1853 We do this under the same conditions that read_avail_input does. */
1854 if (read_socket_hook == 0)
1855 {
1856 /* If the user says she has a meta key, then believe her. */
1857 if (meta_key == 1 && (buf[i] & 0x80))
1858 e.modifiers = meta_modifier;
1859 if (meta_key != 2)
1860 buf[i] &= ~0x80;
1861 }
b95520f5 1862
c81d47b4 1863 XSETINT (e.code, buf[i]);
f4a7e5bd
RS
1864 kbd_buffer_store_event (&e);
1865 /* Don't look at input that follows a C-g too closely.
1866 This reduces lossage due to autorepeat on C-g. */
1867 if (buf[i] == quit_char)
1868 break;
1869 }
86a5659e
JB
1870 }
1871}
1872
4624371d 1873#if !defined (HAVE_SELECT)
819b8f00
KL
1874#define select sys_select
1875#endif
1876
86a5659e 1877#endif /* not HAVE_SELECT */
7964ba9e 1878#endif /* not MSDOS */
86a5659e 1879\f
86a5659e
JB
1880/* POSIX signals support - DJB */
1881/* Anyone with POSIX signals should have ANSI C declarations */
1882
c639b0e3 1883sigset_t empty_mask, full_mask;
86a5659e 1884
d6dae14b
EZ
1885#ifndef WINDOWSNT
1886
86a5659e
JB
1887signal_handler_t
1888sys_signal (int signal_number, signal_handler_t action)
1889{
c639b0e3 1890 struct sigaction new_action, old_action;
86a5659e 1891 sigemptyset (&new_action.sa_mask);
e5c99298 1892 new_action.sa_handler = action;
ef874e3d
AS
1893 new_action.sa_flags = 0;
1894#if defined (SA_RESTART)
25ab68af 1895 /* Emacs mostly works better with restartable system services. If this
55fafcf0
RS
1896 flag exists, we probably want to turn it on here.
1897 However, on some systems this resets the timeout of `select'
1898 which means that `select' never finishes if it keeps getting signals.
1899 BROKEN_SA_RESTART is defined on those systems. */
275464e7
SM
1900 /* It's not clear why the comment above says "mostly works better". --Stef
1901 When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
1902 for pending input so we need long-running syscalls to be interrupted
1903 after a signal that sets the interrupt_input_pending flag. */
766f52ec
AS
1904 /* Non-interactive keyboard input goes through stdio, where we always
1905 want restartable system calls. */
ef874e3d
AS
1906# if defined (BROKEN_SA_RESTART) || defined(SYNC_INPUT)
1907 if (noninteractive)
1908# endif
1909 new_action.sa_flags = SA_RESTART;
25ab68af 1910#endif
d32b2f3c 1911 sigaction (signal_number, &new_action, &old_action);
e5c99298 1912 return (old_action.sa_handler);
86a5659e
JB
1913}
1914
d6dae14b
EZ
1915#endif /* WINDOWSNT */
1916
e065a56e
JB
1917#ifndef __GNUC__
1918/* If we're compiling with GCC, we don't need this function, since it
1919 can be written as a macro. */
1920sigset_t
1921sys_sigmask (int sig)
1922{
1923 sigset_t mask;
1924 sigemptyset (&mask);
1925 sigaddset (&mask, sig);
1926 return mask;
1927}
1928#endif
1929
86a5659e
JB
1930/* I'd like to have these guys return pointers to the mask storage in here,
1931 but there'd be trouble if the code was saving multiple masks. I'll be
1932 safe and pass the structure. It normally won't be more than 2 bytes
1933 anyhow. - DJB */
1934
1935sigset_t
1936sys_sigblock (sigset_t new_mask)
1937{
1938 sigset_t old_mask;
1939 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
1940 return (old_mask);
1941}
1942
1943sigset_t
1944sys_sigunblock (sigset_t new_mask)
1945{
1946 sigset_t old_mask;
1947 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
1948 return (old_mask);
1949}
1950
1951sigset_t
1952sys_sigsetmask (sigset_t new_mask)
1953{
1954 sigset_t old_mask;
1955 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
1956 return (old_mask);
1957}
1958
86a5659e 1959\f
b80263be 1960#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
ca9c0567
PE
1961static char *my_sys_siglist[NSIG];
1962# ifdef sys_siglist
1963# undef sys_siglist
1964# endif
1965# define sys_siglist my_sys_siglist
1966#endif
1967
1968void
971de7fb 1969init_signals (void)
ca9c0567 1970{
ca9c0567
PE
1971 sigemptyset (&empty_mask);
1972 sigfillset (&full_mask);
ca9c0567 1973
b80263be 1974#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
ca9c0567
PE
1975 if (! initialized)
1976 {
1977# ifdef SIGABRT
1978 sys_siglist[SIGABRT] = "Aborted";
1979# endif
1980# ifdef SIGAIO
1981 sys_siglist[SIGAIO] = "LAN I/O interrupt";
1982# endif
1983# ifdef SIGALRM
1984 sys_siglist[SIGALRM] = "Alarm clock";
1985# endif
1986# ifdef SIGBUS
1987 sys_siglist[SIGBUS] = "Bus error";
1988# endif
1989# ifdef SIGCLD
1990 sys_siglist[SIGCLD] = "Child status changed";
1991# endif
1992# ifdef SIGCHLD
1993 sys_siglist[SIGCHLD] = "Child status changed";
1994# endif
1995# ifdef SIGCONT
1996 sys_siglist[SIGCONT] = "Continued";
1997# endif
1998# ifdef SIGDANGER
1999 sys_siglist[SIGDANGER] = "Swap space dangerously low";
2000# endif
2001# ifdef SIGDGNOTIFY
2002 sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
2003# endif
2004# ifdef SIGEMT
2005 sys_siglist[SIGEMT] = "Emulation trap";
2006# endif
2007# ifdef SIGFPE
2008 sys_siglist[SIGFPE] = "Arithmetic exception";
2009# endif
2010# ifdef SIGFREEZE
2011 sys_siglist[SIGFREEZE] = "SIGFREEZE";
2012# endif
2013# ifdef SIGGRANT
2014 sys_siglist[SIGGRANT] = "Monitor mode granted";
2015# endif
2016# ifdef SIGHUP
2017 sys_siglist[SIGHUP] = "Hangup";
2018# endif
2019# ifdef SIGILL
2020 sys_siglist[SIGILL] = "Illegal instruction";
2021# endif
2022# ifdef SIGINT
2023 sys_siglist[SIGINT] = "Interrupt";
2024# endif
2025# ifdef SIGIO
2026 sys_siglist[SIGIO] = "I/O possible";
2027# endif
2028# ifdef SIGIOINT
2029 sys_siglist[SIGIOINT] = "I/O intervention required";
2030# endif
2031# ifdef SIGIOT
2032 sys_siglist[SIGIOT] = "IOT trap";
2033# endif
2034# ifdef SIGKILL
2035 sys_siglist[SIGKILL] = "Killed";
2036# endif
2037# ifdef SIGLOST
2038 sys_siglist[SIGLOST] = "Resource lost";
2039# endif
2040# ifdef SIGLWP
2041 sys_siglist[SIGLWP] = "SIGLWP";
2042# endif
2043# ifdef SIGMSG
2044 sys_siglist[SIGMSG] = "Monitor mode data available";
2045# endif
2046# ifdef SIGPHONE
2047 sys_siglist[SIGWIND] = "SIGPHONE";
2048# endif
2049# ifdef SIGPIPE
2050 sys_siglist[SIGPIPE] = "Broken pipe";
2051# endif
2052# ifdef SIGPOLL
2053 sys_siglist[SIGPOLL] = "Pollable event occurred";
2054# endif
2055# ifdef SIGPROF
2056 sys_siglist[SIGPROF] = "Profiling timer expired";
2057# endif
2058# ifdef SIGPTY
2059 sys_siglist[SIGPTY] = "PTY I/O interrupt";
2060# endif
2061# ifdef SIGPWR
2062 sys_siglist[SIGPWR] = "Power-fail restart";
2063# endif
2064# ifdef SIGQUIT
2065 sys_siglist[SIGQUIT] = "Quit";
2066# endif
2067# ifdef SIGRETRACT
2068 sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
2069# endif
2070# ifdef SIGSAK
2071 sys_siglist[SIGSAK] = "Secure attention";
2072# endif
2073# ifdef SIGSEGV
2074 sys_siglist[SIGSEGV] = "Segmentation violation";
2075# endif
2076# ifdef SIGSOUND
2077 sys_siglist[SIGSOUND] = "Sound completed";
2078# endif
2079# ifdef SIGSTOP
2080 sys_siglist[SIGSTOP] = "Stopped (signal)";
2081# endif
2082# ifdef SIGSTP
2083 sys_siglist[SIGSTP] = "Stopped (user)";
2084# endif
2085# ifdef SIGSYS
2086 sys_siglist[SIGSYS] = "Bad argument to system call";
2087# endif
2088# ifdef SIGTERM
2089 sys_siglist[SIGTERM] = "Terminated";
2090# endif
2091# ifdef SIGTHAW
2092 sys_siglist[SIGTHAW] = "SIGTHAW";
2093# endif
2094# ifdef SIGTRAP
2095 sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
2096# endif
2097# ifdef SIGTSTP
2098 sys_siglist[SIGTSTP] = "Stopped (user)";
2099# endif
2100# ifdef SIGTTIN
2101 sys_siglist[SIGTTIN] = "Stopped (tty input)";
2102# endif
2103# ifdef SIGTTOU
2104 sys_siglist[SIGTTOU] = "Stopped (tty output)";
2105# endif
2106# ifdef SIGURG
2107 sys_siglist[SIGURG] = "Urgent I/O condition";
2108# endif
2109# ifdef SIGUSR1
2110 sys_siglist[SIGUSR1] = "User defined signal 1";
2111# endif
2112# ifdef SIGUSR2
2113 sys_siglist[SIGUSR2] = "User defined signal 2";
2114# endif
2115# ifdef SIGVTALRM
2116 sys_siglist[SIGVTALRM] = "Virtual timer expired";
2117# endif
2118# ifdef SIGWAITING
2119 sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
2120# endif
2121# ifdef SIGWINCH
2122 sys_siglist[SIGWINCH] = "Window size changed";
2123# endif
2124# ifdef SIGWIND
2125 sys_siglist[SIGWIND] = "SIGWIND";
2126# endif
2127# ifdef SIGXCPU
2128 sys_siglist[SIGXCPU] = "CPU time limit exceeded";
2129# endif
2130# ifdef SIGXFSZ
2131 sys_siglist[SIGXFSZ] = "File size limit exceeded";
2132# endif
2133 }
b80263be 2134#endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
ca9c0567
PE
2135}
2136\f
9927a7b1 2137#ifndef HAVE_RANDOM
4bb8c8b7
KH
2138#ifdef random
2139#define HAVE_RANDOM
2140#endif
2141#endif
2142
2143/* Figure out how many bits the system's random number generator uses.
2144 `random' and `lrand48' are assumed to return 31 usable bits.
2145 BSD `rand' returns a 31 bit value but the low order bits are unusable;
2146 so we'll shift it and treat it like the 15-bit USG `rand'. */
2147
2148#ifndef RAND_BITS
2149# ifdef HAVE_RANDOM
2150# define RAND_BITS 31
2151# else /* !HAVE_RANDOM */
2152# ifdef HAVE_LRAND48
2153# define RAND_BITS 31
2154# define random lrand48
2155# else /* !HAVE_LRAND48 */
2156# define RAND_BITS 15
2157# if RAND_MAX == 32767
2158# define random rand
2159# else /* RAND_MAX != 32767 */
2160# if RAND_MAX == 2147483647
2161# define random() (rand () >> 16)
2162# else /* RAND_MAX != 2147483647 */
2163# ifdef USG
2164# define random rand
2165# else
2166# define random() (rand () >> 16)
2a633456 2167# endif /* !USG */
4bb8c8b7
KH
2168# endif /* RAND_MAX != 2147483647 */
2169# endif /* RAND_MAX != 32767 */
2170# endif /* !HAVE_LRAND48 */
2171# endif /* !HAVE_RANDOM */
2172#endif /* !RAND_BITS */
2e46c7c6 2173
4bb8c8b7 2174void
971de7fb 2175seed_random (long int arg)
86a5659e 2176{
4bb8c8b7
KH
2177#ifdef HAVE_RANDOM
2178 srandom ((unsigned int)arg);
f8b53a82 2179#else
4bb8c8b7 2180# ifdef HAVE_LRAND48
76425a49 2181 srand48 (arg);
4bb8c8b7
KH
2182# else
2183 srand ((unsigned int)arg);
2184# endif
2e46c7c6 2185#endif
86a5659e
JB
2186}
2187
4bb8c8b7
KH
2188/*
2189 * Build a full Emacs-sized word out of whatever we've got.
2190 * This suffices even for a 64-bit architecture with a 15-bit rand.
2191 */
2192long
971de7fb 2193get_random (void)
4bb8c8b7
KH
2194{
2195 long val = random ();
2196#if VALBITS > RAND_BITS
2197 val = (val << RAND_BITS) ^ random ();
2198#if VALBITS > 2*RAND_BITS
2199 val = (val << RAND_BITS) ^ random ();
2200#if VALBITS > 3*RAND_BITS
2201 val = (val << RAND_BITS) ^ random ();
2202#if VALBITS > 4*RAND_BITS
2203 val = (val << RAND_BITS) ^ random ();
2204#endif /* need at least 5 */
2205#endif /* need at least 4 */
2206#endif /* need at least 3 */
2207#endif /* need at least 2 */
2208 return val & ((1L << VALBITS) - 1);
2209}
7088d1ca
RM
2210
2211#ifndef HAVE_STRERROR
fe03522b 2212#ifndef WINDOWSNT
7088d1ca
RM
2213char *
2214strerror (errnum)
2215 int errnum;
2216{
2217 extern char *sys_errlist[];
2218 extern int sys_nerr;
2219
2220 if (errnum >= 0 && errnum < sys_nerr)
2221 return sys_errlist[errnum];
2222 return (char *) "Unknown error";
2223}
fe03522b 2224#endif /* not WINDOWSNT */
7088d1ca 2225#endif /* ! HAVE_STRERROR */
86a5659e 2226\f
86a5659e 2227int
971de7fb 2228emacs_open (const char *path, int oflag, int mode)
86a5659e
JB
2229{
2230 register int rtnval;
68c45bf0 2231
86a5659e 2232 while ((rtnval = open (path, oflag, mode)) == -1
275464e7
SM
2233 && (errno == EINTR))
2234 QUIT;
86a5659e
JB
2235 return (rtnval);
2236}
2237
dfcf069d 2238int
971de7fb 2239emacs_close (int fd)
86a5659e 2240{
fe111daf 2241 int did_retry = 0;
86a5659e
JB
2242 register int rtnval;
2243
2244 while ((rtnval = close (fd)) == -1
fe111daf
KH
2245 && (errno == EINTR))
2246 did_retry = 1;
2247
2248 /* If close is interrupted SunOS 4.1 may or may not have closed the
2249 file descriptor. If it did the second close will fail with
2250 errno = EBADF. That means we have succeeded. */
2251 if (rtnval == -1 && did_retry && errno == EBADF)
2252 return 0;
2253
86a5659e
JB
2254 return rtnval;
2255}
2256
86a5659e 2257int
971de7fb 2258emacs_read (int fildes, char *buf, unsigned int nbyte)
86a5659e
JB
2259{
2260 register int rtnval;
177c0ea7 2261
86a5659e 2262 while ((rtnval = read (fildes, buf, nbyte)) == -1
275464e7
SM
2263 && (errno == EINTR))
2264 QUIT;
86a5659e
JB
2265 return (rtnval);
2266}
2267
2268int
971de7fb 2269emacs_write (int fildes, const char *buf, unsigned int nbyte)
86a5659e 2270{
b95520f5 2271 register int rtnval, bytes_written;
86a5659e 2272
b95520f5
BF
2273 bytes_written = 0;
2274
2275 while (nbyte > 0)
2276 {
2277 rtnval = write (fildes, buf, nbyte);
2278
2279 if (rtnval == -1)
2280 {
2281 if (errno == EINTR)
77220eeb
SM
2282 {
2283#ifdef SYNC_INPUT
2284 /* I originally used `QUIT' but that might causes files to
2285 be truncated if you hit C-g in the middle of it. --Stef */
55310b94 2286 process_pending_signals ();
77220eeb
SM
2287#endif
2288 continue;
2289 }
b95520f5 2290 else
aa670904 2291 return (bytes_written ? bytes_written : -1);
b95520f5
BF
2292 }
2293
2294 buf += rtnval;
2295 nbyte -= rtnval;
2296 bytes_written += rtnval;
2297 }
2298 return (bytes_written);
86a5659e 2299}
86a5659e
JB
2300\f
2301#ifdef USG
2302/*
2303 * All of the following are for USG.
2304 *
2305 * On USG systems the system calls are INTERRUPTIBLE by signals
2306 * that the user program has elected to catch. Thus the system call
2307 * must be retried in these cases. To handle this without massive
2308 * changes in the source code, we remap the standard system call names
2309 * to names for our own functions in sysdep.c that do the system call
2310 * with retries. Actually, for portability reasons, it is good
2311 * programming practice, as this example shows, to limit all actual
eb8c3be9 2312 * system calls to a single occurrence in the source. Sure, this
86a5659e
JB
2313 * adds an extra level of function call overhead but it is almost
2314 * always negligible. Fred Fish, Unisoft Systems Inc.
2315 */
2316
86a5659e
JB
2317/*
2318 * Warning, this function may not duplicate 4.2 action properly
2319 * under error conditions.
2320 */
2321
2322#ifndef MAXPATHLEN
2323/* In 4.1, param.h fails to define this. */
2324#define MAXPATHLEN 1024
2325#endif
2326
2327#ifndef HAVE_GETWD
2328
2329char *
cf84bb53 2330getwd (char *pathname)
86a5659e
JB
2331{
2332 char *npath, *spath;
cf84bb53 2333 extern char *getcwd (char *, size_t);
86a5659e 2334
9ac0d9e0 2335 BLOCK_INPUT; /* getcwd uses malloc */
86a5659e 2336 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
f4a7e5bd 2337 if (spath == 0)
18b6bc73
GM
2338 {
2339 UNBLOCK_INPUT;
2340 return spath;
2341 }
86a5659e
JB
2342 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2343 up to first slash. Should be harmless on other systems. */
2344 while (*npath && *npath != '/')
2345 npath++;
2346 strcpy (pathname, npath);
2347 free (spath); /* getcwd uses malloc */
9ac0d9e0 2348 UNBLOCK_INPUT;
86a5659e
JB
2349 return pathname;
2350}
2351
2352#endif /* HAVE_GETWD */
2353
2354/*
2355 * Emulate rename using unlink/link. Note that this is
2356 * only partially correct. Also, doesn't enforce restriction
2357 * that files be of same type (regular->regular, dir->dir, etc).
2358 */
2359
4746118a
JB
2360#ifndef HAVE_RENAME
2361
cf84bb53
JB
2362int
2363rename (const char *from, const char *to)
86a5659e
JB
2364{
2365 if (access (from, 0) == 0)
2366 {
2367 unlink (to);
2368 if (link (from, to) == 0)
2369 if (unlink (from) == 0)
2370 return (0);
2371 }
2372 return (-1);
2373}
2374
4746118a
JB
2375#endif
2376
86a5659e 2377
69ab3201 2378#if defined(HPUX) && !defined(HAVE_PERROR)
86a5659e
JB
2379
2380/* HPUX curses library references perror, but as far as we know
2381 it won't be called. Anyway this definition will do for now. */
2382
cf84bb53
JB
2383void
2384perror (void)
86a5659e
JB
2385{
2386}
69ab3201 2387#endif /* HPUX and not HAVE_PERROR */
86a5659e
JB
2388
2389#ifndef HAVE_DUP2
2390
2391/*
2392 * Emulate BSD dup2. First close newd if it already exists.
2393 * Then, attempt to dup oldd. If not successful, call dup2 recursively
2394 * until we are, then close the unsuccessful ones.
2395 */
2396
cf84bb53
JB
2397int
2398dup2 (int oldd, int newd)
86a5659e
JB
2399{
2400 register int fd, ret;
177c0ea7 2401
68c45bf0 2402 emacs_close (newd);
86a5659e
JB
2403
2404#ifdef F_DUPFD
68c45bf0 2405 return fcntl (oldd, F_DUPFD, newd);
86a5659e
JB
2406#else
2407 fd = dup (old);
2408 if (fd == -1)
2409 return -1;
2410 if (fd == new)
2411 return new;
2412 ret = dup2 (old,new);
68c45bf0 2413 emacs_close (fd);
86a5659e
JB
2414 return ret;
2415#endif
2416}
2417
2418#endif /* not HAVE_DUP2 */
2419
2420/*
2421 * Gettimeofday. Simulate as much as possible. Only accurate
2422 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2423 * Only needed when subprocesses are defined.
2424 */
2425
86a5659e
JB
2426#ifndef HAVE_GETTIMEOFDAY
2427#ifdef HAVE_TIMEVAL
177c0ea7 2428
86a5659e 2429/* ARGSUSED */
dfcf069d 2430int
cf84bb53 2431gettimeofday (struct timeval *tp, struct timezone *tzp)
86a5659e 2432{
cf84bb53 2433 extern long time (long);
86a5659e 2434
177c0ea7 2435 tp->tv_sec = time ((long *)0);
86a5659e 2436 tp->tv_usec = 0;
4ca7594f
RS
2437 if (tzp != 0)
2438 tzp->tz_minuteswest = -1;
dfcf069d 2439 return 0;
86a5659e 2440}
177c0ea7 2441
86a5659e 2442#endif
77defa9a 2443#endif /* !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
177c0ea7 2444
86a5659e
JB
2445/*
2446 * This function will go away as soon as all the stubs fixed. (fnf)
2447 */
2448
dfcf069d 2449void
971de7fb 2450croak (char *badfunc)
86a5659e
JB
2451{
2452 printf ("%s not yet implemented\r\n", badfunc);
28d440ab 2453 reset_all_sys_modes ();
86a5659e
JB
2454 exit (1);
2455}
2456
2457#endif /* USG */
2458\f
86a5659e
JB
2459/* Directory routines for systems that don't have them. */
2460
1c97e857 2461#ifdef HAVE_DIRENT_H
86a5659e
JB
2462
2463#include <dirent.h>
2464
9d9a7716 2465#if !defined (HAVE_CLOSEDIR)
cfdc57af 2466
86a5659e 2467int
9d9a7716 2468closedir (DIR *dirp /* stream from opendir */)
86a5659e 2469{
cfdc57af
RS
2470 int rtnval;
2471
68c45bf0 2472 rtnval = emacs_close (dirp->dd_fd);
9ac0d9e0 2473 xfree ((char *) dirp);
cfdc57af
RS
2474
2475 return rtnval;
86a5659e 2476}
9d9a7716 2477#endif /* not HAVE_CLOSEDIR */
1c97e857 2478#endif /* HAVE_DIRENT_H */
86a5659e 2479
23524fb9 2480\f
53ea491a 2481int
e5447b22 2482set_file_times (const char *filename, EMACS_TIME atime, EMACS_TIME mtime)
53ea491a
KH
2483{
2484#ifdef HAVE_UTIMES
2485 struct timeval tv[2];
2486 tv[0] = atime;
2487 tv[1] = mtime;
8334eb21
RS
2488 return utimes (filename, tv);
2489#else /* not HAVE_UTIMES */
53ea491a
KH
2490 struct utimbuf utb;
2491 utb.actime = EMACS_SECS (atime);
2492 utb.modtime = EMACS_SECS (mtime);
8334eb21
RS
2493 return utime (filename, &utb);
2494#endif /* not HAVE_UTIMES */
53ea491a
KH
2495}
2496\f
23524fb9
JB
2497/* mkdir and rmdir functions, for systems which don't have them. */
2498
2499#ifndef HAVE_MKDIR
2500/*
2501 * Written by Robert Rother, Mariah Corporation, August 1985.
2502 *
2503 * If you want it, it's yours. All I ask in return is that if you
2504 * figure out how to do this in a Bourne Shell script you send me
2505 * a copy.
2506 * sdcsvax!rmr or rmr@uscd
2507 *
2508 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
db9cd97a 2509 * subroutine. 11Mar86; hoptoad!gnu
23524fb9
JB
2510 *
2511 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
2512 * subroutine didn't return EEXIST. It does now.
2513 */
2514
2515/*
2516 * Make a directory.
2517 */
2518int
cf84bb53 2519mkdir (char *dpath, int dmode)
23524fb9 2520{
039f26a4 2521 int cpid, status, fd;
23524fb9
JB
2522 struct stat statbuf;
2523
2524 if (stat (dpath, &statbuf) == 0)
2525 {
2526 errno = EEXIST; /* Stat worked, so it already exists */
2527 return -1;
2528 }
2529
2530 /* If stat fails for a reason other than non-existence, return error */
2531 if (errno != ENOENT)
2532 return -1;
2533
039f26a4 2534 synch_process_alive = 1;
23524fb9
JB
2535 switch (cpid = fork ())
2536 {
2537
039f26a4 2538 case -1: /* Error in fork */
23524fb9
JB
2539 return (-1); /* Errno is set already */
2540
2541 case 0: /* Child process */
2542 /*
2543 * Cheap hack to set mode of new directory. Since this
2544 * child process is going away anyway, we zap its umask.
2545 * FIXME, this won't suffice to set SUID, SGID, etc. on this
2546 * directory. Does anybody care?
2547 */
2548 status = umask (0); /* Get current umask */
2549 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
68c45bf0 2550 fd = emacs_open ("/dev/null", O_RDWR, 0);
039f26a4
RS
2551 if (fd >= 0)
2552 {
2553 dup2 (fd, 0);
2554 dup2 (fd, 1);
2555 dup2 (fd, 2);
2556 }
23524fb9
JB
2557 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
2558 _exit (-1); /* Can't exec /bin/mkdir */
2559
2560 default: /* Parent process */
039f26a4 2561 wait_for_termination (cpid);
23524fb9
JB
2562 }
2563
6b0824c9
JD
2564 if (synch_process_death != 0 || synch_process_retcode != 0
2565 || synch_process_termsig != 0)
23524fb9
JB
2566 {
2567 errno = EIO; /* We don't know why, but */
2568 return -1; /* /bin/mkdir failed */
2569 }
2570
2571 return 0;
2572}
2573#endif /* not HAVE_MKDIR */
2574
2575#ifndef HAVE_RMDIR
2576int
cf84bb53 2577rmdir (char *dpath)
23524fb9 2578{
039f26a4 2579 int cpid, status, fd;
23524fb9
JB
2580 struct stat statbuf;
2581
2582 if (stat (dpath, &statbuf) != 0)
2583 {
2584 /* Stat just set errno. We don't have to */
2585 return -1;
2586 }
2587
039f26a4 2588 synch_process_alive = 1;
23524fb9
JB
2589 switch (cpid = fork ())
2590 {
2591
039f26a4 2592 case -1: /* Error in fork */
23524fb9
JB
2593 return (-1); /* Errno is set already */
2594
2595 case 0: /* Child process */
68c45bf0 2596 fd = emacs_open ("/dev/null", O_RDWR, 0);
039f26a4
RS
2597 if (fd >= 0)
2598 {
2599 dup2 (fd, 0);
2600 dup2 (fd, 1);
2601 dup2 (fd, 2);
2602 }
f560db78
RS
2603 execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
2604 _exit (-1); /* Can't exec /bin/rmdir */
2605
207bdbdb 2606 default: /* Parent process */
f560db78 2607 wait_for_termination (cpid);
23524fb9
JB
2608 }
2609
6b0824c9
JD
2610 if (synch_process_death != 0 || synch_process_retcode != 0
2611 || synch_process_termsig != 0)
23524fb9
JB
2612 {
2613 errno = EIO; /* We don't know why, but */
f560db78 2614 return -1; /* /bin/rmdir failed */
23524fb9
JB
2615 }
2616
2617 return 0;
2618}
2619#endif /* !HAVE_RMDIR */
2620
86a5659e 2621\f
72af86bd
AS
2622#ifndef HAVE_MEMSET
2623void *
2624memset (void *b, int n, size_t length)
2625{
2626 unsigned char *p = b;
2627 while (length-- > 0)
2628 *p++ = n;
2629 return b;
2630}
2631#endif /* !HAVE_MEMSET */
2632
2633#ifndef HAVE_MEMCPY
2634void *
2635memcpy (void *b1, void *b2, size_t length)
2636{
2637 unsigned char *p1 = b1, *p2 = b2;
2638 while (length-- > 0)
2639 *p1++ = *p2++;
2640 return b1;
2641}
2642#endif /* !HAVE_MEMCPY */
2643
2644#ifndef HAVE_MEMMOVE
2645void *
2646memmove (void *b1, void *b2, size_t length)
2647{
2648 unsigned char *p1 = b1, *p2 = b2;
2649 if (p1 < p2 || p1 >= p2 + length)
2650 while (length-- > 0)
2651 *p1++ = *p2++;
2652 else
2653 {
2654 p1 += length;
2655 p2 += length;
2656 while (length-- > 0)
2657 *--p1 = *--p2;
2658 }
2659 return b1;
2660}
2661#endif /* !HAVE_MEMCPY */
2662
2663#ifndef HAVE_MEMCMP
2664int
2665memcmp (void *b1, void *b2, size_t length)
2666{
2667 unsigned char *p1 = b1, *p2 = b2;
2668 while (length-- > 0)
2669 if (*p1++ != *p2++)
2670 return p1[-1] < p2[-1] ? -1 : 1;
2671 return 0;
2672}
2673#endif /* !HAVE_MEMCMP */
2674\f
68c45bf0
PE
2675#ifndef HAVE_STRSIGNAL
2676char *
cf84bb53 2677strsignal (int code)
68c45bf0
PE
2678{
2679 char *signame = 0;
2680
2681 if (0 <= code && code < NSIG)
2682 {
68c45bf0
PE
2683 /* Cast to suppress warning if the table has const char *. */
2684 signame = (char *) sys_siglist[code];
68c45bf0 2685 }
c4ea52a6 2686
68c45bf0
PE
2687 return signame;
2688}
2689#endif /* HAVE_STRSIGNAL */
d888760c
GM
2690\f
2691#ifdef HAVE_TERMIOS
2692/* For make-serial-process */
cf84bb53
JB
2693int
2694serial_open (char *port)
d888760c
GM
2695{
2696 int fd = -1;
2697
2698 fd = emacs_open ((char*) port,
2699 O_RDWR
2700#ifdef O_NONBLOCK
2701 | O_NONBLOCK
2702#else
2703 | O_NDELAY
2704#endif
2705#ifdef O_NOCTTY
2706 | O_NOCTTY
2707#endif
2708 , 0);
2709 if (fd < 0)
2710 {
2711 error ("Could not open %s: %s",
2712 port, emacs_strerror (errno));
2713 }
2714#ifdef TIOCEXCL
2715 ioctl (fd, TIOCEXCL, (char *) 0);
2716#endif
2717
2718 return fd;
2719}
2720#endif /* TERMIOS */
2721
2722#ifdef HAVE_TERMIOS
759d3f32
SM
2723
2724#if !defined (HAVE_CFMAKERAW)
2725/* Workaround for targets which are missing cfmakeraw. */
2726/* Pasted from man page. */
cf84bb53
JB
2727static void
2728cfmakeraw (struct termios *termios_p)
759d3f32
SM
2729{
2730 termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
2731 termios_p->c_oflag &= ~OPOST;
2732 termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
2733 termios_p->c_cflag &= ~(CSIZE|PARENB);
2734 termios_p->c_cflag |= CS8;
2735}
2736#endif /* !defined (HAVE_CFMAKERAW */
2737
2738#if !defined (HAVE_CFSETSPEED)
2739/* Workaround for targets which are missing cfsetspeed. */
cf84bb53
JB
2740static int
2741cfsetspeed (struct termios *termios_p, speed_t vitesse)
759d3f32
SM
2742{
2743 return (cfsetispeed (termios_p, vitesse)
2744 + cfsetospeed (termios_p, vitesse));
2745}
2746#endif
2747
d888760c
GM
2748/* For serial-process-configure */
2749void
2750serial_configure (struct Lisp_Process *p,
cf84bb53 2751 Lisp_Object contact)
d888760c
GM
2752{
2753 Lisp_Object childp2 = Qnil;
2754 Lisp_Object tem = Qnil;
2755 struct termios attr;
2756 int err = -1;
2757 char summary[4] = "???"; /* This usually becomes "8N1". */
2758
2759 childp2 = Fcopy_sequence (p->childp);
2760
2761 /* Read port attributes and prepare default configuration. */
2762 err = tcgetattr (p->outfd, &attr);
2763 if (err != 0)
2764 error ("tcgetattr() failed: %s", emacs_strerror (errno));
2765 cfmakeraw (&attr);
2766#if defined (CLOCAL)
2767 attr.c_cflag |= CLOCAL;
2768#endif
2769#if defined (CREAD)
6d1921be 2770 attr.c_cflag |= CREAD;
d888760c
GM
2771#endif
2772
2773 /* Configure speed. */
2774 if (!NILP (Fplist_member (contact, QCspeed)))
2775 tem = Fplist_get (contact, QCspeed);
2776 else
2777 tem = Fplist_get (p->childp, QCspeed);
2778 CHECK_NUMBER (tem);
2779 err = cfsetspeed (&attr, XINT (tem));
2780 if (err != 0)
2781 error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
2782 childp2 = Fplist_put (childp2, QCspeed, tem);
2783
2784 /* Configure bytesize. */
2785 if (!NILP (Fplist_member (contact, QCbytesize)))
2786 tem = Fplist_get (contact, QCbytesize);
2787 else
2788 tem = Fplist_get (p->childp, QCbytesize);
2789 if (NILP (tem))
2790 tem = make_number (8);
2791 CHECK_NUMBER (tem);
2792 if (XINT (tem) != 7 && XINT (tem) != 8)
2793 error (":bytesize must be nil (8), 7, or 8");
cf84bb53 2794 summary[0] = XINT (tem) + '0';
d888760c
GM
2795#if defined (CSIZE) && defined (CS7) && defined (CS8)
2796 attr.c_cflag &= ~CSIZE;
2797 attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
2798#else
16bad4dd 2799 /* Don't error on bytesize 8, which should be set by cfmakeraw. */
d888760c
GM
2800 if (XINT (tem) != 8)
2801 error ("Bytesize cannot be changed");
2802#endif
2803 childp2 = Fplist_put (childp2, QCbytesize, tem);
2804
2805 /* Configure parity. */
2806 if (!NILP (Fplist_member (contact, QCparity)))
2807 tem = Fplist_get (contact, QCparity);
2808 else
2809 tem = Fplist_get (p->childp, QCparity);
2810 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
2811 error (":parity must be nil (no parity), `even', or `odd'");
2812#if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
2813 attr.c_cflag &= ~(PARENB | PARODD);
2814 attr.c_iflag &= ~(IGNPAR | INPCK);
2815 if (NILP (tem))
2816 {
2817 summary[1] = 'N';
2818 }
2819 else if (EQ (tem, Qeven))
2820 {
2821 summary[1] = 'E';
2822 attr.c_cflag |= PARENB;
2823 attr.c_iflag |= (IGNPAR | INPCK);
2824 }
2825 else if (EQ (tem, Qodd))
2826 {
2827 summary[1] = 'O';
2828 attr.c_cflag |= (PARENB | PARODD);
2829 attr.c_iflag |= (IGNPAR | INPCK);
2830 }
2831#else
16bad4dd 2832 /* Don't error on no parity, which should be set by cfmakeraw. */
d888760c
GM
2833 if (!NILP (tem))
2834 error ("Parity cannot be configured");
2835#endif
2836 childp2 = Fplist_put (childp2, QCparity, tem);
2837
2838 /* Configure stopbits. */
2839 if (!NILP (Fplist_member (contact, QCstopbits)))
2840 tem = Fplist_get (contact, QCstopbits);
2841 else
2842 tem = Fplist_get (p->childp, QCstopbits);
2843 if (NILP (tem))
2844 tem = make_number (1);
2845 CHECK_NUMBER (tem);
2846 if (XINT (tem) != 1 && XINT (tem) != 2)
2847 error (":stopbits must be nil (1 stopbit), 1, or 2");
2848 summary[2] = XINT (tem) + '0';
2849#if defined (CSTOPB)
2850 attr.c_cflag &= ~CSTOPB;
2851 if (XINT (tem) == 2)
2852 attr.c_cflag |= CSTOPB;
2853#else
16bad4dd 2854 /* Don't error on 1 stopbit, which should be set by cfmakeraw. */
d888760c
GM
2855 if (XINT (tem) != 1)
2856 error ("Stopbits cannot be configured");
2857#endif
2858 childp2 = Fplist_put (childp2, QCstopbits, tem);
2859
2860 /* Configure flowcontrol. */
2861 if (!NILP (Fplist_member (contact, QCflowcontrol)))
2862 tem = Fplist_get (contact, QCflowcontrol);
2863 else
2864 tem = Fplist_get (p->childp, QCflowcontrol);
2865 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
2866 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
2867#if defined (CRTSCTS)
2868 attr.c_cflag &= ~CRTSCTS;
2869#endif
2870#if defined (CNEW_RTSCTS)
2871 attr.c_cflag &= ~CNEW_RTSCTS;
2872#endif
2873#if defined (IXON) && defined (IXOFF)
2874 attr.c_iflag &= ~(IXON | IXOFF);
2875#endif
2876 if (NILP (tem))
2877 {
2878 /* Already configured. */
2879 }
2880 else if (EQ (tem, Qhw))
2881 {
2882#if defined (CRTSCTS)
2883 attr.c_cflag |= CRTSCTS;
2884#elif defined (CNEW_RTSCTS)
2885 attr.c_cflag |= CNEW_RTSCTS;
2886#else
2887 error ("Hardware flowcontrol (RTS/CTS) not supported");
2888#endif
2889 }
2890 else if (EQ (tem, Qsw))
2891 {
2892#if defined (IXON) && defined (IXOFF)
2893 attr.c_iflag |= (IXON | IXOFF);
2894#else
2895 error ("Software flowcontrol (XON/XOFF) not supported");
2896#endif
2897 }
2898 childp2 = Fplist_put (childp2, QCflowcontrol, tem);
2899
2900 /* Activate configuration. */
2901 err = tcsetattr (p->outfd, TCSANOW, &attr);
2902 if (err != 0)
2903 error ("tcsetattr() failed: %s", emacs_strerror (errno));
2904
2905 childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
2906 p->childp = childp2;
2907
2908}
2909#endif /* TERMIOS */
06e111a6
DN
2910\f
2911/* System depended enumeration of and access to system processes a-la ps(1). */
2912
2913#ifdef HAVE_PROCFS
2914
2915/* Process enumeration and access via /proc. */
2916
2917Lisp_Object
971de7fb 2918list_system_processes (void)
06e111a6
DN
2919{
2920 Lisp_Object procdir, match, proclist, next;
2921 struct gcpro gcpro1, gcpro2;
2922 register Lisp_Object tail;
2923
2924 GCPRO2 (procdir, match);
2925 /* For every process on the system, there's a directory in the
2926 "/proc" pseudo-directory whose name is the numeric ID of that
2927 process. */
2928 procdir = build_string ("/proc");
2929 match = build_string ("[0-9]+");
2930 proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil);
2931
2932 /* `proclist' gives process IDs as strings. Destructively convert
2933 each string into a number. */
2934 for (tail = proclist; CONSP (tail); tail = next)
2935 {
2936 next = XCDR (tail);
2937 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
2938 }
2939 UNGCPRO;
2940
2941 /* directory_files_internal returns the files in reverse order; undo
2942 that. */
2943 proclist = Fnreverse (proclist);
2944 return proclist;
2945}
2946
f8d23104
DN
2947/* The WINDOWSNT implementation is in w32.c.
2948 The MSDOS implementation is in dosfns.c. */
c4605e09 2949#elif !defined (WINDOWSNT) && !defined (MSDOS)
06e111a6
DN
2950
2951Lisp_Object
cf84bb53 2952list_system_processes (void)
06e111a6
DN
2953{
2954 return Qnil;
2955}
91c85b70
EZ
2956
2957#endif /* !defined (WINDOWSNT) */
06e111a6
DN
2958
2959#ifdef GNU_LINUX
2960static void
2961time_from_jiffies (unsigned long long tval, long hz,
2962 time_t *sec, unsigned *usec)
2963{
2964 unsigned long long ullsec;
2965
2966 *sec = tval / hz;
2967 ullsec = *sec;
2968 tval -= ullsec * hz;
2969 /* Careful: if HZ > 1 million, then integer division by it yields zero. */
2970 if (hz <= 1000000)
2971 *usec = tval * 1000000 / hz;
2972 else
2973 *usec = tval / (hz / 1000000);
2974}
2975
2976static Lisp_Object
2977ltime_from_jiffies (unsigned long long tval, long hz)
2978{
2979 time_t sec;
2980 unsigned usec;
2981
2982 time_from_jiffies (tval, hz, &sec, &usec);
2983
2984 return list3 (make_number ((sec >> 16) & 0xffff),
2985 make_number (sec & 0xffff),
2986 make_number (usec));
2987}
2988
2989static void
2990get_up_time (time_t *sec, unsigned *usec)
2991{
2992 FILE *fup;
2993
2994 *sec = *usec = 0;
2995
2996 BLOCK_INPUT;
2997 fup = fopen ("/proc/uptime", "r");
2998
2999 if (fup)
3000 {
3001 double uptime, idletime;
3002
3003 /* The numbers in /proc/uptime use C-locale decimal point, but
3004 we already set ourselves to the C locale (see `fixup_locale'
3005 in emacs.c). */
3006 if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime))
3007 {
3008 *sec = uptime;
3009 *usec = (uptime - *sec) * 1000000;
3010 }
3011 fclose (fup);
3012 }
3013 UNBLOCK_INPUT;
3014}
3015
3016#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
3017#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
3018
3019static Lisp_Object
f4f634e8 3020procfs_ttyname (int rdev)
06e111a6
DN
3021{
3022 FILE *fdev = NULL;
3023 char name[PATH_MAX];
3024
3025 BLOCK_INPUT;
3026 fdev = fopen ("/proc/tty/drivers", "r");
3027
3028 if (fdev)
3029 {
3030 unsigned major;
3031 unsigned long minor_beg, minor_end;
3032 char minor[25]; /* 2 32-bit numbers + dash */
3033 char *endp;
3034
3035 while (!feof (fdev) && !ferror (fdev))
3036 {
3037 if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
3038 && major == MAJOR (rdev))
3039 {
3040 minor_beg = strtoul (minor, &endp, 0);
3041 if (*endp == '\0')
3042 minor_end = minor_beg;
3043 else if (*endp == '-')
3044 minor_end = strtoul (endp + 1, &endp, 0);
3045 else
3046 continue;
3047
3048 if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
3049 {
10d66ec0 3050 sprintf (name + strlen (name), "%u", MINOR (rdev));
06e111a6
DN
3051 break;
3052 }
3053 }
3054 }
3055 fclose (fdev);
3056 }
3057 UNBLOCK_INPUT;
3058 return build_string (name);
3059}
3060
3061static unsigned long
3062procfs_get_total_memory (void)
3063{
3064 FILE *fmem = NULL;
3065 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
3066
3067 BLOCK_INPUT;
3068 fmem = fopen ("/proc/meminfo", "r");
3069
3070 if (fmem)
3071 {
3072 unsigned long entry_value;
3073 char entry_name[20]; /* the longest I saw is 13+1 */
3074
3075 while (!feof (fmem) && !ferror (fmem))
3076 {
3077 if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
3078 && strcmp (entry_name, "MemTotal:") == 0)
3079 {
3080 retval = entry_value;
3081 break;
3082 }
3083 }
3084 fclose (fmem);
3085 }
3086 UNBLOCK_INPUT;
3087 return retval;
3088}
3089
3090Lisp_Object
f4f634e8 3091system_process_attributes (Lisp_Object pid)
06e111a6
DN
3092{
3093 char procfn[PATH_MAX], fn[PATH_MAX];
3094 struct stat st;
3095 struct passwd *pw;
3096 struct group *gr;
3097 long clocks_per_sec;
3098 char *procfn_end;
3099 char procbuf[1025], *p, *q;
3100 int fd;
3101 ssize_t nread;
3102 const char *cmd = NULL;
3103 char *cmdline = NULL;
3104 size_t cmdsize = 0, cmdline_size;
3105 unsigned char c;
3106 int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
3107 unsigned long long utime, stime, cutime, cstime, start;
3108 long priority, nice, rss;
3109 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
3110 time_t sec;
3111 unsigned usec;
2b0a91e7 3112 EMACS_TIME tnow, tstart, tboot, telapsed;
06e111a6
DN
3113 double pcpu, pmem;
3114 Lisp_Object attrs = Qnil;
3115 Lisp_Object cmd_str, decoded_cmd, tem;
3116 struct gcpro gcpro1, gcpro2;
3117 EMACS_INT uid_eint, gid_eint;
3118
3119 CHECK_NUMBER_OR_FLOAT (pid);
3120 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
10d66ec0 3121 sprintf (procfn, "/proc/%u", proc_id);
06e111a6
DN
3122 if (stat (procfn, &st) < 0)
3123 return attrs;
3124
3125 GCPRO2 (attrs, decoded_cmd);
3126
3127 /* euid egid */
3128 uid = st.st_uid;
3129 /* Use of EMACS_INT stops GCC whining about limited range of data type. */
3130 uid_eint = uid;
3131 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
3132 BLOCK_INPUT;
3133 pw = getpwuid (uid);
3134 UNBLOCK_INPUT;
3135 if (pw)
3136 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3137
3138 gid = st.st_gid;
3139 gid_eint = gid;
3140 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
3141 BLOCK_INPUT;
3142 gr = getgrgid (gid);
3143 UNBLOCK_INPUT;
3144 if (gr)
3145 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3146
3147 strcpy (fn, procfn);
3148 procfn_end = fn + strlen (fn);
3149 strcpy (procfn_end, "/stat");
3150 fd = emacs_open (fn, O_RDONLY, 0);
cf84bb53 3151 if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof (procbuf) - 1)) > 0)
06e111a6
DN
3152 {
3153 procbuf[nread] = '\0';
3154 p = procbuf;
3155
3156 p = strchr (p, '(');
3157 if (p != NULL)
3158 {
3159 q = strrchr (p + 1, ')');
3160 /* comm */
3161 if (q != NULL)
3162 {
3163 cmd = p + 1;
3164 cmdsize = q - cmd;
3165 }
3166 }
3167 else
3168 q = NULL;
3169 if (cmd == NULL)
3170 {
3171 cmd = "???";
3172 cmdsize = 3;
3173 }
3174 /* Command name is encoded in locale-coding-system; decode it. */
3175 cmd_str = make_unibyte_string (cmd, cmdsize);
3176 decoded_cmd = code_convert_string_norecord (cmd_str,
3177 Vlocale_coding_system, 0);
3178 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3179
3180 if (q)
3181 {
3182 EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint;
3183 p = q + 2;
3184 /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */
3185 sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld",
3186 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
3187 &minflt, &cminflt, &majflt, &cmajflt,
3188 &utime, &stime, &cutime, &cstime,
3189 &priority, &nice, &thcount, &start, &vsize, &rss);
3190 {
3191 char state_str[2];
3192
3193 state_str[0] = c;
3194 state_str[1] = '\0';
3195 tem = build_string (state_str);
3196 attrs = Fcons (Fcons (Qstate, tem), attrs);
3197 }
3198 /* Stops GCC whining about limited range of data type. */
3199 ppid_eint = ppid;
3200 pgrp_eint = pgrp;
3201 sess_eint = sess;
3202 tpgid_eint = tpgid;
3203 thcount_eint = thcount;
3204 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs);
3205 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs);
3206 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs);
3207 attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
3208 attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs);
3209 attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs);
3210 attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs);
3211 attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs);
3212 attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs);
3213 clocks_per_sec = sysconf (_SC_CLK_TCK);
3214 if (clocks_per_sec < 0)
3215 clocks_per_sec = 100;
3216 attrs = Fcons (Fcons (Qutime,
3217 ltime_from_jiffies (utime, clocks_per_sec)),
3218 attrs);
3219 attrs = Fcons (Fcons (Qstime,
3220 ltime_from_jiffies (stime, clocks_per_sec)),
3221 attrs);
ac1e4171
EZ
3222 attrs = Fcons (Fcons (Qtime,
3223 ltime_from_jiffies (stime+utime, clocks_per_sec)),
3224 attrs);
06e111a6
DN
3225 attrs = Fcons (Fcons (Qcutime,
3226 ltime_from_jiffies (cutime, clocks_per_sec)),
3227 attrs);
3228 attrs = Fcons (Fcons (Qcstime,
3229 ltime_from_jiffies (cstime, clocks_per_sec)),
ac1e4171
EZ
3230 attrs);
3231 attrs = Fcons (Fcons (Qctime,
3232 ltime_from_jiffies (cstime+cutime, clocks_per_sec)),
06e111a6
DN
3233 attrs);
3234 attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
3235 attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs);
3236 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
3237 EMACS_GET_TIME (tnow);
3238 get_up_time (&sec, &usec);
3239 EMACS_SET_SECS (telapsed, sec);
3240 EMACS_SET_USECS (telapsed, usec);
3241 EMACS_SUB_TIME (tboot, tnow, telapsed);
3242 time_from_jiffies (start, clocks_per_sec, &sec, &usec);
3243 EMACS_SET_SECS (tstart, sec);
3244 EMACS_SET_USECS (tstart, usec);
3245 EMACS_ADD_TIME (tstart, tboot, tstart);
3246 attrs = Fcons (Fcons (Qstart,
3247 list3 (make_number
3248 ((EMACS_SECS (tstart) >> 16) & 0xffff),
3249 make_number
3250 (EMACS_SECS (tstart) & 0xffff),
3251 make_number
3252 (EMACS_USECS (tstart)))),
3253 attrs);
3254 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
3255 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
3256 EMACS_SUB_TIME (telapsed, tnow, tstart);
3257 attrs = Fcons (Fcons (Qetime,
3258 list3 (make_number
3259 ((EMACS_SECS (telapsed) >> 16) & 0xffff),
3260 make_number
3261 (EMACS_SECS (telapsed) & 0xffff),
3262 make_number
3263 (EMACS_USECS (telapsed)))),
3264 attrs);
3265 time_from_jiffies (utime + stime, clocks_per_sec, &sec, &usec);
3266 pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
3267 if (pcpu > 1.0)
3268 pcpu = 1.0;
3269 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
3270 pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
3271 if (pmem > 100)
3272 pmem = 100;
3273 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
3274 }
3275 }
3276 if (fd >= 0)
3277 emacs_close (fd);
3278
3279 /* args */
3280 strcpy (procfn_end, "/cmdline");
3281 fd = emacs_open (fn, O_RDONLY, 0);
3282 if (fd >= 0)
3283 {
3284 for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++)
3285 {
3286 if (isspace (c) || c == '\\')
3287 cmdline_size++; /* for later quoting, see below */
3288 }
3289 if (cmdline_size)
3290 {
3291 cmdline = xmalloc (cmdline_size + 1);
3292 lseek (fd, 0L, SEEK_SET);
3293 cmdline[0] = '\0';
3294 if ((nread = read (fd, cmdline, cmdline_size)) >= 0)
3295 cmdline[nread++] = '\0';
3296 else
3297 {
3298 /* Assigning zero to `nread' makes us skip the following
3299 two loops, assign zero to cmdline_size, and enter the
3300 following `if' clause that handles unknown command
3301 lines. */
3302 nread = 0;
3303 }
3304 /* We don't want trailing null characters. */
3305 for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
3306 nread--;
3307 for (p = cmdline; p < cmdline + nread; p++)
3308 {
3309 /* Escape-quote whitespace and backslashes. */
3310 if (isspace (*p) || *p == '\\')
3311 {
3312 memmove (p + 1, p, nread - (p - cmdline));
3313 nread++;
3314 *p++ = '\\';
3315 }
3316 else if (*p == '\0')
3317 *p = ' ';
3318 }
3319 cmdline_size = nread;
3320 }
3321 if (!cmdline_size)
3322 {
3323 if (!cmd)
3324 cmd = "???";
3325 if (!cmdsize)
3326 cmdsize = strlen (cmd);
3327 cmdline_size = cmdsize + 2;
3328 cmdline = xmalloc (cmdline_size + 1);
3329 strcpy (cmdline, "[");
3330 strcat (strncat (cmdline, cmd, cmdsize), "]");
3331 }
3332 emacs_close (fd);
3333 /* Command line is encoded in locale-coding-system; decode it. */
3334 cmd_str = make_unibyte_string (cmdline, cmdline_size);
3335 decoded_cmd = code_convert_string_norecord (cmd_str,
3336 Vlocale_coding_system, 0);
3337 xfree (cmdline);
3338 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3339 }
3340
3341 UNGCPRO;
3342 return attrs;
3343}
91c85b70 3344
f4f634e8
DN
3345#elif defined (SOLARIS2) && defined (HAVE_PROCFS)
3346
3347/* The <procfs.h> header does not like to be included if _LP64 is defined and
3348 __FILE_OFFSET_BITS == 64. This is an ugly workaround that. */
3349#if !defined (_LP64) && defined (_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
3350#define PROCFS_FILE_OFFSET_BITS_HACK 1
3351#undef _FILE_OFFSET_BITS
3352#else
3353#define PROCFS_FILE_OFFSET_BITS_HACK 0
3354#endif
3355
3356#include <procfs.h>
3357
3358#if PROCFS_FILE_OFFSET_BITS_HACK == 1
3359#define _FILE_OFFSET_BITS 64
3360#endif /* PROCFS_FILE_OFFSET_BITS_HACK == 1 */
3361
3362Lisp_Object
3363system_process_attributes (Lisp_Object pid)
3364{
3365 char procfn[PATH_MAX], fn[PATH_MAX];
3366 struct stat st;
3367 struct passwd *pw;
3368 struct group *gr;
3369 char *procfn_end;
3370 struct psinfo pinfo;
3371 int fd;
3372 ssize_t nread;
3373 int proc_id, uid, gid;
3374 Lisp_Object attrs = Qnil;
3375 Lisp_Object decoded_cmd, tem;
3376 struct gcpro gcpro1, gcpro2;
3377 EMACS_INT uid_eint, gid_eint;
3378
3379 CHECK_NUMBER_OR_FLOAT (pid);
3380 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
3381 sprintf (procfn, "/proc/%u", proc_id);
3382 if (stat (procfn, &st) < 0)
3383 return attrs;
3384
3385 GCPRO2 (attrs, decoded_cmd);
3386
3387 /* euid egid */
3388 uid = st.st_uid;
3389 /* Use of EMACS_INT stops GCC whining about limited range of data type. */
3390 uid_eint = uid;
3391 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
3392 BLOCK_INPUT;
3393 pw = getpwuid (uid);
3394 UNBLOCK_INPUT;
3395 if (pw)
3396 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3397
3398 gid = st.st_gid;
3399 gid_eint = gid;
3400 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
3401 BLOCK_INPUT;
3402 gr = getgrgid (gid);
3403 UNBLOCK_INPUT;
3404 if (gr)
3405 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3406
3407 strcpy (fn, procfn);
3408 procfn_end = fn + strlen (fn);
3409 strcpy (procfn_end, "/psinfo");
3410 fd = emacs_open (fn, O_RDONLY, 0);
3411 if (fd >= 0
cf84bb53 3412 && (nread = read (fd, (char*)&pinfo, sizeof (struct psinfo)) > 0))
f4f634e8
DN
3413 {
3414 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (pinfo.pr_ppid)), attrs);
3415 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pinfo.pr_pgid)), attrs);
3416 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (pinfo.pr_sid)), attrs);
3417
3418 {
3419 char state_str[2];
3420 state_str[0] = pinfo.pr_lwp.pr_sname;
3421 state_str[1] = '\0';
3422 tem = build_string (state_str);
3423 attrs = Fcons (Fcons (Qstate, tem), attrs);
3424 }
3425
3426 /* FIXME: missing Qttyname. psinfo.pr_ttydev is a dev_t,
3427 need to get a string from it. */
3428
3429 /* FIXME: missing: Qtpgid */
3430
3431 /* FIXME: missing:
3432 Qminflt
3433 Qmajflt
3434 Qcminflt
3435 Qcmajflt
3436
bfe11752
DN
3437 Qutime
3438 Qcutime
f4f634e8
DN
3439 Qstime
3440 Qcstime
3441 Are they available? */
3442
bfe11752 3443 attrs = Fcons (Fcons (Qtime,
f4f634e8
DN
3444 list3 (make_number (pinfo.pr_time.tv_sec >> 16),
3445 make_number (pinfo.pr_time.tv_sec & 0xffff),
3446 make_number (pinfo.pr_time.tv_nsec))),
3447 attrs);
3448
bfe11752 3449 attrs = Fcons (Fcons (Qctime,
f4f634e8
DN
3450 list3 (make_number (pinfo.pr_ctime.tv_sec >> 16),
3451 make_number (pinfo.pr_ctime.tv_sec & 0xffff),
3452 make_number (pinfo.pr_ctime.tv_nsec))),
3453 attrs);
3454
3455 attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs);
3456 attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs);
3457 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs);
3458
3459 attrs = Fcons (Fcons (Qstart,
3460 list3 (make_number (pinfo.pr_start.tv_sec >> 16),
3461 make_number (pinfo.pr_start.tv_sec & 0xffff),
3462 make_number (pinfo.pr_start.tv_nsec))),
3463 attrs);
3464 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs);
3465 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs);
3466
3467 /* pr_pctcpu and pr_pctmem are encoded as a fixed point 16 bit number in [0 ... 1]. */
3468 attrs = Fcons (Fcons (Qpcpu, (pinfo.pr_pctcpu * 100.0) / (double)0x8000), attrs);
3469 attrs = Fcons (Fcons (Qpmem, (pinfo.pr_pctmem * 100.0) / (double)0x8000), attrs);
3470
3471 decoded_cmd
3472 = code_convert_string_norecord (make_unibyte_string (pinfo.pr_fname,
3473 strlen (pinfo.pr_fname)),
3474 Vlocale_coding_system, 0);
3475 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3476 decoded_cmd
3477 = code_convert_string_norecord (make_unibyte_string (pinfo.pr_psargs,
3478 strlen (pinfo.pr_psargs)),
3479 Vlocale_coding_system, 0);
3480 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3481 }
3482
2d2d05d8
DN
3483 if (fd >= 0)
3484 emacs_close (fd);
3485
f4f634e8
DN
3486 UNGCPRO;
3487 return attrs;
3488}
06e111a6 3489
f8d23104
DN
3490/* The WINDOWSNT implementation is in w32.c.
3491 The MSDOS implementation is in dosfns.c. */
c4605e09 3492#elif !defined (WINDOWSNT) && !defined (MSDOS)
06e111a6
DN
3493
3494Lisp_Object
3495system_process_attributes (Lisp_Object pid)
3496{
9dcbe89b 3497 return Qnil;
06e111a6
DN
3498}
3499
3500#endif /* !defined (WINDOWSNT) */
3501
c4ea52a6 3502
ab5796a9
MB
3503/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
3504 (do not change this comment) */