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