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