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