Assume POSIX 1003.1-1988 or later for dirent.h.
[bpt/emacs.git] / src / sysdep.c
CommitLineData
86a5659e 1/* Interfaces to system-dependent kernel and library entries.
acaf905b 2 Copyright (C) 1985-1988, 1993-1995, 1999-2012
8cabe764 3 Free Software Foundation, Inc.
86a5659e
JB
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
86a5659e 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
86a5659e
JB
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
86a5659e 19
4838e624 20#include <config.h>
f162bcc3
PE
21
22#define SYSTIME_INLINE EXTERN_INLINE
23
cf29dd84 24#include <execinfo.h>
5890e9f7 25#include <stdio.h>
06e111a6
DN
26#ifdef HAVE_PWD_H
27#include <pwd.h>
28#include <grp.h>
29#endif /* HAVE_PWD_H */
06e111a6 30#include <limits.h>
d3eb3bfa 31#include <unistd.h>
53934c98 32
d1fdcab7 33#include <allocator.h>
620f13b0 34#include <c-ctype.h>
d1fdcab7 35#include <careadlinkat.h>
67342916 36#include <ignore-value.h>
d35af63c 37#include <utimens.h>
67342916 38
86a5659e 39#include "lisp.h"
819b8f00 40#include "sysselect.h"
9ac0d9e0 41#include "blockinput.h"
86a5659e 42
7dca65a4
PE
43#ifdef BSD_SYSTEM
44#include <sys/param.h>
b91b7e4d 45#include <sys/sysctl.h>
7dca65a4
PE
46#endif
47
48#ifdef __FreeBSD__
b91b7e4d 49#include <sys/user.h>
d054f3fb 50#include <sys/resource.h>
b91b7e4d
EW
51#include <math.h>
52#endif
53
fe03522b 54#ifdef WINDOWSNT
e15b6288
JR
55#define read sys_read
56#define write sys_write
62aba0d4
FP
57#ifndef STDERR_FILENO
58#define STDERR_FILENO fileno(GetStdHandle(STD_ERROR_HANDLE))
59#endif
fe03522b 60#include <windows.h>
fe03522b
RS
61#endif /* not WINDOWSNT */
62
86a5659e
JB
63#include <sys/types.h>
64#include <sys/stat.h>
65#include <errno.h>
66
b05af5d3
PE
67/* Get SI_SRPC_DOMAIN, if it is available. */
68#ifdef HAVE_SYS_SYSTEMINFO_H
69#include <sys/systeminfo.h>
70#endif
71
207bdbdb 72#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
207bdbdb
RS
73#include "msdos.h"
74#include <sys/param.h>
15614e61 75#endif
207bdbdb 76
bb4bc8e2 77#include <sys/file.h>
bb4bc8e2 78#include <fcntl.h>
86a5659e 79
e04a4e0d 80#include "systty.h"
94c8642a 81#include "syswait.h"
86a5659e 82
a7ebc409 83#ifdef HAVE_SYS_UTSNAME_H
86a5659e 84#include <sys/utsname.h>
86a5659e 85#include <memory.h>
a7ebc409 86#endif /* HAVE_SYS_UTSNAME_H */
86a5659e 87
e36ec798 88#include "keyboard.h"
0137dbf7 89#include "frame.h"
86a5659e
JB
90#include "window.h"
91#include "termhooks.h"
92#include "termchar.h"
93#include "termopts.h"
94#include "dispextern.h"
95#include "process.h"
0a125897 96#include "cm.h" /* for reset_sys_modes */
86a5659e 97
fe03522b
RS
98#ifdef WINDOWSNT
99#include <direct.h>
100/* In process.h which conflicts with the local copy. */
101#define _P_WAIT 0
43db14bb
JB
102int _cdecl _spawnlp (int, const char *, const char *, ...);
103int _cdecl _getpid (void);
fe03522b
RS
104#endif
105
91bac16a
JB
106#include "syssignal.h"
107#include "systime.h"
86a5659e 108
1fa53021
PE
109static int emacs_get_tty (int, struct emacs_tty *);
110static int emacs_set_tty (int, struct emacs_tty *, int);
111
5a16b9bc
PE
112/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */
113#ifndef ULLONG_MAX
114#define ULLONG_MAX TYPE_MAXIMUM (unsigned long long int)
115#endif
116
ff2e8052
DN
117/* Declare here, including term.h is problematic on some systems. */
118extern void tputs (const char *, int, int (*)(int));
119
91433552 120static const int baud_convert[] =
86a5659e
JB
121 {
122 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
123 1800, 2400, 4800, 9600, 19200, 38400
124 };
86a5659e 125
f78f1a83 126
3480d92b 127#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
f78f1a83 128
b6682dd9 129/* Return the current working directory. Returns NULL on errors.
f78f1a83
EZ
130 Any other returned value must be freed with free. This is used
131 only when get_current_dir_name is not defined on the system. */
132char*
cf84bb53 133get_current_dir_name (void)
f78f1a83
EZ
134{
135 char *buf;
9239d970 136 char *pwd = getenv ("PWD");
f78f1a83 137 struct stat dotstat, pwdstat;
9239d970 138 /* If PWD is accurate, use it instead of calling getcwd. PWD is
f78f1a83
EZ
139 sometimes a nicer name, and using it may avoid a fatal error if a
140 parent directory is searchable but not readable. */
9239d970 141 if (pwd
f78f1a83
EZ
142 && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
143 && stat (pwd, &pwdstat) == 0
144 && stat (".", &dotstat) == 0
145 && dotstat.st_ino == pwdstat.st_ino
146 && dotstat.st_dev == pwdstat.st_dev
147#ifdef MAXPATHLEN
148 && strlen (pwd) < MAXPATHLEN
149#endif
150 )
151 {
38182d90 152 buf = malloc (strlen (pwd) + 1);
f78f1a83
EZ
153 if (!buf)
154 return NULL;
155 strcpy (buf, pwd);
156 }
f78f1a83
EZ
157 else
158 {
159 size_t buf_size = 1024;
38182d90 160 buf = malloc (buf_size);
f78f1a83
EZ
161 if (!buf)
162 return NULL;
163 for (;;)
164 {
165 if (getcwd (buf, buf_size) == buf)
166 break;
167 if (errno != ERANGE)
168 {
169 int tmp_errno = errno;
170 free (buf);
171 errno = tmp_errno;
172 return NULL;
173 }
174 buf_size *= 2;
38182d90 175 buf = realloc (buf, buf_size);
f78f1a83
EZ
176 if (!buf)
177 return NULL;
178 }
179 }
f78f1a83
EZ
180 return buf;
181}
182#endif
183
64e971c3 184\f
9628b887 185/* Discard pending input on all input descriptors. */
91bac16a 186
08633194 187void
971de7fb 188discard_tty_input (void)
86a5659e 189{
fe03522b 190#ifndef WINDOWSNT
91bac16a 191 struct emacs_tty buf;
86a5659e
JB
192
193 if (noninteractive)
194 return;
195
fe03522b 196#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
207bdbdb 197 while (dos_keyread () != -1)
fe03522b 198 ;
207bdbdb 199#else /* not MSDOS */
9628b887 200 {
28d7d09f 201 struct tty_display_info *tty;
9628b887
KL
202 for (tty = tty_list; tty; tty = tty->next)
203 {
0b0d3e0b
KL
204 if (tty->input) /* Is the device suspended? */
205 {
12e610e8
DN
206 emacs_get_tty (fileno (tty->input), &buf);
207 emacs_set_tty (fileno (tty->input), &buf, 0);
0b0d3e0b 208 }
9628b887
KL
209 }
210 }
207bdbdb 211#endif /* not MSDOS */
fe03522b 212#endif /* not WINDOWSNT */
86a5659e
JB
213}
214
16c290d8 215\f
86a5659e
JB
216#ifdef SIGTSTP
217
64e971c3 218/* Arrange for character C to be read as the next input from
16c290d8
KL
219 the terminal.
220 XXX What if we have multiple ttys?
221*/
64e971c3 222
dfcf069d 223void
0c2338d8 224stuff_char (char c)
86a5659e 225{
428a555e 226 if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
23dab951
RS
227 return;
228
86a5659e
JB
229/* Should perhaps error if in batch mode */
230#ifdef TIOCSTI
0b0d3e0b 231 ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
86a5659e 232#else /* no TIOCSTI */
71f06467 233 error ("Cannot stuff terminal input characters in this version of Unix");
86a5659e
JB
234#endif /* no TIOCSTI */
235}
236
237#endif /* SIGTSTP */
64e971c3 238\f
08633194 239void
16c290d8 240init_baud_rate (int fd)
86a5659e 241{
4c620157 242 int emacs_ospeed;
67342916 243
86a5659e 244 if (noninteractive)
5bdd7bdd 245 emacs_ospeed = 0;
86a5659e
JB
246 else
247 {
fe03522b 248#ifdef DOS_NT
5bdd7bdd 249 emacs_ospeed = 15;
fe03522b 250#else /* not DOS_NT */
e04a4e0d 251 struct termios sg;
91bac16a 252
71f06467 253 sg.c_cflag = B9600;
16c290d8 254 tcgetattr (fd, &sg);
5bdd7bdd 255 emacs_ospeed = cfgetospeed (&sg);
fe03522b 256#endif /* not DOS_NT */
86a5659e 257 }
177c0ea7 258
5bdd7bdd
GM
259 baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
260 ? baud_convert[emacs_ospeed] : 9600);
86a5659e
JB
261 if (baud_rate == 0)
262 baud_rate = 1200;
263}
264
16c290d8 265\f
86a5659e 266
77defa9a 267#ifndef MSDOS
86a5659e 268
e7a6747f 269static void
d311d28c 270wait_for_termination_1 (pid_t pid, int interruptible)
86a5659e
JB
271{
272 while (1)
273 {
4d7e6e51
PE
274 int status;
275 int wait_result = waitpid (pid, &status, 0);
276 if (wait_result < 0)
9ab714c7 277 {
4d7e6e51
PE
278 if (errno != EINTR)
279 break;
280 }
281 else
282 {
283 record_child_status_change (wait_result, status);
9ab714c7
RS
284 break;
285 }
ac3ac859 286
22bae83f
EZ
287 /* Note: the MS-Windows emulation of waitpid calls QUIT
288 internally. */
1ef14cb4
LMI
289 if (interruptible)
290 QUIT;
86a5659e
JB
291 }
292}
293
e7a6747f
AS
294/* Wait for subprocess with process id `pid' to terminate and
295 make sure it will get eliminated (not remain forever as a zombie) */
296
297void
d311d28c 298wait_for_termination (pid_t pid)
e7a6747f
AS
299{
300 wait_for_termination_1 (pid, 0);
301}
302
303/* Like the above, but allow keyboard interruption. */
304void
d311d28c 305interruptible_wait_for_termination (pid_t pid)
e7a6747f
AS
306{
307 wait_for_termination_1 (pid, 1);
308}
309
86a5659e
JB
310/*
311 * flush any pending output
312 * (may flush input as well; it does not matter the way we use it)
313 */
177c0ea7 314
08633194 315void
971de7fb 316flush_pending_output (int channel)
86a5659e 317{
9de940b5 318 /* FIXME: maybe this function should be removed */
86a5659e 319}
64e971c3 320\f
86a5659e
JB
321/* Set up the terminal at the other end of a pseudo-terminal that
322 we will be controlling an inferior through.
323 It should not echo or do line-editing, since that is done
324 in Emacs. No padding needed for insertion into an Emacs buffer. */
325
08633194 326void
971de7fb 327child_setup_tty (int out)
86a5659e 328{
77defa9a 329#ifndef WINDOWSNT
91bac16a
JB
330 struct emacs_tty s;
331
12e610e8 332 emacs_get_tty (out, &s);
91bac16a
JB
333 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
334 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
9d4e5eea 335#ifdef NLDLY
07cfc4e7
GM
336 /* http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00406.html
337 Some versions of GNU Hurd do not have FFDLY? */
338#ifdef FFDLY
91bac16a
JB
339 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
340 /* No output delays */
07cfc4e7
GM
341#else
342 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
343 /* No output delays */
344#endif
9d4e5eea 345#endif
91bac16a
JB
346 s.main.c_lflag &= ~ECHO; /* Disable echo */
347 s.main.c_lflag |= ISIG; /* Enable signals */
9d4e5eea
RS
348#ifdef IUCLC
349 s.main.c_iflag &= ~IUCLC; /* Disable downcasing on input. */
350#endif
f7097b2a
RS
351#ifdef ISTRIP
352 s.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
353#endif
23e4c8be 354#ifdef OLCUC
9d4e5eea
RS
355 s.main.c_oflag &= ~OLCUC; /* Disable upcasing on output. */
356#endif
f7097b2a 357 s.main.c_oflag &= ~TAB3; /* Disable tab expansion */
1bf96fb5 358 s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
441f6399
RS
359 s.main.c_cc[VERASE] = CDISABLE; /* disable erase processing */
360 s.main.c_cc[VKILL] = CDISABLE; /* disable kill processing */
91bac16a 361
86a5659e 362#ifdef HPUX
91bac16a 363 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
86a5659e 364#endif /* HPUX */
91bac16a 365
dfe598b5
RS
366#ifdef SIGNALS_VIA_CHARACTERS
367 /* the QUIT and INTR character are used in process_send_signal
368 so set them here to something useful. */
fa51fa32 369 if (s.main.c_cc[VQUIT] == CDISABLE)
dfe598b5 370 s.main.c_cc[VQUIT] = '\\'&037; /* Control-\ */
fa51fa32 371 if (s.main.c_cc[VINTR] == CDISABLE)
dfe598b5
RS
372 s.main.c_cc[VINTR] = 'C'&037; /* Control-C */
373#endif /* not SIGNALS_VIA_CHARACTERS */
374
86a5659e 375#ifdef AIX
86a5659e
JB
376 /* Also, PTY overloads NUL and BREAK.
377 don't ignore break, but don't signal either, so it looks like NUL. */
91bac16a
JB
378 s.main.c_iflag &= ~IGNBRK;
379 s.main.c_iflag &= ~BRKINT;
dfe598b5
RS
380 /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
381 unconditionally. Then a SIGNALS_VIA_CHARACTERS conditional
382 would force it to 0377. That looks like duplicated code. */
91bac16a 383 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
86a5659e
JB
384#endif /* AIX */
385
aaa0a19a 386 /* We originally enabled ICANON (and set VEOF to 04), and then had
c80e3b4a 387 process.c send additional EOF chars to flush the output when faced
aaa0a19a 388 with long lines, but this leads to weird effects when the
2b0a91e7
SM
389 subprocess has disabled ICANON and ends up seeing those spurious
390 extra EOFs. So we don't send EOFs any more in
aaa0a19a
SM
391 process.c:send_process. First we tried to disable ICANON by
392 default, so if a subsprocess sets up ICANON, it's his problem (or
393 the Elisp package that talks to it) to deal with lines that are
394 too long. But this disables some features, such as the ability
395 to send EOF signals. So we re-enabled ICANON but there is no
396 more "send eof to flush" going on (which is wrong and unportable
397 in itself). The correct way to handle too much output is to
398 buffer what could not be written and then write it again when
399 select returns ok for writing. This has it own set of
400 problems. Write is now asynchronous, is that a problem? How much
401 do we buffer, and what do we do when that limit is reached? */
9a747ba6
JD
402
403 s.main.c_lflag |= ICANON; /* Enable line editing and eof processing */
404 s.main.c_cc[VEOF] = 'D'&037; /* Control-D */
3d15fe78 405#if 0 /* These settings only apply to non-ICANON mode. */
2b0a91e7
SM
406 s.main.c_cc[VMIN] = 1;
407 s.main.c_cc[VTIME] = 0;
aaa0a19a 408#endif
2b0a91e7 409
12e610e8 410 emacs_set_tty (out, &s, 0);
77defa9a 411#endif /* not WINDOWSNT */
86a5659e 412}
57507bf8 413#endif /* not MSDOS */
86a5659e 414
64e971c3 415\f
2fe28299 416/* Record a signal code and the action for it. */
86a5659e
JB
417struct save_signal
418{
419 int code;
2fe28299 420 struct sigaction action;
86a5659e
JB
421};
422
f57e2426
J
423static void save_signal_handlers (struct save_signal *);
424static void restore_signal_handlers (struct save_signal *);
35a05cca 425
86a5659e
JB
426/* Suspend the Emacs process; give terminal to its superior. */
427
08633194 428void
971de7fb 429sys_suspend (void)
86a5659e 430{
c4ea52a6 431#if defined (SIGTSTP) && !defined (MSDOS)
86a5659e 432
5a570e37 433 {
dd0333b6 434 pid_t pgrp = getpgrp ();
5a570e37
JB
435 EMACS_KILLPG (pgrp, SIGTSTP);
436 }
86a5659e
JB
437
438#else /* No SIGTSTP */
86a5659e
JB
439/* On a system where suspending is not implemented,
440 instead fork a subshell and let it talk directly to the terminal
441 while we wait. */
a0932daa
KH
442 sys_subshell ();
443
a0932daa 444#endif /* no SIGTSTP */
a0932daa
KH
445}
446
447/* Fork a subshell. */
448
08633194 449void
971de7fb 450sys_subshell (void)
a0932daa 451{
ad00c243 452#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
a0932daa
KH
453 int st;
454 char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
455#endif
efa04277 456 int pid;
86a5659e 457 struct save_signal saved_handlers[5];
efa04277 458 Lisp_Object dir;
5e41f65d 459 unsigned char *volatile str_volatile = 0;
7e9123a2 460 unsigned char *str;
efa04277 461 int len;
86a5659e
JB
462
463 saved_handlers[0].code = SIGINT;
464 saved_handlers[1].code = SIGQUIT;
465 saved_handlers[2].code = SIGTERM;
4a4bbad2 466#ifdef USABLE_SIGIO
86a5659e
JB
467 saved_handlers[3].code = SIGIO;
468 saved_handlers[4].code = 0;
469#else
470 saved_handlers[3].code = 0;
471#endif
472
efa04277
RS
473 /* Mentioning current_buffer->buffer would mean including buffer.h,
474 which somehow wedges the hp compiler. So instead... */
475
476 dir = intern ("default-directory");
0e7e7a58 477 if (NILP (Fboundp (dir)))
efa04277
RS
478 goto xyzzy;
479 dir = Fsymbol_value (dir);
914e81a2 480 if (!STRINGP (dir))
efa04277
RS
481 goto xyzzy;
482
483 dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
38182d90 484 str_volatile = str = alloca (SCHARS (dir) + 2);
d5db4077 485 len = SCHARS (dir);
72af86bd 486 memcpy (str, SDATA (dir), len);
efa04277
RS
487 if (str[len - 1] != '/') str[len++] = '/';
488 str[len] = 0;
489 xyzzy:
490
ad00c243 491#ifdef DOS_NT
7964ba9e 492 pid = 0;
718ca3cf
RS
493 save_signal_handlers (saved_handlers);
494 synch_process_alive = 1;
177c0ea7 495#else
efa04277 496 pid = vfork ();
86a5659e
JB
497 if (pid == -1)
498 error ("Can't spawn subshell");
7964ba9e
RS
499#endif
500
86a5659e
JB
501 if (pid == 0)
502 {
8ea90aa3 503 const char *sh = 0;
86a5659e 504
ad00c243 505#ifdef DOS_NT /* MW, Aug 1993 */
9239d970 506 getcwd (oldwd, sizeof oldwd);
7964ba9e
RS
507 if (sh == 0)
508 sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
207bdbdb 509#endif
7964ba9e
RS
510 if (sh == 0)
511 sh = (char *) egetenv ("SHELL");
86a5659e
JB
512 if (sh == 0)
513 sh = "sh";
207bdbdb 514
86a5659e 515 /* Use our buffer's default directory for the subshell. */
5e41f65d 516 str = str_volatile;
32299e33
PE
517 if (str && chdir ((char *) str) != 0)
518 {
519#ifndef DOS_NT
520 ignore_value (write (1, "Can't chdir\n", 12));
521 _exit (1);
522#endif
523 }
efa04277 524
86a5659e 525 close_process_descs (); /* Close Emacs's pipes/ptys */
1593c2fe 526
fe03522b 527#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
c0917202 528 {
48178f9a
EZ
529 char *epwd = getenv ("PWD");
530 char old_pwd[MAXPATHLEN+1+4];
c0917202
EZ
531
532 /* If PWD is set, pass it with corrected value. */
48178f9a 533 if (epwd)
c0917202 534 {
48178f9a 535 strcpy (old_pwd, epwd);
c0917202
EZ
536 if (str[len - 1] == '/')
537 str[len - 1] = '\0';
538 setenv ("PWD", str, 1);
539 }
540 st = system (sh);
32299e33 541 chdir (oldwd); /* FIXME: Do the right thing on chdir failure. */
48178f9a 542 if (epwd)
c0917202
EZ
543 putenv (old_pwd); /* restore previous value */
544 }
207bdbdb 545#else /* not MSDOS */
fe03522b 546#ifdef WINDOWSNT
fe03522b
RS
547 /* Waits for process completion */
548 pid = _spawnlp (_P_WAIT, sh, sh, NULL);
32299e33 549 chdir (oldwd); /* FIXME: Do the right thing on chdir failure. */
fe03522b
RS
550 if (pid == -1)
551 write (1, "Can't execute subshell", 22);
fe03522b 552#else /* not WINDOWSNT */
e120ea40 553 execlp (sh, sh, (char *) 0);
67342916 554 ignore_value (write (1, "Can't execute subshell", 22));
86a5659e 555 _exit (1);
fe03522b 556#endif /* not WINDOWSNT */
207bdbdb 557#endif /* not MSDOS */
86a5659e
JB
558 }
559
718ca3cf 560 /* Do this now if we did not do it before. */
ed68db4d 561#ifndef MSDOS
86a5659e 562 save_signal_handlers (saved_handlers);
ffafc793 563 synch_process_alive = 1;
718ca3cf
RS
564#endif
565
ad00c243 566#ifndef DOS_NT
86a5659e 567 wait_for_termination (pid);
7964ba9e 568#endif
86a5659e 569 restore_signal_handlers (saved_handlers);
718ca3cf 570 synch_process_alive = 0;
86a5659e
JB
571}
572
35a05cca 573static void
971de7fb 574save_signal_handlers (struct save_signal *saved_handlers)
86a5659e
JB
575{
576 while (saved_handlers->code)
577 {
2fe28299
PE
578 struct sigaction action;
579 emacs_sigaction_init (&action, SIG_IGN);
580 sigaction (saved_handlers->code, &action, &saved_handlers->action);
86a5659e
JB
581 saved_handlers++;
582 }
583}
584
35a05cca 585static void
971de7fb 586restore_signal_handlers (struct save_signal *saved_handlers)
86a5659e
JB
587{
588 while (saved_handlers->code)
589 {
2fe28299 590 sigaction (saved_handlers->code, &saved_handlers->action, 0);
86a5659e
JB
591 saved_handlers++;
592 }
593}
594\f
4a4bbad2 595#ifdef USABLE_SIGIO
1fa53021 596static int old_fcntl_flags[MAXDESC];
4a4bbad2 597#endif
86a5659e 598
08633194 599void
971de7fb 600init_sigio (int fd)
86a5659e 601{
4a4bbad2 602#ifdef USABLE_SIGIO
819b8f00
KL
603 old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
604 fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
23dab951 605 interrupts_deferred = 0;
4a4bbad2 606#endif
86a5659e
JB
607}
608
604efe86 609static void
971de7fb 610reset_sigio (int fd)
86a5659e 611{
4a4bbad2 612#ifdef USABLE_SIGIO
819b8f00 613 fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
4d553a13 614#endif
86a5659e
JB
615}
616
08633194 617void
971de7fb 618request_sigio (void)
86a5659e 619{
4a4bbad2 620#ifdef USABLE_SIGIO
2fe28299
PE
621 sigset_t unblocked;
622
6bbba5a6 623 if (noninteractive)
23dab951
RS
624 return;
625
2fe28299 626 sigemptyset (&unblocked);
4a4bbad2 627# ifdef SIGWINCH
2fe28299 628 sigaddset (&unblocked, SIGWINCH);
4a4bbad2 629# endif
2fe28299
PE
630 sigaddset (&unblocked, SIGIO);
631 pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
86a5659e
JB
632
633 interrupts_deferred = 0;
4a4bbad2 634#endif
86a5659e
JB
635}
636
08633194 637void
0a125897 638unrequest_sigio (void)
cf84bb53 639{
4a4bbad2 640#ifdef USABLE_SIGIO
2fe28299
PE
641 sigset_t blocked;
642
6bbba5a6
KL
643 if (noninteractive)
644 return;
645
2fe28299 646 sigemptyset (&blocked);
4a4bbad2 647# ifdef SIGWINCH
2fe28299 648 sigaddset (&blocked, SIGWINCH);
4a4bbad2 649# endif
2fe28299
PE
650 sigaddset (&blocked, SIGIO);
651 pthread_sigmask (SIG_BLOCK, &blocked, 0);
86a5659e 652 interrupts_deferred = 1;
4a4bbad2 653#endif
86a5659e 654}
177c0ea7 655
08633194 656void
4a4bbad2 657ignore_sigio (void)
86a5659e 658{
4a4bbad2
PE
659#ifdef USABLE_SIGIO
660 signal (SIGIO, SIG_IGN);
661#endif
86a5659e 662}
feb67dfe 663
9ae8f997 664\f
322aea6d
PE
665/* Saving and restoring the process group of Emacs's terminal. */
666
667/* The process group of which Emacs was a member when it initially
668 started.
669
670 If Emacs was in its own process group (i.e. inherited_pgroup ==
671 getpid ()), then we know we're running under a shell with job
672 control (Emacs would never be run as part of a pipeline).
673 Everything is fine.
674
675 If Emacs was not in its own process group, then we know we're
676 running under a shell (or a caller) that doesn't know how to
677 separate itself from Emacs (like sh). Emacs must be in its own
678 process group in order to receive SIGIO correctly. In this
679 situation, we put ourselves in our own pgroup, forcibly set the
680 tty's pgroup to our pgroup, and make sure to restore and reinstate
681 the tty's pgroup just like any other terminal setting. If
682 inherited_group was not the tty's pgroup, then we'll get a
683 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
684 it goes foreground in the future, which is what should happen. */
685
686static pid_t inherited_pgroup;
687
688void
689init_foreground_group (void)
690{
dd0333b6 691 pid_t pgrp = getpgrp ();
322aea6d
PE
692 inherited_pgroup = getpid () == pgrp ? 0 : pgrp;
693}
694
695/* Safely set a controlling terminal FD's process group to PGID.
696 If we are not in the foreground already, POSIX requires tcsetpgrp
697 to deliver a SIGTTOU signal, which would stop us. This is an
698 annoyance, so temporarily ignore the signal.
699
700 In practice, platforms lacking SIGTTOU also lack tcsetpgrp, so
701 skip all this unless SIGTTOU is defined. */
702static void
703tcsetpgrp_without_stopping (int fd, pid_t pgid)
704{
705#ifdef SIGTTOU
706 signal_handler_t handler;
707 block_input ();
708 handler = signal (SIGTTOU, SIG_IGN);
709 tcsetpgrp (fd, pgid);
710 signal (SIGTTOU, handler);
711 unblock_input ();
712#endif
713}
714
715/* Split off the foreground process group to Emacs alone. When we are
716 in the foreground, but not started in our own process group,
717 redirect the tty device handle FD to point to our own process
718 group. FD must be the file descriptor of the controlling tty. */
719static void
720narrow_foreground_group (int fd)
721{
722 if (inherited_pgroup && setpgid (0, 0) == 0)
723 tcsetpgrp_without_stopping (fd, getpid ());
724}
725
726/* Set the tty to our original foreground group. */
727static void
728widen_foreground_group (int fd)
729{
730 if (inherited_pgroup && setpgid (0, inherited_pgroup) == 0)
731 tcsetpgrp_without_stopping (fd, inherited_pgroup);
732}
733\f
68936329
JB
734/* Getting and setting emacs_tty structures. */
735
736/* Set *TC to the parameters associated with the terminal FD.
737 Return zero if all's well, or -1 if we ran into an error we
738 couldn't deal with. */
739int
971de7fb 740emacs_get_tty (int fd, struct emacs_tty *settings)
68936329
JB
741{
742 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
a7ebc409 743#ifndef DOS_NT
68936329 744 /* We have those nifty POSIX tcmumbleattr functions. */
72af86bd 745 memset (&settings->main, 0, sizeof (settings->main));
68936329
JB
746 if (tcgetattr (fd, &settings->main) < 0)
747 return -1;
68936329
JB
748#endif
749
750 /* We have survived the tempest. */
751 return 0;
752}
753
754
755/* Set the parameters of the tty on FD according to the contents of
394049ec 756 *SETTINGS. If FLUSHP is non-zero, we discard input.
68936329 757 Return 0 if all went well, and -1 if anything failed. */
394049ec 758
68936329 759int
971de7fb 760emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
68936329
JB
761{
762 /* Set the primary parameters - baud rate, character size, etcetera. */
a7ebc409 763#ifndef DOS_NT
e6cc3307 764 int i;
68936329
JB
765 /* We have those nifty POSIX tcmumbleattr functions.
766 William J. Smith <wjs@wiis.wang.com> writes:
c4ea52a6 767 "POSIX 1003.1 defines tcsetattr to return success if it was
68936329
JB
768 able to perform any of the requested actions, even if some
769 of the requested actions could not be performed.
770 We must read settings back to ensure tty setup properly.
771 AIX requires this to keep tty from hanging occasionally." */
eb8c3be9 772 /* This make sure that we don't loop indefinitely in here. */
e6cc3307 773 for (i = 0 ; i < 10 ; i++)
394049ec 774 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
68936329
JB
775 {
776 if (errno == EINTR)
777 continue;
778 else
779 return -1;
780 }
781 else
782 {
783 struct termios new;
784
72af86bd 785 memset (&new, 0, sizeof (new));
68936329
JB
786 /* Get the current settings, and see if they're what we asked for. */
787 tcgetattr (fd, &new);
e6cc3307
RS
788 /* We cannot use memcmp on the whole structure here because under
789 * aix386 the termios structure has some reserved field that may
790 * not be filled in.
791 */
792 if ( new.c_iflag == settings->main.c_iflag
793 && new.c_oflag == settings->main.c_oflag
794 && new.c_cflag == settings->main.c_cflag
795 && new.c_lflag == settings->main.c_lflag
c4ea52a6 796 && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
68936329 797 break;
e6cc3307
RS
798 else
799 continue;
68936329 800 }
68936329 801#endif
177c0ea7 802
68936329
JB
803 /* We have survived the tempest. */
804 return 0;
805}
806
807\f
86a5659e
JB
808
809#ifdef F_SETOWN
1fa53021 810static int old_fcntl_owner[MAXDESC];
86a5659e
JB
811#endif /* F_SETOWN */
812
86a5659e
JB
813/* This may also be defined in stdio,
814 but if so, this does no harm,
815 and using the same name avoids wasting the other one's space. */
816
9d9a7716 817#if defined (USG)
86a5659e
JB
818unsigned char _sobuf[BUFSIZ+8];
819#else
820char _sobuf[BUFSIZ];
821#endif
177c0ea7 822
da8e1115
KL
823/* Initialize the terminal mode on all tty devices that are currently
824 open. */
825
08633194 826void
28d440ab
KL
827init_all_sys_modes (void)
828{
28d7d09f 829 struct tty_display_info *tty;
16c290d8 830 for (tty = tty_list; tty; tty = tty->next)
28d440ab 831 init_sys_modes (tty);
28d440ab
KL
832}
833
da8e1115
KL
834/* Initialize the terminal mode on the given tty device. */
835
28d440ab 836void
971de7fb 837init_sys_modes (struct tty_display_info *tty_out)
86a5659e 838{
91bac16a 839 struct emacs_tty tty;
e112cc37 840 Lisp_Object terminal;
91bac16a 841
4ec5cb58
RS
842 Vtty_erase_char = Qnil;
843
86a5659e
JB
844 if (noninteractive)
845 return;
846
0b0d3e0b
KL
847 if (!tty_out->output)
848 return; /* The tty is suspended. */
cf84bb53 849
322aea6d
PE
850 narrow_foreground_group (fileno (tty_out->input));
851
2246281f 852 if (! tty_out->old_tty)
38182d90 853 tty_out->old_tty = xmalloc (sizeof *tty_out->old_tty);
cf84bb53 854
12e610e8 855 emacs_get_tty (fileno (tty_out->input), tty_out->old_tty);
23dab951 856
2246281f 857 tty = *tty_out->old_tty;
86a5659e 858
a7ebc409 859#if !defined (DOS_NT)
2246281f 860 XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
4ec5cb58 861
2246281f
KL
862 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
863 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
7f371164
RS
864#ifdef INLCR /* I'm just being cautious,
865 since I can't check how widespread INLCR is--rms. */
2246281f 866 tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
7f371164 867#endif
86a5659e 868#ifdef ISTRIP
2246281f 869 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
86a5659e 870#endif
2246281f
KL
871 tty.main.c_lflag &= ~ECHO; /* Disable echo */
872 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
e2b40c23 873#ifdef IEXTEN
2246281f 874 tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
e2b40c23 875#endif
2246281f
KL
876 tty.main.c_lflag |= ISIG; /* Enable signals */
877 if (tty_out->flow_control)
878 {
879 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
86a5659e 880#ifdef IXANY
2246281f 881 tty.main.c_iflag &= ~IXANY;
86a5659e 882#endif /* IXANY */
2246281f
KL
883 }
884 else
885 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
886 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
887 on output */
888 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
86a5659e 889#ifdef CS8
2246281f
KL
890 if (tty_out->meta_key)
891 {
892 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
893 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
894 }
86a5659e 895#endif
e112cc37
ET
896
897 XSETTERMINAL(terminal, tty_out->terminal);
898 if (!NILP (Fcontrolling_tty_p (terminal)))
2246281f
KL
899 {
900 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
901 /* Set up C-g for both SIGQUIT and SIGINT.
902 We don't know which we will get, but we handle both alike
903 so which one it really gives us does not matter. */
904 tty.main.c_cc[VQUIT] = quit_char;
905 }
906 else
907 {
908 /* We normally don't get interrupt or quit signals from tty
909 devices other than our controlling terminal; therefore,
910 we must handle C-g as normal input. Unfortunately, this
911 means that the interrupt and quit feature must be
912 disabled on secondary ttys, or we would not even see the
913 keypress.
cf84bb53 914
2246281f
KL
915 Note that even though emacsclient could have special code
916 to pass SIGINT to Emacs, we should _not_ enable
917 interrupt/quit keys for emacsclient frames. This means
918 that we can't break out of loops in C code from a
919 secondary tty frame, but we can always decide what
920 display the C-g came from, which is more important from a
921 usability point of view. (Consider the case when two
922 people work together using the same Emacs instance.) */
923 tty.main.c_cc[VINTR] = CDISABLE;
924 tty.main.c_cc[VQUIT] = CDISABLE;
925 }
926 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
927 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
86a5659e 928#ifdef VSWTCH
2246281f 929 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
91bac16a 930 of C-z */
86a5659e 931#endif /* VSWTCH */
cf84bb53 932
86a5659e 933#ifdef VSUSP
a7ebc409 934 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off handling of C-z. */
86a5659e
JB
935#endif /* VSUSP */
936#ifdef V_DSUSP
a7ebc409 937 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off handling of C-y. */
86a5659e 938#endif /* V_DSUSP */
e2b40c23 939#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
2246281f 940 tty.main.c_cc[VDSUSP] = CDISABLE;
e2b40c23 941#endif /* VDSUSP */
92c995de 942#ifdef VLNEXT
2246281f 943 tty.main.c_cc[VLNEXT] = CDISABLE;
92c995de
RS
944#endif /* VLNEXT */
945#ifdef VREPRINT
2246281f 946 tty.main.c_cc[VREPRINT] = CDISABLE;
92c995de
RS
947#endif /* VREPRINT */
948#ifdef VWERASE
2246281f 949 tty.main.c_cc[VWERASE] = CDISABLE;
92c995de
RS
950#endif /* VWERASE */
951#ifdef VDISCARD
2246281f 952 tty.main.c_cc[VDISCARD] = CDISABLE;
92c995de 953#endif /* VDISCARD */
c179a6d1 954
2246281f
KL
955 if (tty_out->flow_control)
956 {
421dd92f 957#ifdef VSTART
2246281f 958 tty.main.c_cc[VSTART] = '\021';
421dd92f
RS
959#endif /* VSTART */
960#ifdef VSTOP
2246281f 961 tty.main.c_cc[VSTOP] = '\023';
421dd92f 962#endif /* VSTOP */
2246281f
KL
963 }
964 else
965 {
c179a6d1 966#ifdef VSTART
2246281f 967 tty.main.c_cc[VSTART] = CDISABLE;
c179a6d1
RS
968#endif /* VSTART */
969#ifdef VSTOP
2246281f 970 tty.main.c_cc[VSTOP] = CDISABLE;
c179a6d1 971#endif /* VSTOP */
2246281f 972 }
c179a6d1 973
86a5659e 974#ifdef AIX
f5272227
KL
975 tty.main.c_cc[VSTRT] = CDISABLE;
976 tty.main.c_cc[VSTOP] = CDISABLE;
977 tty.main.c_cc[VSUSP] = CDISABLE;
978 tty.main.c_cc[VDSUSP] = CDISABLE;
2246281f
KL
979 if (tty_out->flow_control)
980 {
ac567c95 981#ifdef VSTART
2246281f 982 tty.main.c_cc[VSTART] = '\021';
ac567c95
RS
983#endif /* VSTART */
984#ifdef VSTOP
2246281f 985 tty.main.c_cc[VSTOP] = '\023';
ac567c95 986#endif /* VSTOP */
2246281f
KL
987 }
988 /* Also, PTY overloads NUL and BREAK.
989 don't ignore break, but don't signal either, so it looks like NUL.
990 This really serves a purpose only if running in an XTERM window
991 or via TELNET or the like, but does no harm elsewhere. */
992 tty.main.c_iflag &= ~IGNBRK;
993 tty.main.c_iflag &= ~BRKINT;
86a5659e 994#endif
fe03522b 995#endif /* not DOS_NT */
cf84bb53 996
207bdbdb 997#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
2246281f
KL
998 if (!tty_out->term_initted)
999 internal_terminal_init ();
4e389d32 1000 dos_ttraw (tty_out);
207bdbdb 1001#endif
91bac16a 1002
12e610e8 1003 emacs_set_tty (fileno (tty_out->input), &tty, 0);
86a5659e 1004
2246281f
KL
1005 /* This code added to insure that, if flow-control is not to be used,
1006 we have an unlocked terminal at the start. */
91bac16a 1007
86a5659e 1008#ifdef TCXONC
0b0d3e0b 1009 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
86a5659e 1010#endif
86a5659e 1011#ifdef TIOCSTART
0b0d3e0b 1012 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
86a5659e 1013#endif
86a5659e 1014
a7ebc409 1015#if !defined (DOS_NT)
51417996 1016#ifdef TCOON
0b0d3e0b 1017 if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
d228f207 1018#endif
51417996 1019#endif
d228f207 1020
49cdacda 1021#ifdef F_GETOWN
2246281f 1022 if (interrupt_input)
86a5659e 1023 {
0b0d3e0b
KL
1024 old_fcntl_owner[fileno (tty_out->input)] =
1025 fcntl (fileno (tty_out->input), F_GETOWN, 0);
1026 fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
1027 init_sigio (fileno (tty_out->input));
7e5a23bd 1028#ifdef HAVE_GPM
75a8734b 1029 if (gpm_tty == tty_out)
3e748bcb 1030 {
75a8734b 1031 /* Arrange for mouse events to give us SIGIO signals. */
3e748bcb 1032 fcntl (gpm_fd, F_SETOWN, getpid ());
57669cf1 1033 fcntl (gpm_fd, F_SETFL, fcntl (gpm_fd, F_GETFL, 0) | O_NONBLOCK);
3e748bcb
NR
1034 init_sigio (gpm_fd);
1035 }
7e5a23bd 1036#endif /* HAVE_GPM */
86a5659e
JB
1037 }
1038#endif /* F_GETOWN */
86a5659e 1039
86a5659e
JB
1040#ifdef _IOFBF
1041 /* This symbol is defined on recent USG systems.
1042 Someone says without this call USG won't really buffer the file
1043 even with a call to setbuf. */
0b0d3e0b 1044 setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf);
86a5659e 1045#else
0b0d3e0b 1046 setbuf (tty_out->output, (char *) _sobuf);
86a5659e 1047#endif
4d553a13 1048
69fb5031
JR
1049 if (tty_out->terminal->set_terminal_modes_hook)
1050 tty_out->terminal->set_terminal_modes_hook (tty_out->terminal);
4b311aaf 1051
9628b887
KL
1052 if (!tty_out->term_initted)
1053 {
1054 Lisp_Object tail, frame;
1055 FOR_EACH_FRAME (tail, frame)
1056 {
daf01701 1057 /* XXX This needs to be revised. */
9628b887
KL
1058 if (FRAME_TERMCAP_P (XFRAME (frame))
1059 && FRAME_TTY (XFRAME (frame)) == tty_out)
1060 init_frame_faces (XFRAME (frame));
1061 }
1062 }
045942b2 1063
9628b887 1064 if (tty_out->term_initted && no_redraw_on_reenter)
86a5659e 1065 {
855a0da7
SM
1066 /* We used to call "direct_output_forward_char(0)" here,
1067 but it's not clear why, since it may not do anything anyway. */
86a5659e
JB
1068 }
1069 else
1070 {
9628b887 1071 Lisp_Object tail, frame;
0137dbf7 1072 frame_garbaged = 1;
9628b887
KL
1073 FOR_EACH_FRAME (tail, frame)
1074 {
7ab98847
EZ
1075 if ((FRAME_TERMCAP_P (XFRAME (frame))
1076 || FRAME_MSDOS_P (XFRAME (frame)))
9628b887
KL
1077 && FRAME_TTY (XFRAME (frame)) == tty_out)
1078 FRAME_GARBAGED_P (XFRAME (frame)) = 1;
1079 }
86a5659e 1080 }
91bac16a 1081
9628b887 1082 tty_out->term_initted = 1;
86a5659e
JB
1083}
1084
1085/* Return nonzero if safe to use tabs in output.
1086 At the time this is called, init_sys_modes has not been done yet. */
177c0ea7 1087
dfcf069d 1088int
16c290d8 1089tabs_safe_p (int fd)
86a5659e 1090{
6548cf00 1091 struct emacs_tty etty;
91bac16a 1092
12e610e8
DN
1093 emacs_get_tty (fd, &etty);
1094#ifndef DOS_NT
1095#ifdef TABDLY
1096 return ((etty.main.c_oflag & TABDLY) != TAB3);
1097#else /* not TABDLY */
1098 return 1;
1099#endif /* not TABDLY */
1100#else /* DOS_NT */
1101 return 0;
1102#endif /* DOS_NT */
86a5659e 1103}
73d5358f 1104\f
86a5659e 1105/* Get terminal size from system.
73d5358f
RS
1106 Store number of lines into *HEIGHTP and width into *WIDTHP.
1107 We store 0 if there's no valid information. */
86a5659e 1108
08633194 1109void
16c290d8 1110get_tty_size (int fd, int *widthp, int *heightp)
86a5659e 1111{
e16e55d4 1112#if defined TIOCGWINSZ
91bac16a
JB
1113
1114 /* BSD-style. */
86a5659e 1115 struct winsize size;
91bac16a 1116
16c290d8 1117 if (ioctl (fd, TIOCGWINSZ, &size) == -1)
91bac16a
JB
1118 *widthp = *heightp = 0;
1119 else
1120 {
1121 *widthp = size.ws_col;
1122 *heightp = size.ws_row;
1123 }
1124
e16e55d4 1125#elif defined TIOCGSIZE
91bac16a
JB
1126
1127 /* SunOS - style. */
177c0ea7 1128 struct ttysize size;
91bac16a 1129
16c290d8 1130 if (ioctl (fd, TIOCGSIZE, &size) == -1)
91bac16a
JB
1131 *widthp = *heightp = 0;
1132 else
1133 {
1134 *widthp = size.ts_cols;
1135 *heightp = size.ts_lines;
1136 }
1137
e16e55d4
JB
1138#elif defined WINDOWSNT
1139
1140 CONSOLE_SCREEN_BUFFER_INFO info;
1141 if (GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info))
1142 {
1143 *widthp = info.srWindow.Right - info.srWindow.Left + 1;
1144 *heightp = info.srWindow.Bottom - info.srWindow.Top + 1;
1145 }
1146 else
1147 *widthp = *heightp = 0;
1148
1149#elif defined MSDOS
1150
207bdbdb
RS
1151 *widthp = ScreenCols ();
1152 *heightp = ScreenRows ();
e16e55d4 1153
86a5659e 1154#else /* system doesn't know size */
e16e55d4 1155
86a5659e
JB
1156 *widthp = 0;
1157 *heightp = 0;
e16e55d4 1158
207bdbdb 1159#endif
86a5659e 1160}
91bac16a 1161
73d5358f
RS
1162/* Set the logical window size associated with descriptor FD
1163 to HEIGHT and WIDTH. This is used mainly with ptys. */
1164
1165int
971de7fb 1166set_window_size (int fd, int height, int width)
73d5358f
RS
1167{
1168#ifdef TIOCSWINSZ
1169
1170 /* BSD-style. */
1171 struct winsize size;
1172 size.ws_row = height;
1173 size.ws_col = width;
1174
1175 if (ioctl (fd, TIOCSWINSZ, &size) == -1)
1176 return 0; /* error */
1177 else
1178 return 1;
1179
1180#else
1181#ifdef TIOCSSIZE
1182
1183 /* SunOS - style. */
177c0ea7 1184 struct ttysize size;
73d5358f
RS
1185 size.ts_lines = height;
1186 size.ts_cols = width;
1187
1188 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1189 return 0;
1190 else
1191 return 1;
1192#else
1193 return -1;
1194#endif /* not SunOS-style */
1195#endif /* not BSD-style */
1196}
1197
86a5659e 1198\f
da8e1115
KL
1199
1200/* Prepare all terminal devices for exiting Emacs. */
1201
28d440ab
KL
1202void
1203reset_all_sys_modes (void)
1204{
28d7d09f 1205 struct tty_display_info *tty;
16c290d8 1206 for (tty = tty_list; tty; tty = tty->next)
28d440ab 1207 reset_sys_modes (tty);
28d440ab
KL
1208}
1209
0a125897 1210/* Prepare the terminal for closing it; move the cursor to the
0137dbf7 1211 bottom of the frame, turn off interrupt-driven I/O, etc. */
da8e1115 1212
08633194 1213void
971de7fb 1214reset_sys_modes (struct tty_display_info *tty_out)
86a5659e
JB
1215{
1216 if (noninteractive)
1217 {
1218 fflush (stdout);
1219 return;
1220 }
9628b887 1221 if (!tty_out->term_initted)
86a5659e 1222 return;
da8e1115 1223
0b0d3e0b
KL
1224 if (!tty_out->output)
1225 return; /* The tty is suspended. */
cf84bb53 1226
da8e1115
KL
1227 /* Go to and clear the last line of the terminal. */
1228
0a125897 1229 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
cf84bb53 1230
da8e1115
KL
1231 /* Code adapted from tty_clear_end_of_line. */
1232 if (tty_out->TS_clr_line)
1233 {
1234 emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc);
1235 }
1236 else
1237 { /* have to do it the hard way */
1238 int i;
ed8dad6b 1239 tty_turn_off_insert (tty_out);
cf84bb53 1240
da8e1115 1241 for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
0b0d3e0b
KL
1242 {
1243 fputc (' ', tty_out->output);
1244 }
da8e1115 1245 }
cf84bb53 1246
0a125897 1247 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
819b8f00 1248 fflush (tty_out->output);
cf84bb53 1249
69fb5031
JR
1250 if (tty_out->terminal->reset_terminal_modes_hook)
1251 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
2f98e6e3 1252
2a633456 1253#ifdef BSD_SYSTEM
86a5659e 1254 /* Avoid possible loss of output when changing terminal modes. */
0b0d3e0b 1255 fsync (fileno (tty_out->output));
86a5659e 1256#endif
91bac16a 1257
49cdacda
PE
1258#ifndef DOS_NT
1259#ifdef F_SETOWN
86a5659e
JB
1260 if (interrupt_input)
1261 {
0b0d3e0b
KL
1262 reset_sigio (fileno (tty_out->input));
1263 fcntl (fileno (tty_out->input), F_SETOWN,
1264 old_fcntl_owner[fileno (tty_out->input)]);
86a5659e
JB
1265 }
1266#endif /* F_SETOWN */
0b0d3e0b 1267 fcntl (fileno (tty_out->input), F_SETFL,
49cdacda 1268 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NONBLOCK);
a6b00318 1269#endif
91bac16a 1270
fca177d4 1271 if (tty_out->old_tty)
12e610e8 1272 while (emacs_set_tty (fileno (tty_out->input),
fca177d4 1273 tty_out->old_tty, 0) < 0 && errno == EINTR)
7e32a4fb 1274 ;
86a5659e 1275
207bdbdb
RS
1276#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1277 dos_ttcooked ();
1278#endif
1279
322aea6d 1280 widen_foreground_group (fileno (tty_out->input));
86a5659e
JB
1281}
1282\f
1283#ifdef HAVE_PTYS
1284
1285/* Set up the proper status flags for use of a pty. */
1286
08633194 1287void
971de7fb 1288setup_pty (int fd)
86a5659e
JB
1289{
1290 /* I'm told that TOICREMOTE does not mean control chars
1291 "can't be sent" but rather that they don't have
1292 input-editing or signaling effects.
1293 That should be good, because we have other ways
1294 to do those things in Emacs.
1295 However, telnet mode seems not to work on 4.2.
1296 So TIOCREMOTE is turned off now. */
1297
1298 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1299 will hang. In particular, the "timeout" feature (which
1300 causes a read to return if there is no data available)
1301 does this. Also it is known that telnet mode will hang
1302 in such a way that Emacs must be stopped (perhaps this
1303 is the same problem).
177c0ea7 1304
86a5659e
JB
1305 If TIOCREMOTE is turned off, then there is a bug in
1306 hp-ux which sometimes loses data. Apparently the
1307 code which blocks the master process when the internal
1308 buffer fills up does not work. Other than this,
1309 though, everything else seems to work fine.
177c0ea7 1310
86a5659e
JB
1311 Since the latter lossage is more benign, we may as well
1312 lose that way. -- cph */
1313#ifdef FIONBIO
5e617bc2 1314#if defined (UNIX98_PTYS)
86a5659e
JB
1315 {
1316 int on = 1;
1317 ioctl (fd, FIONBIO, &on);
1318 }
1319#endif
1320#endif
86a5659e
JB
1321}
1322#endif /* HAVE_PTYS */
1323\f
f8a80313
RS
1324#ifdef HAVE_SOCKETS
1325#include <sys/socket.h>
1326#include <netdb.h>
1327#endif /* HAVE_SOCKETS */
f8a80313 1328
8581cd64
KH
1329#ifdef TRY_AGAIN
1330#ifndef HAVE_H_ERRNO
1331extern int h_errno;
1332#endif
1333#endif /* TRY_AGAIN */
1334
c0c86835 1335void
971de7fb 1336init_system_name (void)
86a5659e 1337{
210b2b4f 1338#ifndef HAVE_GETHOSTNAME
c0c86835
KH
1339 struct utsname uts;
1340 uname (&uts);
1341 Vsystem_name = build_string (uts.nodename);
67004ffb 1342#else /* HAVE_GETHOSTNAME */
cc6e7269 1343 unsigned int hostname_size = 256;
38182d90 1344 char *hostname = alloca (hostname_size);
c0c86835
KH
1345
1346 /* Try to get the host name; if the buffer is too short, try
1347 again. Apparently, the only indication gethostname gives of
1348 whether the buffer was large enough is the presence or absence
1349 of a '\0' in the string. Eech. */
1350 for (;;)
1351 {
1352 gethostname (hostname, hostname_size - 1);
1353 hostname[hostname_size - 1] = '\0';
1354
1355 /* Was the buffer large enough for the '\0'? */
1356 if (strlen (hostname) < hostname_size - 1)
1357 break;
1358
1359 hostname_size <<= 1;
38182d90 1360 hostname = alloca (hostname_size);
c0c86835 1361 }
67004ffb 1362#ifdef HAVE_SOCKETS
c0c86835
KH
1363 /* Turn the hostname into the official, fully-qualified hostname.
1364 Don't do this if we're going to dump; this can confuse system
1365 libraries on some machines and make the dumped emacs core dump. */
67004ffb 1366#ifndef CANNOT_DUMP
c0c86835 1367 if (initialized)
67004ffb 1368#endif /* not CANNOT_DUMP */
8966b757 1369 if (! strchr (hostname, '.'))
960d894c 1370 {
960d894c 1371 int count;
3d66b985
JD
1372#ifdef HAVE_GETADDRINFO
1373 struct addrinfo *res;
1374 struct addrinfo hints;
1375 int ret;
1376
cf84bb53 1377 memset (&hints, 0, sizeof (hints));
3d66b985
JD
1378 hints.ai_socktype = SOCK_STREAM;
1379 hints.ai_flags = AI_CANONNAME;
1380
960d894c
KH
1381 for (count = 0;; count++)
1382 {
3d66b985
JD
1383 if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
1384 || ret != EAI_AGAIN)
1385 break;
1386
1387 if (count >= 5)
1388 break;
1389 Fsleep_for (make_number (1), Qnil);
1390 }
1391
1392 if (ret == 0)
1393 {
1394 struct addrinfo *it = res;
1395 while (it)
1396 {
1397 char *fqdn = it->ai_canonname;
8966b757 1398 if (fqdn && strchr (fqdn, '.')
3d66b985
JD
1399 && strcmp (fqdn, "localhost.localdomain") != 0)
1400 break;
1401 it = it->ai_next;
1402 }
1403 if (it)
1404 {
1405 hostname = alloca (strlen (it->ai_canonname) + 1);
1406 strcpy (hostname, it->ai_canonname);
1407 }
1408 freeaddrinfo (res);
1409 }
1410#else /* !HAVE_GETADDRINFO */
1411 struct hostent *hp;
1412 for (count = 0;; count++)
1413 {
1414
e24f1d55 1415#ifdef TRY_AGAIN
960d894c 1416 h_errno = 0;
e24f1d55 1417#endif
960d894c 1418 hp = gethostbyname (hostname);
efa04277 1419#ifdef TRY_AGAIN
960d894c
KH
1420 if (! (hp == 0 && h_errno == TRY_AGAIN))
1421#endif
3d66b985 1422
960d894c 1423 break;
3d66b985 1424
960d894c
KH
1425 if (count >= 5)
1426 break;
1427 Fsleep_for (make_number (1), Qnil);
1428 }
3d66b985 1429
960d894c
KH
1430 if (hp)
1431 {
1432 char *fqdn = (char *) hp->h_name;
960d894c 1433
8966b757 1434 if (!strchr (fqdn, '.'))
960d894c
KH
1435 {
1436 /* We still don't have a fully qualified domain name.
1437 Try to find one in the list of alternate names */
1438 char **alias = hp->h_aliases;
923721f4 1439 while (*alias
8966b757 1440 && (!strchr (*alias, '.')
923721f4 1441 || !strcmp (*alias, "localhost.localdomain")))
960d894c
KH
1442 alias++;
1443 if (*alias)
1444 fqdn = *alias;
1445 }
1446 hostname = fqdn;
960d894c 1447 }
3d66b985 1448#endif /* !HAVE_GETADDRINFO */
960d894c 1449 }
67004ffb 1450#endif /* HAVE_SOCKETS */
c0c86835 1451 Vsystem_name = build_string (hostname);
67004ffb 1452#endif /* HAVE_GETHOSTNAME */
c0c86835
KH
1453 {
1454 unsigned char *p;
d5db4077 1455 for (p = SDATA (Vsystem_name); *p; p++)
c0c86835
KH
1456 if (*p == ' ' || *p == '\t')
1457 *p = '-';
1458 }
67004ffb 1459}
86a5659e 1460\f
1fa53021 1461sigset_t empty_mask;
86a5659e 1462
4d7e6e51
PE
1463static struct sigaction process_fatal_action;
1464
1465static int
1466emacs_sigaction_flags (void)
86a5659e 1467{
4d7e6e51 1468#ifdef SA_RESTART
0caaedb1
PE
1469 /* SA_RESTART causes interruptible functions with timeouts (e.g.,
1470 'select') to reset their timeout on some platforms (e.g.,
1471 HP-UX 11), which is not what we want. Also, when Emacs is
1472 interactive, we don't want SA_RESTART because we need to poll
275464e7 1473 for pending input so we need long-running syscalls to be interrupted
4d7e6e51
PE
1474 after a signal that sets pending_signals.
1475
1476 Non-interactive keyboard input goes through stdio, where we
1477 always want restartable system calls. */
ef874e3d 1478 if (noninteractive)
4d7e6e51 1479 return SA_RESTART;
e065a56e 1480#endif
4d7e6e51
PE
1481 return 0;
1482}
1483
1484/* Store into *ACTION a signal action suitable for Emacs, with handler
1485 HANDLER. */
1486void
1487emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
1488{
1489 sigemptyset (&action->sa_mask);
1490
1491 /* When handling a signal, block nonfatal system signals that are caught
1492 by Emacs. This makes race conditions less likely. */
1493 sigaddset (&action->sa_mask, SIGALRM);
1494#ifdef SIGCHLD
1495 sigaddset (&action->sa_mask, SIGCHLD);
1496#endif
1497#ifdef SIGDANGER
1498 sigaddset (&action->sa_mask, SIGDANGER);
1499#endif
d89460ed
PE
1500#ifdef PROFILER_CPU_SUPPORT
1501 sigaddset (&action->sa_mask, SIGPROF);
1502#endif
4d7e6e51
PE
1503#ifdef SIGWINCH
1504 sigaddset (&action->sa_mask, SIGWINCH);
1505#endif
1506 if (! noninteractive)
1507 {
1508 sigaddset (&action->sa_mask, SIGINT);
1509 sigaddset (&action->sa_mask, SIGQUIT);
1510#ifdef USABLE_SIGIO
1511 sigaddset (&action->sa_mask, SIGIO);
1512#endif
1513 }
1514
1515 if (! IEEE_FLOATING_POINT)
1516 sigaddset (&action->sa_mask, SIGFPE);
1517
1518 action->sa_handler = handler;
1519 action->sa_flags = emacs_sigaction_flags ();
86a5659e
JB
1520}
1521
20ef56db 1522#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
0caaedb1 1523static pthread_t main_thread;
20ef56db
PE
1524#endif
1525
4d7e6e51
PE
1526/* SIG has arrived at the current process. Deliver it to the main
1527 thread, which should handle it with HANDLER.
1528
1529 If we are on the main thread, handle the signal SIG with HANDLER.
20ef56db
PE
1530 Otherwise, redirect the signal to the main thread, blocking it from
1531 this thread. POSIX says any thread can receive a signal that is
1532 associated with a process, process group, or asynchronous event.
1533 On GNU/Linux that is not true, but for other systems (FreeBSD at
1534 least) it is. */
1535void
4d7e6e51 1536deliver_process_signal (int sig, signal_handler_t handler)
20ef56db
PE
1537{
1538 /* Preserve errno, to avoid race conditions with signal handlers that
1539 might change errno. Races can occur even in single-threaded hosts. */
1540 int old_errno = errno;
1541
1542 bool on_main_thread = true;
1543#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
1544 if (! pthread_equal (pthread_self (), main_thread))
1545 {
1546 sigset_t blocked;
1547 sigemptyset (&blocked);
1548 sigaddset (&blocked, sig);
1549 pthread_sigmask (SIG_BLOCK, &blocked, 0);
1550 pthread_kill (main_thread, sig);
1551 on_main_thread = false;
1552 }
1553#endif
1554 if (on_main_thread)
1555 handler (sig);
1556
1557 errno = old_errno;
1558}
4d7e6e51
PE
1559
1560/* Static location to save a fatal backtrace in a thread.
1561 FIXME: If two subsidiary threads fail simultaneously, the resulting
1562 backtrace may be garbage. */
1563enum { BACKTRACE_LIMIT_MAX = 500 };
1564static void *thread_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1];
1565static int thread_backtrace_npointers;
1566
1567/* SIG has arrived at the current thread.
1568 If we are on the main thread, handle the signal SIG with HANDLER.
1569 Otherwise, this is a fatal error in the handling thread. */
1570static void
1571deliver_thread_signal (int sig, signal_handler_t handler)
1572{
1573 int old_errno = errno;
1574
1575#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
1576 if (! pthread_equal (pthread_self (), main_thread))
1577 {
1578 thread_backtrace_npointers
1579 = backtrace (thread_backtrace_buffer, BACKTRACE_LIMIT_MAX);
1580 sigaction (sig, &process_fatal_action, 0);
1581 pthread_kill (main_thread, sig);
1582
1583 /* Avoid further damage while the main thread is exiting. */
1584 while (1)
1585 sigsuspend (&empty_mask);
1586 }
1587#endif
1588
1589 handler (sig);
1590 errno = old_errno;
1591}
86a5659e 1592\f
aa1ba90e
PE
1593#if !HAVE_DECL_SYS_SIGLIST
1594# undef sys_siglist
c622b48f
PE
1595# ifdef _sys_siglist
1596# define sys_siglist _sys_siglist
1597# else
1598# define sys_siglist my_sys_siglist
aa1ba90e 1599static char const *sys_siglist[NSIG];
c622b48f
PE
1600# endif
1601#endif
1602
1603#ifdef _sys_nsig
1604# define sys_siglist_entries _sys_nsig
1605#else
1606# define sys_siglist_entries NSIG
ca9c0567
PE
1607#endif
1608
4d7e6e51
PE
1609/* Handle bus errors, invalid instruction, etc. */
1610static void
1611handle_fatal_signal (int sig)
1612{
9d4dcdc9 1613 terminate_due_to_signal (sig, 40);
4d7e6e51
PE
1614}
1615
1616static void
1617deliver_fatal_signal (int sig)
1618{
1619 deliver_process_signal (sig, handle_fatal_signal);
1620}
1621
1622static void
1623deliver_fatal_thread_signal (int sig)
1624{
1625 deliver_thread_signal (sig, handle_fatal_signal);
1626}
1627
1628static _Noreturn void
1629handle_arith_signal (int sig)
1630{
1631 pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
1632 xsignal0 (Qarith_error);
1633}
1634
1635static void
1636deliver_arith_signal (int sig)
1637{
1638 deliver_thread_signal (sig, handle_arith_signal);
1639}
1640
1641/* Treat SIG as a terminating signal, unless it is already ignored and
1642 we are in --batch mode. Among other things, this makes nohup work. */
1643static void
1644maybe_fatal_sig (int sig)
1645{
1646 bool catch_sig = !noninteractive;
1647 if (!catch_sig)
1648 {
1649 struct sigaction old_action;
1650 sigaction (sig, 0, &old_action);
1651 catch_sig = old_action.sa_handler != SIG_IGN;
1652 }
1653 if (catch_sig)
1654 sigaction (sig, &process_fatal_action, 0);
1655}
1656
ca9c0567 1657void
4d7e6e51 1658init_signals (bool dumping)
ca9c0567 1659{
4d7e6e51
PE
1660 struct sigaction thread_fatal_action;
1661 struct sigaction action;
1662
ca9c0567 1663 sigemptyset (&empty_mask);
ca9c0567 1664
20ef56db
PE
1665#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
1666 main_thread = pthread_self ();
1667#endif
1668
c622b48f 1669#if !HAVE_DECL_SYS_SIGLIST && !defined _sys_siglist
ca9c0567
PE
1670 if (! initialized)
1671 {
ca9c0567 1672 sys_siglist[SIGABRT] = "Aborted";
ca9c0567
PE
1673# ifdef SIGAIO
1674 sys_siglist[SIGAIO] = "LAN I/O interrupt";
1675# endif
1676# ifdef SIGALRM
1677 sys_siglist[SIGALRM] = "Alarm clock";
1678# endif
1679# ifdef SIGBUS
1680 sys_siglist[SIGBUS] = "Bus error";
1681# endif
1682# ifdef SIGCLD
1683 sys_siglist[SIGCLD] = "Child status changed";
1684# endif
1685# ifdef SIGCHLD
1686 sys_siglist[SIGCHLD] = "Child status changed";
1687# endif
1688# ifdef SIGCONT
1689 sys_siglist[SIGCONT] = "Continued";
1690# endif
1691# ifdef SIGDANGER
1692 sys_siglist[SIGDANGER] = "Swap space dangerously low";
1693# endif
1694# ifdef SIGDGNOTIFY
1695 sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
1696# endif
1697# ifdef SIGEMT
1698 sys_siglist[SIGEMT] = "Emulation trap";
1699# endif
ca9c0567 1700 sys_siglist[SIGFPE] = "Arithmetic exception";
ca9c0567
PE
1701# ifdef SIGFREEZE
1702 sys_siglist[SIGFREEZE] = "SIGFREEZE";
1703# endif
1704# ifdef SIGGRANT
1705 sys_siglist[SIGGRANT] = "Monitor mode granted";
1706# endif
1707# ifdef SIGHUP
1708 sys_siglist[SIGHUP] = "Hangup";
1709# endif
ca9c0567 1710 sys_siglist[SIGILL] = "Illegal instruction";
ca9c0567 1711 sys_siglist[SIGINT] = "Interrupt";
ca9c0567
PE
1712# ifdef SIGIO
1713 sys_siglist[SIGIO] = "I/O possible";
1714# endif
1715# ifdef SIGIOINT
1716 sys_siglist[SIGIOINT] = "I/O intervention required";
1717# endif
1718# ifdef SIGIOT
1719 sys_siglist[SIGIOT] = "IOT trap";
1720# endif
1721# ifdef SIGKILL
1722 sys_siglist[SIGKILL] = "Killed";
1723# endif
1724# ifdef SIGLOST
1725 sys_siglist[SIGLOST] = "Resource lost";
1726# endif
1727# ifdef SIGLWP
1728 sys_siglist[SIGLWP] = "SIGLWP";
1729# endif
1730# ifdef SIGMSG
1731 sys_siglist[SIGMSG] = "Monitor mode data available";
1732# endif
1733# ifdef SIGPHONE
1734 sys_siglist[SIGWIND] = "SIGPHONE";
1735# endif
1736# ifdef SIGPIPE
1737 sys_siglist[SIGPIPE] = "Broken pipe";
1738# endif
1739# ifdef SIGPOLL
1740 sys_siglist[SIGPOLL] = "Pollable event occurred";
1741# endif
1742# ifdef SIGPROF
1743 sys_siglist[SIGPROF] = "Profiling timer expired";
1744# endif
1745# ifdef SIGPTY
1746 sys_siglist[SIGPTY] = "PTY I/O interrupt";
1747# endif
1748# ifdef SIGPWR
1749 sys_siglist[SIGPWR] = "Power-fail restart";
1750# endif
1751# ifdef SIGQUIT
1752 sys_siglist[SIGQUIT] = "Quit";
1753# endif
1754# ifdef SIGRETRACT
40ba43b4 1755 sys_siglist[SIGRETRACT] = "Need to relinquish monitor mode";
ca9c0567
PE
1756# endif
1757# ifdef SIGSAK
1758 sys_siglist[SIGSAK] = "Secure attention";
1759# endif
ca9c0567 1760 sys_siglist[SIGSEGV] = "Segmentation violation";
ca9c0567
PE
1761# ifdef SIGSOUND
1762 sys_siglist[SIGSOUND] = "Sound completed";
1763# endif
1764# ifdef SIGSTOP
1765 sys_siglist[SIGSTOP] = "Stopped (signal)";
1766# endif
1767# ifdef SIGSTP
1768 sys_siglist[SIGSTP] = "Stopped (user)";
1769# endif
1770# ifdef SIGSYS
1771 sys_siglist[SIGSYS] = "Bad argument to system call";
1772# endif
ca9c0567 1773 sys_siglist[SIGTERM] = "Terminated";
ca9c0567
PE
1774# ifdef SIGTHAW
1775 sys_siglist[SIGTHAW] = "SIGTHAW";
1776# endif
1777# ifdef SIGTRAP
1778 sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
1779# endif
1780# ifdef SIGTSTP
1781 sys_siglist[SIGTSTP] = "Stopped (user)";
1782# endif
1783# ifdef SIGTTIN
1784 sys_siglist[SIGTTIN] = "Stopped (tty input)";
1785# endif
1786# ifdef SIGTTOU
1787 sys_siglist[SIGTTOU] = "Stopped (tty output)";
1788# endif
1789# ifdef SIGURG
1790 sys_siglist[SIGURG] = "Urgent I/O condition";
1791# endif
1792# ifdef SIGUSR1
1793 sys_siglist[SIGUSR1] = "User defined signal 1";
1794# endif
1795# ifdef SIGUSR2
1796 sys_siglist[SIGUSR2] = "User defined signal 2";
1797# endif
1798# ifdef SIGVTALRM
1799 sys_siglist[SIGVTALRM] = "Virtual timer expired";
1800# endif
1801# ifdef SIGWAITING
1802 sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
1803# endif
1804# ifdef SIGWINCH
1805 sys_siglist[SIGWINCH] = "Window size changed";
1806# endif
1807# ifdef SIGWIND
1808 sys_siglist[SIGWIND] = "SIGWIND";
1809# endif
1810# ifdef SIGXCPU
1811 sys_siglist[SIGXCPU] = "CPU time limit exceeded";
1812# endif
1813# ifdef SIGXFSZ
1814 sys_siglist[SIGXFSZ] = "File size limit exceeded";
1815# endif
1816 }
c622b48f 1817#endif /* !HAVE_DECL_SYS_SIGLIST && !_sys_siglist */
4d7e6e51
PE
1818
1819 /* Don't alter signal handlers if dumping. On some machines,
1820 changing signal handlers sets static data that would make signals
1821 fail to work right when the dumped Emacs is run. */
1822 if (dumping)
1823 return;
1824
1825 sigfillset (&process_fatal_action.sa_mask);
1826 process_fatal_action.sa_handler = deliver_fatal_signal;
62a1d661 1827 process_fatal_action.sa_flags = emacs_sigaction_flags ();
4d7e6e51
PE
1828
1829 sigfillset (&thread_fatal_action.sa_mask);
1830 thread_fatal_action.sa_handler = deliver_fatal_thread_signal;
1831 thread_fatal_action.sa_flags = process_fatal_action.sa_flags;
1832
1833 /* SIGINT may need special treatment on MS-Windows. See
1834 http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html
1835 Please update the doc of kill-emacs, kill-emacs-hook, and
1836 NEWS if you change this. */
1837
1838 maybe_fatal_sig (SIGHUP);
1839 maybe_fatal_sig (SIGINT);
1840 maybe_fatal_sig (SIGTERM);
1841
1842 /* Emacs checks for write errors, so it can safely ignore SIGPIPE.
1843 However, in batch mode leave SIGPIPE alone, as that causes Emacs
1844 to behave more like typical batch applications do. */
1845 if (! noninteractive)
1846 signal (SIGPIPE, SIG_IGN);
1847
1848 sigaction (SIGQUIT, &process_fatal_action, 0);
1849 sigaction (SIGILL, &thread_fatal_action, 0);
1850 sigaction (SIGTRAP, &thread_fatal_action, 0);
1851
1852 /* Typically SIGFPE is thread-specific and is fatal, like SIGILL.
1853 But on a non-IEEE host SIGFPE can come from a trap in the Lisp
1854 interpreter's floating point operations, so treat SIGFPE as an
1855 arith-error if it arises in the main thread. */
1856 if (IEEE_FLOATING_POINT)
1857 sigaction (SIGFPE, &thread_fatal_action, 0);
1858 else
1859 {
1860 emacs_sigaction_init (&action, deliver_arith_signal);
1861 sigaction (SIGFPE, &action, 0);
1862 }
1863
1864#ifdef SIGUSR1
1865 add_user_signal (SIGUSR1, "sigusr1");
1866#endif
1867#ifdef SIGUSR2
1868 add_user_signal (SIGUSR2, "sigusr2");
1869#endif
1870 sigaction (SIGABRT, &thread_fatal_action, 0);
1871#ifdef SIGPRE
1872 sigaction (SIGPRE, &thread_fatal_action, 0);
1873#endif
1874#ifdef SIGORE
1875 sigaction (SIGORE, &thread_fatal_action, 0);
1876#endif
1877#ifdef SIGUME
1878 sigaction (SIGUME, &thread_fatal_action, 0);
1879#endif
1880#ifdef SIGDLK
1881 sigaction (SIGDLK, &process_fatal_action, 0);
1882#endif
1883#ifdef SIGCPULIM
1884 sigaction (SIGCPULIM, &process_fatal_action, 0);
1885#endif
1886#ifdef SIGIOT
1887 sigaction (SIGIOT, &thread_fatal_action, 0);
1888#endif
1889#ifdef SIGEMT
1890 sigaction (SIGEMT, &thread_fatal_action, 0);
1891#endif
1892#ifdef SIGBUS
1893 sigaction (SIGBUS, &thread_fatal_action, 0);
1894#endif
1895 sigaction (SIGSEGV, &thread_fatal_action, 0);
1896#ifdef SIGSYS
1897 sigaction (SIGSYS, &thread_fatal_action, 0);
1898#endif
1899 sigaction (SIGTERM, &process_fatal_action, 0);
1900#ifdef SIGPROF
d89460ed 1901 signal (SIGPROF, SIG_IGN);
4d7e6e51
PE
1902#endif
1903#ifdef SIGVTALRM
1904 sigaction (SIGVTALRM, &process_fatal_action, 0);
1905#endif
1906#ifdef SIGXCPU
1907 sigaction (SIGXCPU, &process_fatal_action, 0);
1908#endif
1909#ifdef SIGXFSZ
1910 sigaction (SIGXFSZ, &process_fatal_action, 0);
1911#endif
1912
1913#ifdef SIGDANGER
1914 /* This just means available memory is getting low. */
1915 emacs_sigaction_init (&action, deliver_danger_signal);
1916 sigaction (SIGDANGER, &action, 0);
1917#endif
1918
1919 /* AIX-specific signals. */
1920#ifdef SIGGRANT
1921 sigaction (SIGGRANT, &process_fatal_action, 0);
1922#endif
1923#ifdef SIGMIGRATE
1924 sigaction (SIGMIGRATE, &process_fatal_action, 0);
1925#endif
1926#ifdef SIGMSG
1927 sigaction (SIGMSG, &process_fatal_action, 0);
1928#endif
1929#ifdef SIGRETRACT
1930 sigaction (SIGRETRACT, &process_fatal_action, 0);
1931#endif
1932#ifdef SIGSAK
1933 sigaction (SIGSAK, &process_fatal_action, 0);
1934#endif
1935#ifdef SIGSOUND
1936 sigaction (SIGSOUND, &process_fatal_action, 0);
1937#endif
1938#ifdef SIGTALRM
1939 sigaction (SIGTALRM, &thread_fatal_action, 0);
1940#endif
ca9c0567
PE
1941}
1942\f
9927a7b1 1943#ifndef HAVE_RANDOM
4bb8c8b7
KH
1944#ifdef random
1945#define HAVE_RANDOM
1946#endif
1947#endif
1948
1949/* Figure out how many bits the system's random number generator uses.
1950 `random' and `lrand48' are assumed to return 31 usable bits.
1951 BSD `rand' returns a 31 bit value but the low order bits are unusable;
1952 so we'll shift it and treat it like the 15-bit USG `rand'. */
1953
1954#ifndef RAND_BITS
1955# ifdef HAVE_RANDOM
1956# define RAND_BITS 31
1957# else /* !HAVE_RANDOM */
1958# ifdef HAVE_LRAND48
1959# define RAND_BITS 31
1960# define random lrand48
1961# else /* !HAVE_LRAND48 */
1962# define RAND_BITS 15
1963# if RAND_MAX == 32767
1964# define random rand
1965# else /* RAND_MAX != 32767 */
1966# if RAND_MAX == 2147483647
1967# define random() (rand () >> 16)
1968# else /* RAND_MAX != 2147483647 */
1969# ifdef USG
1970# define random rand
1971# else
1972# define random() (rand () >> 16)
2a633456 1973# endif /* !USG */
4bb8c8b7
KH
1974# endif /* RAND_MAX != 2147483647 */
1975# endif /* RAND_MAX != 32767 */
1976# endif /* !HAVE_LRAND48 */
1977# endif /* !HAVE_RANDOM */
1978#endif /* !RAND_BITS */
2e46c7c6 1979
4bb8c8b7 1980void
0e23ef9d 1981seed_random (void *seed, ptrdiff_t seed_size)
86a5659e 1982{
33634217 1983#if defined HAVE_RANDOM || ! defined HAVE_LRAND48
0e23ef9d
PE
1984 unsigned int arg = 0;
1985#else
1986 long int arg = 0;
1987#endif
1988 unsigned char *argp = (unsigned char *) &arg;
1989 unsigned char *seedp = seed;
1990 ptrdiff_t i;
1991 for (i = 0; i < seed_size; i++)
1992 argp[i % sizeof arg] ^= seedp[i];
4bb8c8b7 1993#ifdef HAVE_RANDOM
0e23ef9d 1994 srandom (arg);
f8b53a82 1995#else
4bb8c8b7 1996# ifdef HAVE_LRAND48
76425a49 1997 srand48 (arg);
4bb8c8b7 1998# else
0e23ef9d 1999 srand (arg);
4bb8c8b7 2000# endif
2e46c7c6 2001#endif
86a5659e
JB
2002}
2003
0e23ef9d
PE
2004void
2005init_random (void)
2006{
2007 EMACS_TIME t = current_emacs_time ();
2008 uintmax_t v = getpid () ^ EMACS_SECS (t) ^ EMACS_NSECS (t);
2009 seed_random (&v, sizeof v);
2010}
2011
4bb8c8b7 2012/*
d8ed26bd
PE
2013 * Return a nonnegative random integer out of whatever we've got.
2014 * It contains enough bits to make a random (signed) Emacs fixnum.
4bb8c8b7
KH
2015 * This suffices even for a 64-bit architecture with a 15-bit rand.
2016 */
ede49d71 2017EMACS_INT
971de7fb 2018get_random (void)
4bb8c8b7 2019{
ede49d71
PE
2020 EMACS_UINT val = 0;
2021 int i;
d8ed26bd
PE
2022 for (i = 0; i < (FIXNUM_BITS + RAND_BITS - 1) / RAND_BITS; i++)
2023 val = (random () ^ (val << RAND_BITS)
2024 ^ (val >> (BITS_PER_EMACS_INT - RAND_BITS)));
2025 val ^= val >> (BITS_PER_EMACS_INT - FIXNUM_BITS);
2026 return val & INTMASK;
4bb8c8b7 2027}
7088d1ca 2028
55e5faa1
PE
2029#ifndef HAVE_SNPRINTF
2030/* Approximate snprintf as best we can on ancient hosts that lack it. */
2031int
2032snprintf (char *buf, size_t bufsize, char const *format, ...)
2033{
2034 ptrdiff_t size = min (bufsize, PTRDIFF_MAX);
2035 ptrdiff_t nbytes = size - 1;
2036 va_list ap;
2037
2038 if (size)
2039 {
2040 va_start (ap, format);
2041 nbytes = doprnt (buf, size, format, 0, ap);
2042 va_end (ap);
2043 }
2044
2045 if (nbytes == size - 1)
2046 {
2047 /* Calculate the length of the string that would have been created
2048 had the buffer been large enough. */
2049 char stackbuf[4000];
2050 char *b = stackbuf;
2051 ptrdiff_t bsize = sizeof stackbuf;
2052 va_start (ap, format);
2053 nbytes = evxprintf (&b, &bsize, stackbuf, -1, format, ap);
2054 va_end (ap);
2055 if (b != stackbuf)
2056 xfree (b);
2057 }
2058
2059 if (INT_MAX < nbytes)
2060 {
31bed486 2061#ifdef EOVERFLOW
55e5faa1 2062 errno = EOVERFLOW;
31bed486
EZ
2063#else
2064 errno = EDOM;
2065#endif
55e5faa1
PE
2066 return -1;
2067 }
2068 return nbytes;
2069}
2070#endif
86a5659e 2071\f
cf29dd84
PE
2072/* If a backtrace is available, output the top lines of it to stderr.
2073 Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines.
2074 This function may be called from a signal handler, so it should
2075 not invoke async-unsafe functions like malloc. */
2076void
2077emacs_backtrace (int backtrace_limit)
2078{
4d7e6e51 2079 void *main_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1];
cf29dd84 2080 int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX);
4d7e6e51
PE
2081 void *buffer;
2082 int npointers;
2083
2084 if (thread_backtrace_npointers)
2085 {
2086 buffer = thread_backtrace_buffer;
2087 npointers = thread_backtrace_npointers;
2088 }
2089 else
2090 {
2091 buffer = main_backtrace_buffer;
2092 npointers = backtrace (buffer, bounded_limit + 1);
2093 }
2094
cf29dd84 2095 if (npointers)
4d7e6e51
PE
2096 {
2097 ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12));
2098 backtrace_symbols_fd (buffer, npointers, STDERR_FILENO);
2099 if (bounded_limit < npointers)
2100 ignore_value (write (STDERR_FILENO, "...\n", 4));
2101 }
cf29dd84
PE
2102}
2103\f
1088b922 2104#ifndef HAVE_NTGUI
1088b922
PE
2105void
2106emacs_abort (void)
2107{
4d7e6e51 2108 terminate_due_to_signal (SIGABRT, 10);
1088b922
PE
2109}
2110#endif
2111
86a5659e 2112int
971de7fb 2113emacs_open (const char *path, int oflag, int mode)
86a5659e
JB
2114{
2115 register int rtnval;
68c45bf0 2116
86a5659e 2117 while ((rtnval = open (path, oflag, mode)) == -1
275464e7
SM
2118 && (errno == EINTR))
2119 QUIT;
86a5659e
JB
2120 return (rtnval);
2121}
2122
dfcf069d 2123int
971de7fb 2124emacs_close (int fd)
86a5659e 2125{
fe111daf 2126 int did_retry = 0;
86a5659e
JB
2127 register int rtnval;
2128
2129 while ((rtnval = close (fd)) == -1
fe111daf
KH
2130 && (errno == EINTR))
2131 did_retry = 1;
2132
2133 /* If close is interrupted SunOS 4.1 may or may not have closed the
2134 file descriptor. If it did the second close will fail with
2135 errno = EBADF. That means we have succeeded. */
2136 if (rtnval == -1 && did_retry && errno == EBADF)
2137 return 0;
2138
86a5659e
JB
2139 return rtnval;
2140}
2141
1963a2e0
PE
2142/* Maximum number of bytes to read or write in a single system call.
2143 This works around a serious bug in Linux kernels before 2.6.16; see
2144 <https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=612839>.
2145 It's likely to work around similar bugs in other operating systems, so do it
2146 on all platforms. Round INT_MAX down to a page size, with the conservative
2147 assumption that page sizes are at most 2**18 bytes (any kernel with a
2148 page size larger than that shouldn't have the bug). */
2149#ifndef MAX_RW_COUNT
2150#define MAX_RW_COUNT (INT_MAX >> 18 << 18)
2151#endif
2152
273a5f82
PE
2153/* Read from FILEDESC to a buffer BUF with size NBYTE, retrying if interrupted.
2154 Return the number of bytes read, which might be less than NBYTE.
2155 On error, set errno and return -1. */
d311d28c
PE
2156ptrdiff_t
2157emacs_read (int fildes, char *buf, ptrdiff_t nbyte)
86a5659e 2158{
8a2cbd72 2159 register ssize_t rtnval;
177c0ea7 2160
71b41406
PE
2161 /* There is no need to check against MAX_RW_COUNT, since no caller ever
2162 passes a size that large to emacs_read. */
2163
2164 while ((rtnval = read (fildes, buf, nbyte)) == -1
275464e7
SM
2165 && (errno == EINTR))
2166 QUIT;
86a5659e
JB
2167 return (rtnval);
2168}
2169
273a5f82
PE
2170/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted
2171 or if a partial write occurs. Return the number of bytes written, setting
2172 errno if this is less than NBYTE. */
d311d28c
PE
2173ptrdiff_t
2174emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
86a5659e 2175{
273a5f82 2176 ssize_t rtnval;
d311d28c 2177 ptrdiff_t bytes_written;
28272684 2178
b95520f5
BF
2179 bytes_written = 0;
2180
273a5f82 2181 while (nbyte > 0)
b95520f5 2182 {
1963a2e0 2183 rtnval = write (fildes, buf, min (nbyte, MAX_RW_COUNT));
b95520f5 2184
273a5f82 2185 if (rtnval < 0)
b95520f5
BF
2186 {
2187 if (errno == EINTR)
77220eeb 2188 {
77220eeb
SM
2189 /* I originally used `QUIT' but that might causes files to
2190 be truncated if you hit C-g in the middle of it. --Stef */
4d7e6e51
PE
2191 if (pending_signals)
2192 process_pending_signals ();
77220eeb
SM
2193 continue;
2194 }
b95520f5 2195 else
273a5f82 2196 break;
b95520f5
BF
2197 }
2198
2199 buf += rtnval;
2200 nbyte -= rtnval;
2201 bytes_written += rtnval;
2202 }
273a5f82 2203
b95520f5 2204 return (bytes_written);
86a5659e 2205}
d1fdcab7
PE
2206
2207static struct allocator const emacs_norealloc_allocator =
2208 { xmalloc, NULL, xfree, memory_full };
2209
2210/* Get the symbolic link value of FILENAME. Return a pointer to a
2211 NUL-terminated string. If readlink fails, return NULL and set
2212 errno. If the value fits in INITIAL_BUF, return INITIAL_BUF.
2213 Otherwise, allocate memory and return a pointer to that memory. If
2214 memory allocation fails, diagnose and fail without returning. If
2215 successful, store the length of the symbolic link into *LINKLEN. */
2216char *
2217emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
2218{
2219 return careadlinkat (AT_FDCWD, filename, initial_buf, READLINK_BUFSIZE,
2220 &emacs_norealloc_allocator, careadlinkatcwd);
2221}
86a5659e 2222\f
d35af63c
PE
2223/* Return a struct timeval that is roughly equivalent to T.
2224 Use the least timeval not less than T.
2225 Return an extremal value if the result would overflow. */
2226struct timeval
2227make_timeval (EMACS_TIME t)
2228{
2229 struct timeval tv;
2230 tv.tv_sec = t.tv_sec;
2231 tv.tv_usec = t.tv_nsec / 1000;
2232
2233 if (t.tv_nsec % 1000 != 0)
2234 {
2235 if (tv.tv_usec < 999999)
2236 tv.tv_usec++;
2237 else if (tv.tv_sec < TYPE_MAXIMUM (time_t))
2238 {
2239 tv.tv_sec++;
2240 tv.tv_usec = 0;
2241 }
2242 }
2243
2244 return tv;
2245}
2246
2247/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2248 ATIME and MTIME, respectively.
2249 FD must be either negative -- in which case it is ignored --
2250 or a file descriptor that is open on FILE.
2251 If FD is nonnegative, then FILE can be NULL. */
53ea491a 2252int
d35af63c
PE
2253set_file_times (int fd, const char *filename,
2254 EMACS_TIME atime, EMACS_TIME mtime)
2255{
2256 struct timespec timespec[2];
2257 timespec[0] = atime;
2258 timespec[1] = mtime;
2259 return fdutimens (fd, filename, timespec);
53ea491a
KH
2260}
2261\f
aa1ba90e
PE
2262/* Like strsignal, except async-signal-safe, and this function typically
2263 returns a string in the C locale rather than the current locale. */
2264char const *
2265safe_strsignal (int code)
68c45bf0 2266{
aa1ba90e 2267 char const *signame = 0;
68c45bf0 2268
c622b48f 2269 if (0 <= code && code < sys_siglist_entries)
aa1ba90e
PE
2270 signame = sys_siglist[code];
2271 if (! signame)
2272 signame = "Unknown signal";
c4ea52a6 2273
68c45bf0
PE
2274 return signame;
2275}
d888760c 2276\f
a7ebc409 2277#ifndef DOS_NT
d888760c 2278/* For make-serial-process */
cf84bb53
JB
2279int
2280serial_open (char *port)
d888760c 2281{
49cdacda 2282 int fd = emacs_open (port, O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
d888760c
GM
2283 if (fd < 0)
2284 {
2285 error ("Could not open %s: %s",
2286 port, emacs_strerror (errno));
2287 }
2288#ifdef TIOCEXCL
2289 ioctl (fd, TIOCEXCL, (char *) 0);
2290#endif
2291
2292 return fd;
2293}
759d3f32
SM
2294
2295#if !defined (HAVE_CFMAKERAW)
2296/* Workaround for targets which are missing cfmakeraw. */
2297/* Pasted from man page. */
cf84bb53
JB
2298static void
2299cfmakeraw (struct termios *termios_p)
759d3f32
SM
2300{
2301 termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
2302 termios_p->c_oflag &= ~OPOST;
2303 termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
2304 termios_p->c_cflag &= ~(CSIZE|PARENB);
2305 termios_p->c_cflag |= CS8;
2306}
2307#endif /* !defined (HAVE_CFMAKERAW */
2308
2309#if !defined (HAVE_CFSETSPEED)
2310/* Workaround for targets which are missing cfsetspeed. */
cf84bb53
JB
2311static int
2312cfsetspeed (struct termios *termios_p, speed_t vitesse)
759d3f32
SM
2313{
2314 return (cfsetispeed (termios_p, vitesse)
2315 + cfsetospeed (termios_p, vitesse));
2316}
2317#endif
2318
d888760c
GM
2319/* For serial-process-configure */
2320void
2321serial_configure (struct Lisp_Process *p,
cf84bb53 2322 Lisp_Object contact)
d888760c
GM
2323{
2324 Lisp_Object childp2 = Qnil;
2325 Lisp_Object tem = Qnil;
2326 struct termios attr;
2327 int err = -1;
2328 char summary[4] = "???"; /* This usually becomes "8N1". */
2329
4d2b044c 2330 childp2 = Fcopy_sequence (p->childp);
d888760c
GM
2331
2332 /* Read port attributes and prepare default configuration. */
2333 err = tcgetattr (p->outfd, &attr);
2334 if (err != 0)
2335 error ("tcgetattr() failed: %s", emacs_strerror (errno));
2336 cfmakeraw (&attr);
2337#if defined (CLOCAL)
2338 attr.c_cflag |= CLOCAL;
2339#endif
2340#if defined (CREAD)
6d1921be 2341 attr.c_cflag |= CREAD;
d888760c
GM
2342#endif
2343
2344 /* Configure speed. */
2345 if (!NILP (Fplist_member (contact, QCspeed)))
2346 tem = Fplist_get (contact, QCspeed);
2347 else
4d2b044c 2348 tem = Fplist_get (p->childp, QCspeed);
d888760c
GM
2349 CHECK_NUMBER (tem);
2350 err = cfsetspeed (&attr, XINT (tem));
2351 if (err != 0)
c2982e87 2352 error ("cfsetspeed(%"pI"d) failed: %s", XINT (tem),
5fdb398c 2353 emacs_strerror (errno));
d888760c
GM
2354 childp2 = Fplist_put (childp2, QCspeed, tem);
2355
2356 /* Configure bytesize. */
2357 if (!NILP (Fplist_member (contact, QCbytesize)))
2358 tem = Fplist_get (contact, QCbytesize);
2359 else
4d2b044c 2360 tem = Fplist_get (p->childp, QCbytesize);
d888760c
GM
2361 if (NILP (tem))
2362 tem = make_number (8);
2363 CHECK_NUMBER (tem);
2364 if (XINT (tem) != 7 && XINT (tem) != 8)
2365 error (":bytesize must be nil (8), 7, or 8");
cf84bb53 2366 summary[0] = XINT (tem) + '0';
d888760c
GM
2367#if defined (CSIZE) && defined (CS7) && defined (CS8)
2368 attr.c_cflag &= ~CSIZE;
2369 attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
2370#else
16bad4dd 2371 /* Don't error on bytesize 8, which should be set by cfmakeraw. */
d888760c
GM
2372 if (XINT (tem) != 8)
2373 error ("Bytesize cannot be changed");
2374#endif
2375 childp2 = Fplist_put (childp2, QCbytesize, tem);
2376
2377 /* Configure parity. */
2378 if (!NILP (Fplist_member (contact, QCparity)))
2379 tem = Fplist_get (contact, QCparity);
2380 else
4d2b044c 2381 tem = Fplist_get (p->childp, QCparity);
d888760c
GM
2382 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
2383 error (":parity must be nil (no parity), `even', or `odd'");
2384#if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
2385 attr.c_cflag &= ~(PARENB | PARODD);
2386 attr.c_iflag &= ~(IGNPAR | INPCK);
2387 if (NILP (tem))
2388 {
2389 summary[1] = 'N';
2390 }
2391 else if (EQ (tem, Qeven))
2392 {
2393 summary[1] = 'E';
2394 attr.c_cflag |= PARENB;
2395 attr.c_iflag |= (IGNPAR | INPCK);
2396 }
2397 else if (EQ (tem, Qodd))
2398 {
2399 summary[1] = 'O';
2400 attr.c_cflag |= (PARENB | PARODD);
2401 attr.c_iflag |= (IGNPAR | INPCK);
2402 }
2403#else
16bad4dd 2404 /* Don't error on no parity, which should be set by cfmakeraw. */
d888760c
GM
2405 if (!NILP (tem))
2406 error ("Parity cannot be configured");
2407#endif
2408 childp2 = Fplist_put (childp2, QCparity, tem);
2409
2410 /* Configure stopbits. */
2411 if (!NILP (Fplist_member (contact, QCstopbits)))
2412 tem = Fplist_get (contact, QCstopbits);
2413 else
4d2b044c 2414 tem = Fplist_get (p->childp, QCstopbits);
d888760c
GM
2415 if (NILP (tem))
2416 tem = make_number (1);
2417 CHECK_NUMBER (tem);
2418 if (XINT (tem) != 1 && XINT (tem) != 2)
2419 error (":stopbits must be nil (1 stopbit), 1, or 2");
2420 summary[2] = XINT (tem) + '0';
2421#if defined (CSTOPB)
2422 attr.c_cflag &= ~CSTOPB;
2423 if (XINT (tem) == 2)
2424 attr.c_cflag |= CSTOPB;
2425#else
16bad4dd 2426 /* Don't error on 1 stopbit, which should be set by cfmakeraw. */
d888760c
GM
2427 if (XINT (tem) != 1)
2428 error ("Stopbits cannot be configured");
2429#endif
2430 childp2 = Fplist_put (childp2, QCstopbits, tem);
2431
2432 /* Configure flowcontrol. */
2433 if (!NILP (Fplist_member (contact, QCflowcontrol)))
2434 tem = Fplist_get (contact, QCflowcontrol);
2435 else
4d2b044c 2436 tem = Fplist_get (p->childp, QCflowcontrol);
d888760c
GM
2437 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
2438 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
2439#if defined (CRTSCTS)
2440 attr.c_cflag &= ~CRTSCTS;
2441#endif
2442#if defined (CNEW_RTSCTS)
2443 attr.c_cflag &= ~CNEW_RTSCTS;
2444#endif
2445#if defined (IXON) && defined (IXOFF)
2446 attr.c_iflag &= ~(IXON | IXOFF);
2447#endif
2448 if (NILP (tem))
2449 {
2450 /* Already configured. */
2451 }
2452 else if (EQ (tem, Qhw))
2453 {
2454#if defined (CRTSCTS)
2455 attr.c_cflag |= CRTSCTS;
2456#elif defined (CNEW_RTSCTS)
2457 attr.c_cflag |= CNEW_RTSCTS;
2458#else
2459 error ("Hardware flowcontrol (RTS/CTS) not supported");
2460#endif
2461 }
2462 else if (EQ (tem, Qsw))
2463 {
2464#if defined (IXON) && defined (IXOFF)
2465 attr.c_iflag |= (IXON | IXOFF);
2466#else
2467 error ("Software flowcontrol (XON/XOFF) not supported");
2468#endif
2469 }
2470 childp2 = Fplist_put (childp2, QCflowcontrol, tem);
2471
2472 /* Activate configuration. */
2473 err = tcsetattr (p->outfd, TCSANOW, &attr);
2474 if (err != 0)
2475 error ("tcsetattr() failed: %s", emacs_strerror (errno));
2476
2477 childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
6a09a33b 2478 pset_childp (p, childp2);
d888760c 2479}
a7ebc409 2480#endif /* not DOS_NT */
06e111a6
DN
2481\f
2482/* System depended enumeration of and access to system processes a-la ps(1). */
2483
2484#ifdef HAVE_PROCFS
2485
2486/* Process enumeration and access via /proc. */
2487
2488Lisp_Object
971de7fb 2489list_system_processes (void)
06e111a6
DN
2490{
2491 Lisp_Object procdir, match, proclist, next;
2492 struct gcpro gcpro1, gcpro2;
2493 register Lisp_Object tail;
2494
2495 GCPRO2 (procdir, match);
2496 /* For every process on the system, there's a directory in the
2497 "/proc" pseudo-directory whose name is the numeric ID of that
2498 process. */
2499 procdir = build_string ("/proc");
2500 match = build_string ("[0-9]+");
86ec63ba 2501 proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil);
06e111a6
DN
2502
2503 /* `proclist' gives process IDs as strings. Destructively convert
2504 each string into a number. */
2505 for (tail = proclist; CONSP (tail); tail = next)
2506 {
2507 next = XCDR (tail);
2508 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
2509 }
2510 UNGCPRO;
2511
2512 /* directory_files_internal returns the files in reverse order; undo
2513 that. */
2514 proclist = Fnreverse (proclist);
2515 return proclist;
2516}
2517
f01769f9 2518#elif defined BSD_SYSTEM
b91b7e4d
EW
2519
2520Lisp_Object
5790543d 2521list_system_processes (void)
b91b7e4d 2522{
f3047c75 2523#if defined DARWIN_OS || defined __NetBSD__ || defined __OpenBSD__
f01769f9
LL
2524 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
2525#else
b91b7e4d 2526 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC};
f01769f9 2527#endif
b91b7e4d
EW
2528 size_t len;
2529 struct kinfo_proc *procs;
2530 size_t i;
2531
2532 struct gcpro gcpro1;
2533 Lisp_Object proclist = Qnil;
2534
2535 if (sysctl (mib, 3, NULL, &len, NULL, 0) != 0)
2536 return proclist;
5790543d 2537
b91b7e4d
EW
2538 procs = xmalloc (len);
2539 if (sysctl (mib, 3, procs, &len, NULL, 0) != 0)
2540 {
2541 xfree (procs);
2542 return proclist;
2543 }
5790543d 2544
b91b7e4d
EW
2545 GCPRO1 (proclist);
2546 len /= sizeof (struct kinfo_proc);
2547 for (i = 0; i < len; i++)
f01769f9 2548 {
f3047c75 2549#if defined DARWIN_OS || defined __NetBSD__
f01769f9 2550 proclist = Fcons (make_fixnum_or_float (procs[i].kp_proc.p_pid), proclist);
7dca65a4
PE
2551#elif defined __OpenBSD__
2552 proclist = Fcons (make_fixnum_or_float (procs[i].p_pid), proclist);
f01769f9
LL
2553#else
2554 proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist);
2555#endif
2556 }
b91b7e4d 2557 UNGCPRO;
5790543d 2558
b91b7e4d
EW
2559 xfree (procs);
2560
2561 return proclist;
2562}
2563
f8d23104
DN
2564/* The WINDOWSNT implementation is in w32.c.
2565 The MSDOS implementation is in dosfns.c. */
c4605e09 2566#elif !defined (WINDOWSNT) && !defined (MSDOS)
06e111a6
DN
2567
2568Lisp_Object
cf84bb53 2569list_system_processes (void)
06e111a6
DN
2570{
2571 return Qnil;
2572}
91c85b70
EZ
2573
2574#endif /* !defined (WINDOWSNT) */
06e111a6
DN
2575
2576#ifdef GNU_LINUX
d35af63c
PE
2577static EMACS_TIME
2578time_from_jiffies (unsigned long long tval, long hz)
2579{
2580 unsigned long long s = tval / hz;
2581 unsigned long long frac = tval % hz;
2582 int ns;
d35af63c
PE
2583
2584 if (TYPE_MAXIMUM (time_t) < s)
2585 time_overflow ();
2586 if (LONG_MAX - 1 <= ULLONG_MAX / EMACS_TIME_RESOLUTION
2587 || frac <= ULLONG_MAX / EMACS_TIME_RESOLUTION)
2588 ns = frac * EMACS_TIME_RESOLUTION / hz;
06e111a6 2589 else
d35af63c
PE
2590 {
2591 /* This is reachable only in the unlikely case that HZ * HZ
2592 exceeds ULLONG_MAX. It calculates an approximation that is
2593 guaranteed to be in range. */
2594 long hz_per_ns = (hz / EMACS_TIME_RESOLUTION
2595 + (hz % EMACS_TIME_RESOLUTION != 0));
2596 ns = frac / hz_per_ns;
2597 }
2598
e9a9ae03 2599 return make_emacs_time (s, ns);
06e111a6
DN
2600}
2601
2602static Lisp_Object
2603ltime_from_jiffies (unsigned long long tval, long hz)
2604{
d35af63c
PE
2605 EMACS_TIME t = time_from_jiffies (tval, hz);
2606 return make_lisp_time (t);
06e111a6
DN
2607}
2608
d35af63c
PE
2609static EMACS_TIME
2610get_up_time (void)
06e111a6
DN
2611{
2612 FILE *fup;
e9a9ae03 2613 EMACS_TIME up = make_emacs_time (0, 0);
06e111a6 2614
4d7e6e51 2615 block_input ();
06e111a6
DN
2616 fup = fopen ("/proc/uptime", "r");
2617
2618 if (fup)
2619 {
d35af63c
PE
2620 unsigned long long upsec, upfrac, idlesec, idlefrac;
2621 int upfrac_start, upfrac_end, idlefrac_start, idlefrac_end;
06e111a6 2622
d35af63c
PE
2623 if (fscanf (fup, "%llu.%n%llu%n %llu.%n%llu%n",
2624 &upsec, &upfrac_start, &upfrac, &upfrac_end,
2625 &idlesec, &idlefrac_start, &idlefrac, &idlefrac_end)
2626 == 4)
06e111a6 2627 {
d35af63c
PE
2628 if (TYPE_MAXIMUM (time_t) < upsec)
2629 {
2630 upsec = TYPE_MAXIMUM (time_t);
2631 upfrac = EMACS_TIME_RESOLUTION - 1;
2632 }
2633 else
2634 {
2635 int upfraclen = upfrac_end - upfrac_start;
2636 for (; upfraclen < LOG10_EMACS_TIME_RESOLUTION; upfraclen++)
2637 upfrac *= 10;
2638 for (; LOG10_EMACS_TIME_RESOLUTION < upfraclen; upfraclen--)
2639 upfrac /= 10;
2640 upfrac = min (upfrac, EMACS_TIME_RESOLUTION - 1);
2641 }
e9a9ae03 2642 up = make_emacs_time (upsec, upfrac);
06e111a6
DN
2643 }
2644 fclose (fup);
2645 }
4d7e6e51 2646 unblock_input ();
d35af63c
PE
2647
2648 return up;
06e111a6
DN
2649}
2650
2651#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
2652#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
2653
2654static Lisp_Object
f4f634e8 2655procfs_ttyname (int rdev)
06e111a6
DN
2656{
2657 FILE *fdev = NULL;
2658 char name[PATH_MAX];
2659
4d7e6e51 2660 block_input ();
06e111a6
DN
2661 fdev = fopen ("/proc/tty/drivers", "r");
2662
2663 if (fdev)
2664 {
2665 unsigned major;
2666 unsigned long minor_beg, minor_end;
2667 char minor[25]; /* 2 32-bit numbers + dash */
2668 char *endp;
2669
2670 while (!feof (fdev) && !ferror (fdev))
2671 {
2672 if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
2673 && major == MAJOR (rdev))
2674 {
2675 minor_beg = strtoul (minor, &endp, 0);
2676 if (*endp == '\0')
2677 minor_end = minor_beg;
2678 else if (*endp == '-')
2679 minor_end = strtoul (endp + 1, &endp, 0);
2680 else
2681 continue;
2682
2683 if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
2684 {
10d66ec0 2685 sprintf (name + strlen (name), "%u", MINOR (rdev));
06e111a6
DN
2686 break;
2687 }
2688 }
2689 }
2690 fclose (fdev);
2691 }
4d7e6e51 2692 unblock_input ();
06e111a6
DN
2693 return build_string (name);
2694}
2695
2696static unsigned long
2697procfs_get_total_memory (void)
2698{
2699 FILE *fmem = NULL;
2700 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
2701
4d7e6e51 2702 block_input ();
06e111a6
DN
2703 fmem = fopen ("/proc/meminfo", "r");
2704
2705 if (fmem)
2706 {
2707 unsigned long entry_value;
2708 char entry_name[20]; /* the longest I saw is 13+1 */
2709
2710 while (!feof (fmem) && !ferror (fmem))
2711 {
2712 if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
2713 && strcmp (entry_name, "MemTotal:") == 0)
2714 {
2715 retval = entry_value;
2716 break;
2717 }
2718 }
2719 fclose (fmem);
2720 }
4d7e6e51 2721 unblock_input ();
06e111a6
DN
2722 return retval;
2723}
2724
2725Lisp_Object
f4f634e8 2726system_process_attributes (Lisp_Object pid)
06e111a6
DN
2727{
2728 char procfn[PATH_MAX], fn[PATH_MAX];
2729 struct stat st;
2730 struct passwd *pw;
2731 struct group *gr;
2732 long clocks_per_sec;
2733 char *procfn_end;
2734 char procbuf[1025], *p, *q;
2735 int fd;
2736 ssize_t nread;
e99a530f
PE
2737 static char const default_cmd[] = "???";
2738 const char *cmd = default_cmd;
2739 int cmdsize = sizeof default_cmd - 1;
06e111a6 2740 char *cmdline = NULL;
e99a530f 2741 ptrdiff_t cmdline_size;
06e111a6 2742 unsigned char c;
d311d28c
PE
2743 printmax_t proc_id;
2744 int ppid, pgrp, sess, tty, tpgid, thcount;
2745 uid_t uid;
2746 gid_t gid;
a70072c9
PE
2747 unsigned long long u_time, s_time, cutime, cstime, start;
2748 long priority, niceness, rss;
06e111a6 2749 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
d35af63c 2750 EMACS_TIME tnow, tstart, tboot, telapsed, us_time;
06e111a6
DN
2751 double pcpu, pmem;
2752 Lisp_Object attrs = Qnil;
2753 Lisp_Object cmd_str, decoded_cmd, tem;
2754 struct gcpro gcpro1, gcpro2;
06e111a6
DN
2755
2756 CHECK_NUMBER_OR_FLOAT (pid);
225a2cff 2757 CONS_TO_INTEGER (pid, pid_t, proc_id);
d311d28c 2758 sprintf (procfn, "/proc/%"pMd, proc_id);
06e111a6
DN
2759 if (stat (procfn, &st) < 0)
2760 return attrs;
2761
2762 GCPRO2 (attrs, decoded_cmd);
2763
2764 /* euid egid */
2765 uid = st.st_uid;
d311d28c 2766 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
4d7e6e51 2767 block_input ();
06e111a6 2768 pw = getpwuid (uid);
4d7e6e51 2769 unblock_input ();
06e111a6
DN
2770 if (pw)
2771 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
2772
2773 gid = st.st_gid;
d311d28c 2774 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
4d7e6e51 2775 block_input ();
06e111a6 2776 gr = getgrgid (gid);
4d7e6e51 2777 unblock_input ();
06e111a6
DN
2778 if (gr)
2779 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
2780
2781 strcpy (fn, procfn);
2782 procfn_end = fn + strlen (fn);
2783 strcpy (procfn_end, "/stat");
2784 fd = emacs_open (fn, O_RDONLY, 0);
cf84bb53 2785 if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof (procbuf) - 1)) > 0)
06e111a6
DN
2786 {
2787 procbuf[nread] = '\0';
2788 p = procbuf;
2789
2790 p = strchr (p, '(');
2791 if (p != NULL)
2792 {
2793 q = strrchr (p + 1, ')');
2794 /* comm */
2795 if (q != NULL)
2796 {
2797 cmd = p + 1;
2798 cmdsize = q - cmd;
2799 }
2800 }
2801 else
2802 q = NULL;
06e111a6
DN
2803 /* Command name is encoded in locale-coding-system; decode it. */
2804 cmd_str = make_unibyte_string (cmd, cmdsize);
2805 decoded_cmd = code_convert_string_norecord (cmd_str,
2806 Vlocale_coding_system, 0);
2807 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
2808
2809 if (q)
2810 {
2811 EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint;
2812 p = q + 2;
2813 /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */
2814 sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld",
2815 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
2816 &minflt, &cminflt, &majflt, &cmajflt,
a70072c9
PE
2817 &u_time, &s_time, &cutime, &cstime,
2818 &priority, &niceness, &thcount, &start, &vsize, &rss);
06e111a6
DN
2819 {
2820 char state_str[2];
2821
2822 state_str[0] = c;
2823 state_str[1] = '\0';
2824 tem = build_string (state_str);
2825 attrs = Fcons (Fcons (Qstate, tem), attrs);
2826 }
2827 /* Stops GCC whining about limited range of data type. */
2828 ppid_eint = ppid;
2829 pgrp_eint = pgrp;
2830 sess_eint = sess;
2831 tpgid_eint = tpgid;
2832 thcount_eint = thcount;
2833 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs);
2834 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs);
2835 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs);
2836 attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
2837 attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs);
2838 attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs);
2839 attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs);
2840 attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs);
2841 attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs);
2842 clocks_per_sec = sysconf (_SC_CLK_TCK);
2843 if (clocks_per_sec < 0)
2844 clocks_per_sec = 100;
2845 attrs = Fcons (Fcons (Qutime,
a70072c9 2846 ltime_from_jiffies (u_time, clocks_per_sec)),
06e111a6
DN
2847 attrs);
2848 attrs = Fcons (Fcons (Qstime,
a70072c9 2849 ltime_from_jiffies (s_time, clocks_per_sec)),
06e111a6 2850 attrs);
ac1e4171 2851 attrs = Fcons (Fcons (Qtime,
a70072c9
PE
2852 ltime_from_jiffies (s_time + u_time,
2853 clocks_per_sec)),
ac1e4171 2854 attrs);
06e111a6
DN
2855 attrs = Fcons (Fcons (Qcutime,
2856 ltime_from_jiffies (cutime, clocks_per_sec)),
2857 attrs);
2858 attrs = Fcons (Fcons (Qcstime,
2859 ltime_from_jiffies (cstime, clocks_per_sec)),
ac1e4171
EZ
2860 attrs);
2861 attrs = Fcons (Fcons (Qctime,
2862 ltime_from_jiffies (cstime+cutime, clocks_per_sec)),
06e111a6
DN
2863 attrs);
2864 attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
a70072c9 2865 attrs = Fcons (Fcons (Qnice, make_number (niceness)), attrs);
06e111a6 2866 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
e9a9ae03 2867 tnow = current_emacs_time ();
d35af63c 2868 telapsed = get_up_time ();
e9a9ae03 2869 tboot = sub_emacs_time (tnow, telapsed);
d35af63c 2870 tstart = time_from_jiffies (start, clocks_per_sec);
e9a9ae03 2871 tstart = add_emacs_time (tboot, tstart);
d35af63c 2872 attrs = Fcons (Fcons (Qstart, make_lisp_time (tstart)), attrs);
06e111a6
DN
2873 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
2874 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
e9a9ae03 2875 telapsed = sub_emacs_time (tnow, tstart);
d35af63c
PE
2876 attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
2877 us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
2878 pcpu = (EMACS_TIME_TO_DOUBLE (us_time)
2879 / EMACS_TIME_TO_DOUBLE (telapsed));
06e111a6
DN
2880 if (pcpu > 1.0)
2881 pcpu = 1.0;
2882 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
2883 pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
2884 if (pmem > 100)
2885 pmem = 100;
2886 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
2887 }
2888 }
2889 if (fd >= 0)
2890 emacs_close (fd);
2891
2892 /* args */
2893 strcpy (procfn_end, "/cmdline");
2894 fd = emacs_open (fn, O_RDONLY, 0);
2895 if (fd >= 0)
2896 {
fbd02d7b 2897 char ch;
fe6442b1 2898 for (cmdline_size = 0; cmdline_size < STRING_BYTES_BOUND; cmdline_size++)
06e111a6 2899 {
fe6442b1
PE
2900 if (emacs_read (fd, &ch, 1) != 1)
2901 break;
fbd02d7b 2902 c = ch;
620f13b0 2903 if (c_isspace (c) || c == '\\')
06e111a6
DN
2904 cmdline_size++; /* for later quoting, see below */
2905 }
2906 if (cmdline_size)
2907 {
2908 cmdline = xmalloc (cmdline_size + 1);
2909 lseek (fd, 0L, SEEK_SET);
2910 cmdline[0] = '\0';
2911 if ((nread = read (fd, cmdline, cmdline_size)) >= 0)
2912 cmdline[nread++] = '\0';
2913 else
2914 {
2915 /* Assigning zero to `nread' makes us skip the following
2916 two loops, assign zero to cmdline_size, and enter the
2917 following `if' clause that handles unknown command
2918 lines. */
2919 nread = 0;
2920 }
2921 /* We don't want trailing null characters. */
fe6442b1 2922 for (p = cmdline + nread; p > cmdline + 1 && !p[-1]; p--)
06e111a6
DN
2923 nread--;
2924 for (p = cmdline; p < cmdline + nread; p++)
2925 {
2926 /* Escape-quote whitespace and backslashes. */
620f13b0 2927 if (c_isspace (*p) || *p == '\\')
06e111a6
DN
2928 {
2929 memmove (p + 1, p, nread - (p - cmdline));
2930 nread++;
2931 *p++ = '\\';
2932 }
2933 else if (*p == '\0')
2934 *p = ' ';
2935 }
2936 cmdline_size = nread;
2937 }
2938 if (!cmdline_size)
2939 {
06e111a6
DN
2940 cmdline_size = cmdsize + 2;
2941 cmdline = xmalloc (cmdline_size + 1);
e99a530f 2942 sprintf (cmdline, "[%.*s]", cmdsize, cmd);
06e111a6
DN
2943 }
2944 emacs_close (fd);
2945 /* Command line is encoded in locale-coding-system; decode it. */
2946 cmd_str = make_unibyte_string (cmdline, cmdline_size);
2947 decoded_cmd = code_convert_string_norecord (cmd_str,
2948 Vlocale_coding_system, 0);
2949 xfree (cmdline);
2950 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
2951 }
2952
2953 UNGCPRO;
2954 return attrs;
2955}
91c85b70 2956
f4f634e8
DN
2957#elif defined (SOLARIS2) && defined (HAVE_PROCFS)
2958
2959/* The <procfs.h> header does not like to be included if _LP64 is defined and
2960 __FILE_OFFSET_BITS == 64. This is an ugly workaround that. */
2961#if !defined (_LP64) && defined (_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
2962#define PROCFS_FILE_OFFSET_BITS_HACK 1
2963#undef _FILE_OFFSET_BITS
2964#else
2965#define PROCFS_FILE_OFFSET_BITS_HACK 0
2966#endif
2967
2968#include <procfs.h>
2969
2970#if PROCFS_FILE_OFFSET_BITS_HACK == 1
2971#define _FILE_OFFSET_BITS 64
90efadd1
PE
2972#ifdef _FILE_OFFSET_BITS /* Avoid unused-macro warnings. */
2973#endif
f4f634e8
DN
2974#endif /* PROCFS_FILE_OFFSET_BITS_HACK == 1 */
2975
2976Lisp_Object
2977system_process_attributes (Lisp_Object pid)
2978{
2979 char procfn[PATH_MAX], fn[PATH_MAX];
2980 struct stat st;
2981 struct passwd *pw;
2982 struct group *gr;
2983 char *procfn_end;
2984 struct psinfo pinfo;
2985 int fd;
2986 ssize_t nread;
d311d28c
PE
2987 printmax_t proc_id;
2988 uid_t uid;
2989 gid_t gid;
f4f634e8
DN
2990 Lisp_Object attrs = Qnil;
2991 Lisp_Object decoded_cmd, tem;
2992 struct gcpro gcpro1, gcpro2;
f4f634e8
DN
2993
2994 CHECK_NUMBER_OR_FLOAT (pid);
225a2cff 2995 CONS_TO_INTEGER (pid, pid_t, proc_id);
d311d28c 2996 sprintf (procfn, "/proc/%"pMd, proc_id);
f4f634e8
DN
2997 if (stat (procfn, &st) < 0)
2998 return attrs;
2999
3000 GCPRO2 (attrs, decoded_cmd);
3001
3002 /* euid egid */
3003 uid = st.st_uid;
d311d28c 3004 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
4d7e6e51 3005 block_input ();
f4f634e8 3006 pw = getpwuid (uid);
4d7e6e51 3007 unblock_input ();
f4f634e8
DN
3008 if (pw)
3009 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3010
3011 gid = st.st_gid;
d311d28c 3012 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
4d7e6e51 3013 block_input ();
f4f634e8 3014 gr = getgrgid (gid);
4d7e6e51 3015 unblock_input ();
f4f634e8
DN
3016 if (gr)
3017 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3018
3019 strcpy (fn, procfn);
3020 procfn_end = fn + strlen (fn);
3021 strcpy (procfn_end, "/psinfo");
3022 fd = emacs_open (fn, O_RDONLY, 0);
3023 if (fd >= 0
cf84bb53 3024 && (nread = read (fd, (char*)&pinfo, sizeof (struct psinfo)) > 0))
f4f634e8
DN
3025 {
3026 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (pinfo.pr_ppid)), attrs);
3027 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pinfo.pr_pgid)), attrs);
3028 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (pinfo.pr_sid)), attrs);
3029
3030 {
3031 char state_str[2];
3032 state_str[0] = pinfo.pr_lwp.pr_sname;
3033 state_str[1] = '\0';
3034 tem = build_string (state_str);
3035 attrs = Fcons (Fcons (Qstate, tem), attrs);
3036 }
3037
3038 /* FIXME: missing Qttyname. psinfo.pr_ttydev is a dev_t,
3039 need to get a string from it. */
3040
3041 /* FIXME: missing: Qtpgid */
3042
3043 /* FIXME: missing:
3044 Qminflt
3045 Qmajflt
3046 Qcminflt
3047 Qcmajflt
3048
bfe11752
DN
3049 Qutime
3050 Qcutime
f4f634e8
DN
3051 Qstime
3052 Qcstime
3053 Are they available? */
3054
d35af63c
PE
3055 attrs = Fcons (Fcons (Qtime, make_lisp_time (pinfo.pr_time)), attrs);
3056 attrs = Fcons (Fcons (Qctime, make_lisp_time (pinfo.pr_ctime)), attrs);
f4f634e8
DN
3057 attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs);
3058 attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs);
3059 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs);
3060
d35af63c 3061 attrs = Fcons (Fcons (Qstart, make_lisp_time (pinfo.pr_start)), attrs);
f4f634e8
DN
3062 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs);
3063 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs);
3064
773d47f6
PE
3065 /* pr_pctcpu and pr_pctmem are unsigned integers in the
3066 range 0 .. 2**15, representing 0.0 .. 1.0. */
63810350
PE
3067 attrs = Fcons (Fcons (Qpcpu, make_float (100.0 / 0x8000 * pinfo.pr_pctcpu)), attrs);
3068 attrs = Fcons (Fcons (Qpmem, make_float (100.0 / 0x8000 * pinfo.pr_pctmem)), attrs);
f4f634e8
DN
3069
3070 decoded_cmd
3071 = code_convert_string_norecord (make_unibyte_string (pinfo.pr_fname,
3072 strlen (pinfo.pr_fname)),
3073 Vlocale_coding_system, 0);
3074 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3075 decoded_cmd
3076 = code_convert_string_norecord (make_unibyte_string (pinfo.pr_psargs,
3077 strlen (pinfo.pr_psargs)),
3078 Vlocale_coding_system, 0);
3079 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3080 }
3081
2d2d05d8
DN
3082 if (fd >= 0)
3083 emacs_close (fd);
3084
f4f634e8
DN
3085 UNGCPRO;
3086 return attrs;
3087}
06e111a6 3088
5790543d 3089#elif defined __FreeBSD__
b91b7e4d 3090
d054f3fb
PE
3091static EMACS_TIME
3092timeval_to_EMACS_TIME (struct timeval t)
3093{
e9a9ae03 3094 return make_emacs_time (t.tv_sec, t.tv_usec * 1000);
d054f3fb
PE
3095}
3096
3097static Lisp_Object
db7b8d06 3098make_lisp_timeval (struct timeval t)
d054f3fb
PE
3099{
3100 return make_lisp_time (timeval_to_EMACS_TIME (t));
3101}
3102
b91b7e4d
EW
3103Lisp_Object
3104system_process_attributes (Lisp_Object pid)
3105{
3106 int proc_id;
5790543d 3107 int pagesize = getpagesize ();
b91b7e4d
EW
3108 int npages;
3109 int fscale;
3110 struct passwd *pw;
3111 struct group *gr;
3112 char *ttyname;
3113 size_t len;
3114 char args[MAXPATHLEN];
3115 EMACS_TIME t, now;
5790543d 3116
b91b7e4d
EW
3117 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
3118 struct kinfo_proc proc;
5790543d 3119 size_t proclen = sizeof proc;
b91b7e4d
EW
3120
3121 struct gcpro gcpro1, gcpro2;
3122 Lisp_Object attrs = Qnil;
3123 Lisp_Object decoded_comm;
5790543d 3124
b91b7e4d 3125 CHECK_NUMBER_OR_FLOAT (pid);
af52196c 3126 CONS_TO_INTEGER (pid, int, proc_id);
b91b7e4d 3127 mib[3] = proc_id;
5790543d 3128
b91b7e4d
EW
3129 if (sysctl (mib, 4, &proc, &proclen, NULL, 0) != 0)
3130 return attrs;
3131
3132 GCPRO2 (attrs, decoded_comm);
5790543d
PE
3133
3134 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs);
3135
4d7e6e51 3136 block_input ();
b91b7e4d 3137 pw = getpwuid (proc.ki_uid);
4d7e6e51 3138 unblock_input ();
b91b7e4d
EW
3139 if (pw)
3140 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3141
5790543d 3142 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (proc.ki_svgid)), attrs);
b91b7e4d 3143
4d7e6e51 3144 block_input ();
b91b7e4d 3145 gr = getgrgid (proc.ki_svgid);
4d7e6e51 3146 unblock_input ();
b91b7e4d
EW
3147 if (gr)
3148 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3149
3150 decoded_comm = code_convert_string_norecord
3151 (make_unibyte_string (proc.ki_comm, strlen (proc.ki_comm)),
3152 Vlocale_coding_system, 0);
5790543d 3153
b91b7e4d
EW
3154 attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
3155 {
3156 char state[2] = {'\0', '\0'};
3157 switch (proc.ki_stat)
3158 {
3159 case SRUN:
3160 state[0] = 'R';
3161 break;
3162
3163 case SSLEEP:
3164 state[0] = 'S';
3165 break;
5790543d 3166
b91b7e4d
EW
3167 case SLOCK:
3168 state[0] = 'D';
3169 break;
3170
3171 case SZOMB:
3172 state[0] = 'Z';
3173 break;
5790543d 3174
b91b7e4d
EW
3175 case SSTOP:
3176 state[0] = 'T';
3177 break;
3178 }
3179 attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
3180 }
5790543d 3181
b91b7e4d
EW
3182 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (proc.ki_ppid)), attrs);
3183 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (proc.ki_pgid)), attrs);
3184 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (proc.ki_sid)), attrs);
3185
4d7e6e51 3186 block_input ();
b91b7e4d 3187 ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR);
4d7e6e51 3188 unblock_input ();
b91b7e4d
EW
3189 if (ttyname)
3190 attrs = Fcons (Fcons (Qtty, build_string (ttyname)), attrs);
5790543d 3191
b91b7e4d
EW
3192 attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (proc.ki_tpgid)), attrs);
3193 attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (proc.ki_rusage.ru_minflt)), attrs);
3194 attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (proc.ki_rusage.ru_majflt)), attrs);
3195 attrs = Fcons (Fcons (Qcminflt, make_number (proc.ki_rusage_ch.ru_minflt)), attrs);
3196 attrs = Fcons (Fcons (Qcmajflt, make_number (proc.ki_rusage_ch.ru_majflt)), attrs);
3197
db7b8d06
PE
3198 attrs = Fcons (Fcons (Qutime, make_lisp_timeval (proc.ki_rusage.ru_utime)),
3199 attrs);
3200 attrs = Fcons (Fcons (Qstime, make_lisp_timeval (proc.ki_rusage.ru_stime)),
3201 attrs);
e9a9ae03
PE
3202 t = add_emacs_time (timeval_to_EMACS_TIME (proc.ki_rusage.ru_utime),
3203 timeval_to_EMACS_TIME (proc.ki_rusage.ru_stime));
db7b8d06 3204 attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs);
b91b7e4d 3205
db7b8d06
PE
3206 attrs = Fcons (Fcons (Qcutime,
3207 make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
3208 attrs);
3209 attrs = Fcons (Fcons (Qcstime,
3210 make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
3211 attrs);
e9a9ae03
PE
3212 t = add_emacs_time (timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_utime),
3213 timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_stime));
db7b8d06 3214 attrs = Fcons (Fcons (Qctime, make_lisp_time (t)), attrs);
b91b7e4d 3215
5790543d
PE
3216 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (proc.ki_numthreads)),
3217 attrs);
b91b7e4d
EW
3218 attrs = Fcons (Fcons (Qpri, make_number (proc.ki_pri.pri_native)), attrs);
3219 attrs = Fcons (Fcons (Qnice, make_number (proc.ki_nice)), attrs);
db7b8d06 3220 attrs = Fcons (Fcons (Qstart, make_lisp_timeval (proc.ki_start)), attrs);
b91b7e4d 3221 attrs = Fcons (Fcons (Qvsize, make_number (proc.ki_size >> 10)), attrs);
5790543d
PE
3222 attrs = Fcons (Fcons (Qrss, make_number (proc.ki_rssize * pagesize >> 10)),
3223 attrs);
b91b7e4d 3224
e9a9ae03
PE
3225 now = current_emacs_time ();
3226 t = sub_emacs_time (now, timeval_to_EMACS_TIME (proc.ki_start));
db7b8d06 3227 attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
b91b7e4d 3228
5790543d 3229 len = sizeof fscale;
b91b7e4d
EW
3230 if (sysctlbyname ("kern.fscale", &fscale, &len, NULL, 0) == 0)
3231 {
5790543d 3232 double pcpu;
b91b7e4d 3233 fixpt_t ccpu;
5790543d 3234 len = sizeof ccpu;
b91b7e4d
EW
3235 if (sysctlbyname ("kern.ccpu", &ccpu, &len, NULL, 0) == 0)
3236 {
5790543d
PE
3237 pcpu = (100.0 * proc.ki_pctcpu / fscale
3238 / (1 - exp (proc.ki_swtime * log ((double) ccpu / fscale))));
3239 attrs = Fcons (Fcons (Qpcpu, make_fixnum_or_float (pcpu)), attrs);
b91b7e4d
EW
3240 }
3241 }
3242
5790543d 3243 len = sizeof npages;
b91b7e4d
EW
3244 if (sysctlbyname ("hw.availpages", &npages, &len, NULL, 0) == 0)
3245 {
5790543d
PE
3246 double pmem = (proc.ki_flag & P_INMEM
3247 ? 100.0 * proc.ki_rssize / npages
3248 : 0);
3249 attrs = Fcons (Fcons (Qpmem, make_fixnum_or_float (pmem)), attrs);
b91b7e4d
EW
3250 }
3251
3252 mib[2] = KERN_PROC_ARGS;
3253 len = MAXPATHLEN;
3254 if (sysctl (mib, 4, args, &len, NULL, 0) == 0)
3255 {
3256 int i;
3257 for (i = 0; i < len; i++)
3258 {
3259 if (! args[i] && i < len - 1)
3260 args[i] = ' ';
3261 }
3262
5790543d
PE
3263 decoded_comm =
3264 (code_convert_string_norecord
d7ea76b4 3265 (build_unibyte_string (args),
5790543d 3266 Vlocale_coding_system, 0));
b91b7e4d
EW
3267
3268 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
3269 }
5790543d 3270
b91b7e4d
EW
3271 UNGCPRO;
3272 return attrs;
3273}
3274
f8d23104
DN
3275/* The WINDOWSNT implementation is in w32.c.
3276 The MSDOS implementation is in dosfns.c. */
c4605e09 3277#elif !defined (WINDOWSNT) && !defined (MSDOS)
06e111a6
DN
3278
3279Lisp_Object
3280system_process_attributes (Lisp_Object pid)
3281{
9dcbe89b 3282 return Qnil;
06e111a6
DN
3283}
3284
3285#endif /* !defined (WINDOWSNT) */