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