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