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