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