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