Regenerate.
[emacs.git] / src / sysdep.c
blob95efd5059794fa6b83a53dac9eed2a392850f879
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, 2010
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 #include <config.h>
22 #include <ctype.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <setjmp.h>
26 #ifdef HAVE_PWD_H
27 #include <pwd.h>
28 #include <grp.h>
29 #endif /* HAVE_PWD_H */
30 #ifdef HAVE_LIMITS_H
31 #include <limits.h>
32 #endif /* HAVE_LIMITS_H */
33 #include <unistd.h>
35 #include "lisp.h"
36 #include "sysselect.h"
37 #include "blockinput.h"
39 #ifdef WINDOWSNT
40 #define read sys_read
41 #define write sys_write
42 #include <windows.h>
43 #ifndef NULL
44 #define NULL 0
45 #endif
46 #endif /* not WINDOWSNT */
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <errno.h>
52 #ifdef HAVE_SETPGID
53 #if !defined (USG)
54 #undef setpgrp
55 #define setpgrp setpgid
56 #endif
57 #endif
59 /* Get SI_SRPC_DOMAIN, if it is available. */
60 #ifdef HAVE_SYS_SYSTEMINFO_H
61 #include <sys/systeminfo.h>
62 #endif
64 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
65 #include <dos.h>
66 #include "dosfns.h"
67 #include "msdos.h"
68 #include <sys/param.h>
69 #endif
71 #include <sys/file.h>
72 #include <fcntl.h>
74 #include "systty.h"
75 #include "syswait.h"
77 #ifdef HAVE_SYS_UTSNAME_H
78 #include <sys/utsname.h>
79 #include <memory.h>
80 #endif /* HAVE_SYS_UTSNAME_H */
82 #include "keyboard.h"
83 #include "frame.h"
84 #include "window.h"
85 #include "termhooks.h"
86 #include "termchar.h"
87 #include "termopts.h"
88 #include "dispextern.h"
89 #include "process.h"
90 #include "cm.h" /* for reset_sys_modes */
92 #ifdef WINDOWSNT
93 #include <direct.h>
94 /* In process.h which conflicts with the local copy. */
95 #define _P_WAIT 0
96 int _cdecl _spawnlp (int, const char *, const char *, ...);
97 int _cdecl _getpid (void);
98 extern char *getwd (char *);
99 #endif
101 #include "syssignal.h"
102 #include "systime.h"
103 #ifdef HAVE_UTIME_H
104 #include <utime.h>
105 #endif
107 #ifndef HAVE_UTIMES
108 #ifndef HAVE_STRUCT_UTIMBUF
109 /* We want to use utime rather than utimes, but we couldn't find the
110 structure declaration. We'll use the traditional one. */
111 struct utimbuf {
112 long actime;
113 long modtime;
115 #endif
116 #endif
118 /* Declare here, including term.h is problematic on some systems. */
119 extern void tputs (const char *, int, int (*)(int));
121 static const int baud_convert[] =
123 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
124 1800, 2400, 4800, 9600, 19200, 38400
127 void croak (char *) NO_RETURN;
129 /* Temporary used by `sigblock' when defined in terms of signprocmask. */
131 SIGMASKTYPE sigprocmask_set;
134 #if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
136 /* Return the current working directory. Returns NULL on errors.
137 Any other returned value must be freed with free. This is used
138 only when get_current_dir_name is not defined on the system. */
139 char*
140 get_current_dir_name (void)
142 char *buf;
143 char *pwd;
144 struct stat dotstat, pwdstat;
145 /* If PWD is accurate, use it instead of calling getwd. PWD is
146 sometimes a nicer name, and using it may avoid a fatal error if a
147 parent directory is searchable but not readable. */
148 if ((pwd = getenv ("PWD")) != 0
149 && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
150 && stat (pwd, &pwdstat) == 0
151 && stat (".", &dotstat) == 0
152 && dotstat.st_ino == pwdstat.st_ino
153 && dotstat.st_dev == pwdstat.st_dev
154 #ifdef MAXPATHLEN
155 && strlen (pwd) < MAXPATHLEN
156 #endif
159 buf = (char *) malloc (strlen (pwd) + 1);
160 if (!buf)
161 return NULL;
162 strcpy (buf, pwd);
164 #ifdef HAVE_GETCWD
165 else
167 size_t buf_size = 1024;
168 buf = (char *) malloc (buf_size);
169 if (!buf)
170 return NULL;
171 for (;;)
173 if (getcwd (buf, buf_size) == buf)
174 break;
175 if (errno != ERANGE)
177 int tmp_errno = errno;
178 free (buf);
179 errno = tmp_errno;
180 return NULL;
182 buf_size *= 2;
183 buf = (char *) realloc (buf, buf_size);
184 if (!buf)
185 return NULL;
188 #else
189 else
191 /* We need MAXPATHLEN here. */
192 buf = (char *) malloc (MAXPATHLEN + 1);
193 if (!buf)
194 return NULL;
195 if (getwd (buf) == NULL)
197 int tmp_errno = errno;
198 free (buf);
199 errno = tmp_errno;
200 return NULL;
203 #endif
204 return buf;
206 #endif
209 /* Discard pending input on all input descriptors. */
211 void
212 discard_tty_input (void)
214 #ifndef WINDOWSNT
215 struct emacs_tty buf;
217 if (noninteractive)
218 return;
220 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
221 while (dos_keyread () != -1)
223 #else /* not MSDOS */
225 struct tty_display_info *tty;
226 for (tty = tty_list; tty; tty = tty->next)
228 if (tty->input) /* Is the device suspended? */
230 emacs_get_tty (fileno (tty->input), &buf);
231 emacs_set_tty (fileno (tty->input), &buf, 0);
235 #endif /* not MSDOS */
236 #endif /* not WINDOWSNT */
240 #ifdef SIGTSTP
242 /* Arrange for character C to be read as the next input from
243 the terminal.
244 XXX What if we have multiple ttys?
247 void
248 stuff_char (char c)
250 if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
251 return;
253 /* Should perhaps error if in batch mode */
254 #ifdef TIOCSTI
255 ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
256 #else /* no TIOCSTI */
257 error ("Cannot stuff terminal input characters in this version of Unix");
258 #endif /* no TIOCSTI */
261 #endif /* SIGTSTP */
263 void
264 init_baud_rate (int fd)
266 int emacs_ospeed;
268 if (noninteractive)
269 emacs_ospeed = 0;
270 else
272 #ifdef DOS_NT
273 emacs_ospeed = 15;
274 #else /* not DOS_NT */
275 struct termios sg;
277 sg.c_cflag = B9600;
278 tcgetattr (fd, &sg);
279 emacs_ospeed = cfgetospeed (&sg);
280 #endif /* not DOS_NT */
283 baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
284 ? baud_convert[emacs_ospeed] : 9600);
285 if (baud_rate == 0)
286 baud_rate = 1200;
291 int wait_debugging; /* Set nonzero to make following function work under dbx
292 (at least for bsd). */
294 SIGTYPE
295 wait_for_termination_signal (void)
298 #ifndef MSDOS
299 /* Wait for subprocess with process id `pid' to terminate and
300 make sure it will get eliminated (not remain forever as a zombie) */
302 void
303 wait_for_termination (int pid)
305 while (1)
307 #if defined (BSD_SYSTEM) || defined (HPUX)
308 /* Note that kill returns -1 even if the process is just a zombie now.
309 But inevitably a SIGCHLD interrupt should be generated
310 and child_sig will do wait3 and make the process go away. */
311 /* There is some indication that there is a bug involved with
312 termination of subprocesses, perhaps involving a kernel bug too,
313 but no idea what it is. Just as a hunch we signal SIGCHLD to see
314 if that causes the problem to go away or get worse. */
315 sigsetmask (sigmask (SIGCHLD));
316 if (0 > kill (pid, 0))
318 sigsetmask (SIGEMPTYMASK);
319 kill (getpid (), SIGCHLD);
320 break;
322 if (wait_debugging)
323 sleep (1);
324 else
325 sigpause (SIGEMPTYMASK);
326 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
327 #ifdef WINDOWSNT
328 wait (0);
329 break;
330 #else /* not WINDOWSNT */
331 sigblock (sigmask (SIGCHLD));
332 errno = 0;
333 if (kill (pid, 0) == -1 && errno == ESRCH)
335 sigunblock (sigmask (SIGCHLD));
336 break;
339 sigsuspend (&empty_mask);
340 #endif /* not WINDOWSNT */
341 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
346 * flush any pending output
347 * (may flush input as well; it does not matter the way we use it)
350 void
351 flush_pending_output (int channel)
353 /* FIXME: maybe this function should be removed */
356 /* Set up the terminal at the other end of a pseudo-terminal that
357 we will be controlling an inferior through.
358 It should not echo or do line-editing, since that is done
359 in Emacs. No padding needed for insertion into an Emacs buffer. */
361 void
362 child_setup_tty (int out)
364 #ifndef WINDOWSNT
365 struct emacs_tty s;
367 emacs_get_tty (out, &s);
368 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
369 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
370 #ifdef NLDLY
371 /* http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00406.html
372 Some versions of GNU Hurd do not have FFDLY? */
373 #ifdef FFDLY
374 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
375 /* No output delays */
376 #else
377 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
378 /* No output delays */
379 #endif
380 #endif
381 s.main.c_lflag &= ~ECHO; /* Disable echo */
382 s.main.c_lflag |= ISIG; /* Enable signals */
383 #ifdef IUCLC
384 s.main.c_iflag &= ~IUCLC; /* Disable downcasing on input. */
385 #endif
386 #ifdef ISTRIP
387 s.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
388 #endif
389 #ifdef OLCUC
390 s.main.c_oflag &= ~OLCUC; /* Disable upcasing on output. */
391 #endif
392 s.main.c_oflag &= ~TAB3; /* Disable tab expansion */
393 s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
394 s.main.c_cc[VERASE] = CDISABLE; /* disable erase processing */
395 s.main.c_cc[VKILL] = CDISABLE; /* disable kill processing */
397 #ifdef HPUX
398 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
399 #endif /* HPUX */
401 #ifdef SIGNALS_VIA_CHARACTERS
402 /* the QUIT and INTR character are used in process_send_signal
403 so set them here to something useful. */
404 if (s.main.c_cc[VQUIT] == CDISABLE)
405 s.main.c_cc[VQUIT] = '\\'&037; /* Control-\ */
406 if (s.main.c_cc[VINTR] == CDISABLE)
407 s.main.c_cc[VINTR] = 'C'&037; /* Control-C */
408 #endif /* not SIGNALS_VIA_CHARACTERS */
410 #ifdef AIX
411 /* Also, PTY overloads NUL and BREAK.
412 don't ignore break, but don't signal either, so it looks like NUL. */
413 s.main.c_iflag &= ~IGNBRK;
414 s.main.c_iflag &= ~BRKINT;
415 /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
416 unconditionally. Then a SIGNALS_VIA_CHARACTERS conditional
417 would force it to 0377. That looks like duplicated code. */
418 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
419 #endif /* AIX */
421 /* We originally enabled ICANON (and set VEOF to 04), and then had
422 proces.c send additional EOF chars to flush the output when faced
423 with long lines, but this leads to weird effects when the
424 subprocess has disabled ICANON and ends up seeing those spurious
425 extra EOFs. So we don't send EOFs any more in
426 process.c:send_process. First we tried to disable ICANON by
427 default, so if a subsprocess sets up ICANON, it's his problem (or
428 the Elisp package that talks to it) to deal with lines that are
429 too long. But this disables some features, such as the ability
430 to send EOF signals. So we re-enabled ICANON but there is no
431 more "send eof to flush" going on (which is wrong and unportable
432 in itself). The correct way to handle too much output is to
433 buffer what could not be written and then write it again when
434 select returns ok for writing. This has it own set of
435 problems. Write is now asynchronous, is that a problem? How much
436 do we buffer, and what do we do when that limit is reached? */
438 s.main.c_lflag |= ICANON; /* Enable line editing and eof processing */
439 s.main.c_cc[VEOF] = 'D'&037; /* Control-D */
440 #if 0 /* These settings only apply to non-ICANON mode. */
441 s.main.c_cc[VMIN] = 1;
442 s.main.c_cc[VTIME] = 0;
443 #endif
445 emacs_set_tty (out, &s, 0);
446 #endif /* not WINDOWSNT */
448 #endif /* not MSDOS */
451 /* Record a signal code and the handler for it. */
452 struct save_signal
454 int code;
455 SIGTYPE (*handler) (int);
458 static void save_signal_handlers (struct save_signal *);
459 static void restore_signal_handlers (struct save_signal *);
461 /* Suspend the Emacs process; give terminal to its superior. */
463 void
464 sys_suspend (void)
466 #if defined (SIGTSTP) && !defined (MSDOS)
469 int pgrp = EMACS_GETPGRP (0);
470 EMACS_KILLPG (pgrp, SIGTSTP);
473 #else /* No SIGTSTP */
474 /* On a system where suspending is not implemented,
475 instead fork a subshell and let it talk directly to the terminal
476 while we wait. */
477 sys_subshell ();
479 #endif /* no SIGTSTP */
482 /* Fork a subshell. */
484 void
485 sys_subshell (void)
487 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
488 int st;
489 char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
490 #endif
491 int pid;
492 struct save_signal saved_handlers[5];
493 Lisp_Object dir;
494 unsigned char *str = 0;
495 int len;
497 saved_handlers[0].code = SIGINT;
498 saved_handlers[1].code = SIGQUIT;
499 saved_handlers[2].code = SIGTERM;
500 #ifdef SIGIO
501 saved_handlers[3].code = SIGIO;
502 saved_handlers[4].code = 0;
503 #else
504 saved_handlers[3].code = 0;
505 #endif
507 /* Mentioning current_buffer->buffer would mean including buffer.h,
508 which somehow wedges the hp compiler. So instead... */
510 dir = intern ("default-directory");
511 if (NILP (Fboundp (dir)))
512 goto xyzzy;
513 dir = Fsymbol_value (dir);
514 if (!STRINGP (dir))
515 goto xyzzy;
517 dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
518 str = (unsigned char *) alloca (SCHARS (dir) + 2);
519 len = SCHARS (dir);
520 memcpy (str, SDATA (dir), len);
521 if (str[len - 1] != '/') str[len++] = '/';
522 str[len] = 0;
523 xyzzy:
525 #ifdef DOS_NT
526 pid = 0;
527 save_signal_handlers (saved_handlers);
528 synch_process_alive = 1;
529 #else
530 pid = vfork ();
531 if (pid == -1)
532 error ("Can't spawn subshell");
533 #endif
535 if (pid == 0)
537 const char *sh = 0;
539 #ifdef DOS_NT /* MW, Aug 1993 */
540 getwd (oldwd);
541 if (sh == 0)
542 sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
543 #endif
544 if (sh == 0)
545 sh = (char *) egetenv ("SHELL");
546 if (sh == 0)
547 sh = "sh";
549 /* Use our buffer's default directory for the subshell. */
550 if (str)
551 chdir ((char *) str);
553 close_process_descs (); /* Close Emacs's pipes/ptys */
555 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
557 char *epwd = getenv ("PWD");
558 char old_pwd[MAXPATHLEN+1+4];
560 /* If PWD is set, pass it with corrected value. */
561 if (epwd)
563 strcpy (old_pwd, epwd);
564 if (str[len - 1] == '/')
565 str[len - 1] = '\0';
566 setenv ("PWD", str, 1);
568 st = system (sh);
569 chdir (oldwd);
570 if (epwd)
571 putenv (old_pwd); /* restore previous value */
573 #else /* not MSDOS */
574 #ifdef WINDOWSNT
575 /* Waits for process completion */
576 pid = _spawnlp (_P_WAIT, sh, sh, NULL);
577 chdir (oldwd);
578 if (pid == -1)
579 write (1, "Can't execute subshell", 22);
580 #else /* not WINDOWSNT */
581 execlp (sh, sh, (char *) 0);
582 write (1, "Can't execute subshell", 22);
583 _exit (1);
584 #endif /* not WINDOWSNT */
585 #endif /* not MSDOS */
588 /* Do this now if we did not do it before. */
589 #ifndef MSDOS
590 save_signal_handlers (saved_handlers);
591 synch_process_alive = 1;
592 #endif
594 #ifndef DOS_NT
595 wait_for_termination (pid);
596 #endif
597 restore_signal_handlers (saved_handlers);
598 synch_process_alive = 0;
601 static void
602 save_signal_handlers (struct save_signal *saved_handlers)
604 while (saved_handlers->code)
606 saved_handlers->handler
607 = (SIGTYPE (*) (int)) signal (saved_handlers->code, SIG_IGN);
608 saved_handlers++;
612 static void
613 restore_signal_handlers (struct save_signal *saved_handlers)
615 while (saved_handlers->code)
617 signal (saved_handlers->code, saved_handlers->handler);
618 saved_handlers++;
622 #ifndef SIGIO
623 /* If SIGIO is broken, don't do anything. */
624 void
625 init_sigio (int fd)
629 void
630 reset_sigio (int fd)
634 void
635 request_sigio (void)
639 void
640 unrequest_sigio (void)
644 #else
645 #ifdef F_SETFL
647 int old_fcntl_flags[MAXDESC];
649 void
650 init_sigio (int fd)
652 #ifdef FASYNC
653 old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
654 fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
655 #endif
656 interrupts_deferred = 0;
659 void
660 reset_sigio (int fd)
662 #ifdef FASYNC
663 fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
664 #endif
667 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
668 /* XXX Uhm, FASYNC is not used anymore here. */
669 /* XXX Yeah, but you need it for SIGIO, don't you? */
671 void
672 request_sigio (void)
674 if (noninteractive)
675 return;
677 #ifdef SIGWINCH
678 sigunblock (sigmask (SIGWINCH));
679 #endif
680 sigunblock (sigmask (SIGIO));
682 interrupts_deferred = 0;
685 void
686 unrequest_sigio (void)
688 if (noninteractive)
689 return;
691 #if 0 /* XXX What's wrong with blocking SIGIO under X? */
692 if (x_display_list)
693 return;
694 #endif
696 #ifdef SIGWINCH
697 sigblock (sigmask (SIGWINCH));
698 #endif
699 sigblock (sigmask (SIGIO));
700 interrupts_deferred = 1;
703 #else /* no FASYNC */
704 #ifndef MSDOS
706 void
707 request_sigio (void)
709 if (noninteractive || read_socket_hook)
710 return;
712 croak ("request_sigio");
715 void
716 unrequest_sigio (void)
718 if (noninteractive || read_socket_hook)
719 return;
721 croak ("unrequest_sigio");
724 #endif /* MSDOS */
725 #endif /* FASYNC */
726 #endif /* F_SETFL */
727 #endif /* SIGIO */
730 /* Getting and setting emacs_tty structures. */
732 /* Set *TC to the parameters associated with the terminal FD.
733 Return zero if all's well, or -1 if we ran into an error we
734 couldn't deal with. */
736 emacs_get_tty (int fd, struct emacs_tty *settings)
738 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
739 #ifndef DOS_NT
740 /* We have those nifty POSIX tcmumbleattr functions. */
741 memset (&settings->main, 0, sizeof (settings->main));
742 if (tcgetattr (fd, &settings->main) < 0)
743 return -1;
744 #endif
746 /* We have survived the tempest. */
747 return 0;
751 /* Set the parameters of the tty on FD according to the contents of
752 *SETTINGS. If FLUSHP is non-zero, we discard input.
753 Return 0 if all went well, and -1 if anything failed. */
756 emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
758 /* Set the primary parameters - baud rate, character size, etcetera. */
759 #ifndef DOS_NT
760 int i;
761 /* We have those nifty POSIX tcmumbleattr functions.
762 William J. Smith <wjs@wiis.wang.com> writes:
763 "POSIX 1003.1 defines tcsetattr to return success if it was
764 able to perform any of the requested actions, even if some
765 of the requested actions could not be performed.
766 We must read settings back to ensure tty setup properly.
767 AIX requires this to keep tty from hanging occasionally." */
768 /* This make sure that we don't loop indefinitely in here. */
769 for (i = 0 ; i < 10 ; i++)
770 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
772 if (errno == EINTR)
773 continue;
774 else
775 return -1;
777 else
779 struct termios new;
781 memset (&new, 0, sizeof (new));
782 /* Get the current settings, and see if they're what we asked for. */
783 tcgetattr (fd, &new);
784 /* We cannot use memcmp on the whole structure here because under
785 * aix386 the termios structure has some reserved field that may
786 * not be filled in.
788 if ( new.c_iflag == settings->main.c_iflag
789 && new.c_oflag == settings->main.c_oflag
790 && new.c_cflag == settings->main.c_cflag
791 && new.c_lflag == settings->main.c_lflag
792 && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
793 break;
794 else
795 continue;
797 #endif
799 /* We have survived the tempest. */
800 return 0;
805 #ifdef F_SETOWN
806 int old_fcntl_owner[MAXDESC];
807 #endif /* F_SETOWN */
809 /* This may also be defined in stdio,
810 but if so, this does no harm,
811 and using the same name avoids wasting the other one's space. */
813 #if defined (USG)
814 unsigned char _sobuf[BUFSIZ+8];
815 #else
816 char _sobuf[BUFSIZ];
817 #endif
819 /* Initialize the terminal mode on all tty devices that are currently
820 open. */
822 void
823 init_all_sys_modes (void)
825 struct tty_display_info *tty;
826 for (tty = tty_list; tty; tty = tty->next)
827 init_sys_modes (tty);
830 /* Initialize the terminal mode on the given tty device. */
832 void
833 init_sys_modes (struct tty_display_info *tty_out)
835 struct emacs_tty tty;
837 Vtty_erase_char = Qnil;
839 if (noninteractive)
840 return;
842 if (!tty_out->output)
843 return; /* The tty is suspended. */
845 if (! tty_out->old_tty)
846 tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
848 emacs_get_tty (fileno (tty_out->input), tty_out->old_tty);
850 tty = *tty_out->old_tty;
852 #if !defined (DOS_NT)
853 XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
855 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
856 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
857 #ifdef INLCR /* I'm just being cautious,
858 since I can't check how widespread INLCR is--rms. */
859 tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
860 #endif
861 #ifdef ISTRIP
862 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
863 #endif
864 tty.main.c_lflag &= ~ECHO; /* Disable echo */
865 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
866 #ifdef IEXTEN
867 tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
868 #endif
869 tty.main.c_lflag |= ISIG; /* Enable signals */
870 if (tty_out->flow_control)
872 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
873 #ifdef IXANY
874 tty.main.c_iflag &= ~IXANY;
875 #endif /* IXANY */
877 else
878 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
879 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
880 on output */
881 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
882 #ifdef CS8
883 if (tty_out->meta_key)
885 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
886 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
888 #endif
889 if (tty_out->input == stdin)
891 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
892 /* Set up C-g for both SIGQUIT and SIGINT.
893 We don't know which we will get, but we handle both alike
894 so which one it really gives us does not matter. */
895 tty.main.c_cc[VQUIT] = quit_char;
897 else
899 /* We normally don't get interrupt or quit signals from tty
900 devices other than our controlling terminal; therefore,
901 we must handle C-g as normal input. Unfortunately, this
902 means that the interrupt and quit feature must be
903 disabled on secondary ttys, or we would not even see the
904 keypress.
906 Note that even though emacsclient could have special code
907 to pass SIGINT to Emacs, we should _not_ enable
908 interrupt/quit keys for emacsclient frames. This means
909 that we can't break out of loops in C code from a
910 secondary tty frame, but we can always decide what
911 display the C-g came from, which is more important from a
912 usability point of view. (Consider the case when two
913 people work together using the same Emacs instance.) */
914 tty.main.c_cc[VINTR] = CDISABLE;
915 tty.main.c_cc[VQUIT] = CDISABLE;
917 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
918 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
919 #ifdef VSWTCH
920 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
921 of C-z */
922 #endif /* VSWTCH */
924 #ifdef VSUSP
925 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off handling of C-z. */
926 #endif /* VSUSP */
927 #ifdef V_DSUSP
928 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off handling of C-y. */
929 #endif /* V_DSUSP */
930 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
931 tty.main.c_cc[VDSUSP] = CDISABLE;
932 #endif /* VDSUSP */
933 #ifdef VLNEXT
934 tty.main.c_cc[VLNEXT] = CDISABLE;
935 #endif /* VLNEXT */
936 #ifdef VREPRINT
937 tty.main.c_cc[VREPRINT] = CDISABLE;
938 #endif /* VREPRINT */
939 #ifdef VWERASE
940 tty.main.c_cc[VWERASE] = CDISABLE;
941 #endif /* VWERASE */
942 #ifdef VDISCARD
943 tty.main.c_cc[VDISCARD] = CDISABLE;
944 #endif /* VDISCARD */
946 if (tty_out->flow_control)
948 #ifdef VSTART
949 tty.main.c_cc[VSTART] = '\021';
950 #endif /* VSTART */
951 #ifdef VSTOP
952 tty.main.c_cc[VSTOP] = '\023';
953 #endif /* VSTOP */
955 else
957 #ifdef VSTART
958 tty.main.c_cc[VSTART] = CDISABLE;
959 #endif /* VSTART */
960 #ifdef VSTOP
961 tty.main.c_cc[VSTOP] = CDISABLE;
962 #endif /* VSTOP */
965 #ifdef AIX
966 tty.main.c_cc[VSTRT] = CDISABLE;
967 tty.main.c_cc[VSTOP] = CDISABLE;
968 tty.main.c_cc[VSUSP] = CDISABLE;
969 tty.main.c_cc[VDSUSP] = CDISABLE;
970 if (tty_out->flow_control)
972 #ifdef VSTART
973 tty.main.c_cc[VSTART] = '\021';
974 #endif /* VSTART */
975 #ifdef VSTOP
976 tty.main.c_cc[VSTOP] = '\023';
977 #endif /* VSTOP */
979 /* Also, PTY overloads NUL and BREAK.
980 don't ignore break, but don't signal either, so it looks like NUL.
981 This really serves a purpose only if running in an XTERM window
982 or via TELNET or the like, but does no harm elsewhere. */
983 tty.main.c_iflag &= ~IGNBRK;
984 tty.main.c_iflag &= ~BRKINT;
985 #endif
986 #endif /* not DOS_NT */
988 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
989 if (!tty_out->term_initted)
990 internal_terminal_init ();
991 dos_ttraw (tty_out);
992 #endif
994 emacs_set_tty (fileno (tty_out->input), &tty, 0);
996 /* This code added to insure that, if flow-control is not to be used,
997 we have an unlocked terminal at the start. */
999 #ifdef TCXONC
1000 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
1001 #endif
1002 #ifdef TIOCSTART
1003 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
1004 #endif
1006 #if !defined (DOS_NT)
1007 #ifdef TCOON
1008 if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
1009 #endif
1010 #endif
1012 #ifdef F_SETFL
1013 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1014 if (interrupt_input)
1016 old_fcntl_owner[fileno (tty_out->input)] =
1017 fcntl (fileno (tty_out->input), F_GETOWN, 0);
1018 fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
1019 init_sigio (fileno (tty_out->input));
1020 #ifdef HAVE_GPM
1021 if (gpm_tty == tty_out)
1023 /* Arrange for mouse events to give us SIGIO signals. */
1024 fcntl (gpm_fd, F_SETOWN, getpid ());
1025 fcntl (gpm_fd, F_SETFL, fcntl (gpm_fd, F_GETFL, 0) | O_NONBLOCK);
1026 init_sigio (gpm_fd);
1028 #endif /* HAVE_GPM */
1030 #endif /* F_GETOWN */
1031 #endif /* F_SETFL */
1033 #ifdef _IOFBF
1034 /* This symbol is defined on recent USG systems.
1035 Someone says without this call USG won't really buffer the file
1036 even with a call to setbuf. */
1037 setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf);
1038 #else
1039 setbuf (tty_out->output, (char *) _sobuf);
1040 #endif
1042 if (tty_out->terminal->set_terminal_modes_hook)
1043 tty_out->terminal->set_terminal_modes_hook (tty_out->terminal);
1045 if (!tty_out->term_initted)
1047 Lisp_Object tail, frame;
1048 FOR_EACH_FRAME (tail, frame)
1050 /* XXX This needs to be revised. */
1051 if (FRAME_TERMCAP_P (XFRAME (frame))
1052 && FRAME_TTY (XFRAME (frame)) == tty_out)
1053 init_frame_faces (XFRAME (frame));
1057 if (tty_out->term_initted && no_redraw_on_reenter)
1059 /* We used to call "direct_output_forward_char(0)" here,
1060 but it's not clear why, since it may not do anything anyway. */
1062 else
1064 Lisp_Object tail, frame;
1065 frame_garbaged = 1;
1066 FOR_EACH_FRAME (tail, frame)
1068 if ((FRAME_TERMCAP_P (XFRAME (frame))
1069 || FRAME_MSDOS_P (XFRAME (frame)))
1070 && FRAME_TTY (XFRAME (frame)) == tty_out)
1071 FRAME_GARBAGED_P (XFRAME (frame)) = 1;
1075 tty_out->term_initted = 1;
1078 /* Return nonzero if safe to use tabs in output.
1079 At the time this is called, init_sys_modes has not been done yet. */
1082 tabs_safe_p (int fd)
1084 struct emacs_tty etty;
1086 emacs_get_tty (fd, &etty);
1087 #ifndef DOS_NT
1088 #ifdef TABDLY
1089 return ((etty.main.c_oflag & TABDLY) != TAB3);
1090 #else /* not TABDLY */
1091 return 1;
1092 #endif /* not TABDLY */
1093 #else /* DOS_NT */
1094 return 0;
1095 #endif /* DOS_NT */
1098 /* Get terminal size from system.
1099 Store number of lines into *HEIGHTP and width into *WIDTHP.
1100 We store 0 if there's no valid information. */
1102 void
1103 get_tty_size (int fd, int *widthp, int *heightp)
1106 #ifdef TIOCGWINSZ
1108 /* BSD-style. */
1109 struct winsize size;
1111 if (ioctl (fd, TIOCGWINSZ, &size) == -1)
1112 *widthp = *heightp = 0;
1113 else
1115 *widthp = size.ws_col;
1116 *heightp = size.ws_row;
1119 #else
1120 #ifdef TIOCGSIZE
1122 /* SunOS - style. */
1123 struct ttysize size;
1125 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1126 *widthp = *heightp = 0;
1127 else
1129 *widthp = size.ts_cols;
1130 *heightp = size.ts_lines;
1133 #else
1134 #ifdef MSDOS
1135 *widthp = ScreenCols ();
1136 *heightp = ScreenRows ();
1137 #else /* system doesn't know size */
1138 *widthp = 0;
1139 *heightp = 0;
1140 #endif
1141 #endif /* not SunOS-style */
1142 #endif /* not BSD-style */
1145 /* Set the logical window size associated with descriptor FD
1146 to HEIGHT and WIDTH. This is used mainly with ptys. */
1149 set_window_size (int fd, int height, int width)
1151 #ifdef TIOCSWINSZ
1153 /* BSD-style. */
1154 struct winsize size;
1155 size.ws_row = height;
1156 size.ws_col = width;
1158 if (ioctl (fd, TIOCSWINSZ, &size) == -1)
1159 return 0; /* error */
1160 else
1161 return 1;
1163 #else
1164 #ifdef TIOCSSIZE
1166 /* SunOS - style. */
1167 struct ttysize size;
1168 size.ts_lines = height;
1169 size.ts_cols = width;
1171 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1172 return 0;
1173 else
1174 return 1;
1175 #else
1176 return -1;
1177 #endif /* not SunOS-style */
1178 #endif /* not BSD-style */
1183 /* Prepare all terminal devices for exiting Emacs. */
1185 void
1186 reset_all_sys_modes (void)
1188 struct tty_display_info *tty;
1189 for (tty = tty_list; tty; tty = tty->next)
1190 reset_sys_modes (tty);
1193 /* Prepare the terminal for closing it; move the cursor to the
1194 bottom of the frame, turn off interrupt-driven I/O, etc. */
1196 void
1197 reset_sys_modes (struct tty_display_info *tty_out)
1199 if (noninteractive)
1201 fflush (stdout);
1202 return;
1204 if (!tty_out->term_initted)
1205 return;
1207 if (!tty_out->output)
1208 return; /* The tty is suspended. */
1210 /* Go to and clear the last line of the terminal. */
1212 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1214 /* Code adapted from tty_clear_end_of_line. */
1215 if (tty_out->TS_clr_line)
1217 emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc);
1219 else
1220 { /* have to do it the hard way */
1221 int i;
1222 tty_turn_off_insert (tty_out);
1224 for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
1226 fputc (' ', tty_out->output);
1230 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1231 fflush (tty_out->output);
1233 if (tty_out->terminal->reset_terminal_modes_hook)
1234 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
1236 #ifdef BSD_SYSTEM
1237 /* Avoid possible loss of output when changing terminal modes. */
1238 fsync (fileno (tty_out->output));
1239 #endif
1241 #ifdef F_SETFL
1242 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1243 if (interrupt_input)
1245 reset_sigio (fileno (tty_out->input));
1246 fcntl (fileno (tty_out->input), F_SETOWN,
1247 old_fcntl_owner[fileno (tty_out->input)]);
1249 #endif /* F_SETOWN */
1250 #ifdef O_NDELAY
1251 fcntl (fileno (tty_out->input), F_SETFL,
1252 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
1253 #endif
1254 #endif /* F_SETFL */
1256 if (tty_out->old_tty)
1257 while (emacs_set_tty (fileno (tty_out->input),
1258 tty_out->old_tty, 0) < 0 && errno == EINTR)
1261 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1262 dos_ttcooked ();
1263 #endif
1267 #ifdef HAVE_PTYS
1269 /* Set up the proper status flags for use of a pty. */
1271 void
1272 setup_pty (int fd)
1274 /* I'm told that TOICREMOTE does not mean control chars
1275 "can't be sent" but rather that they don't have
1276 input-editing or signaling effects.
1277 That should be good, because we have other ways
1278 to do those things in Emacs.
1279 However, telnet mode seems not to work on 4.2.
1280 So TIOCREMOTE is turned off now. */
1282 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1283 will hang. In particular, the "timeout" feature (which
1284 causes a read to return if there is no data available)
1285 does this. Also it is known that telnet mode will hang
1286 in such a way that Emacs must be stopped (perhaps this
1287 is the same problem).
1289 If TIOCREMOTE is turned off, then there is a bug in
1290 hp-ux which sometimes loses data. Apparently the
1291 code which blocks the master process when the internal
1292 buffer fills up does not work. Other than this,
1293 though, everything else seems to work fine.
1295 Since the latter lossage is more benign, we may as well
1296 lose that way. -- cph */
1297 #ifdef FIONBIO
1298 #if defined(UNIX98_PTYS)
1300 int on = 1;
1301 ioctl (fd, FIONBIO, &on);
1303 #endif
1304 #endif
1306 #endif /* HAVE_PTYS */
1308 /* init_system_name sets up the string for the Lisp function
1309 system-name to return. */
1311 extern Lisp_Object Vsystem_name;
1313 #ifdef HAVE_SOCKETS
1314 #include <sys/socket.h>
1315 #include <netdb.h>
1316 #endif /* HAVE_SOCKETS */
1318 #ifdef TRY_AGAIN
1319 #ifndef HAVE_H_ERRNO
1320 extern int h_errno;
1321 #endif
1322 #endif /* TRY_AGAIN */
1324 void
1325 init_system_name (void)
1327 #ifndef HAVE_GETHOSTNAME
1328 struct utsname uts;
1329 uname (&uts);
1330 Vsystem_name = build_string (uts.nodename);
1331 #else /* HAVE_GETHOSTNAME */
1332 unsigned int hostname_size = 256;
1333 char *hostname = (char *) alloca (hostname_size);
1335 /* Try to get the host name; if the buffer is too short, try
1336 again. Apparently, the only indication gethostname gives of
1337 whether the buffer was large enough is the presence or absence
1338 of a '\0' in the string. Eech. */
1339 for (;;)
1341 gethostname (hostname, hostname_size - 1);
1342 hostname[hostname_size - 1] = '\0';
1344 /* Was the buffer large enough for the '\0'? */
1345 if (strlen (hostname) < hostname_size - 1)
1346 break;
1348 hostname_size <<= 1;
1349 hostname = (char *) alloca (hostname_size);
1351 #ifdef HAVE_SOCKETS
1352 /* Turn the hostname into the official, fully-qualified hostname.
1353 Don't do this if we're going to dump; this can confuse system
1354 libraries on some machines and make the dumped emacs core dump. */
1355 #ifndef CANNOT_DUMP
1356 if (initialized)
1357 #endif /* not CANNOT_DUMP */
1358 if (! strchr (hostname, '.'))
1360 int count;
1361 #ifdef HAVE_GETADDRINFO
1362 struct addrinfo *res;
1363 struct addrinfo hints;
1364 int ret;
1366 memset (&hints, 0, sizeof (hints));
1367 hints.ai_socktype = SOCK_STREAM;
1368 hints.ai_flags = AI_CANONNAME;
1370 for (count = 0;; count++)
1372 if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
1373 || ret != EAI_AGAIN)
1374 break;
1376 if (count >= 5)
1377 break;
1378 Fsleep_for (make_number (1), Qnil);
1381 if (ret == 0)
1383 struct addrinfo *it = res;
1384 while (it)
1386 char *fqdn = it->ai_canonname;
1387 if (fqdn && strchr (fqdn, '.')
1388 && strcmp (fqdn, "localhost.localdomain") != 0)
1389 break;
1390 it = it->ai_next;
1392 if (it)
1394 hostname = alloca (strlen (it->ai_canonname) + 1);
1395 strcpy (hostname, it->ai_canonname);
1397 freeaddrinfo (res);
1399 #else /* !HAVE_GETADDRINFO */
1400 struct hostent *hp;
1401 for (count = 0;; count++)
1404 #ifdef TRY_AGAIN
1405 h_errno = 0;
1406 #endif
1407 hp = gethostbyname (hostname);
1408 #ifdef TRY_AGAIN
1409 if (! (hp == 0 && h_errno == TRY_AGAIN))
1410 #endif
1412 break;
1414 if (count >= 5)
1415 break;
1416 Fsleep_for (make_number (1), Qnil);
1419 if (hp)
1421 char *fqdn = (char *) hp->h_name;
1423 if (!strchr (fqdn, '.'))
1425 /* We still don't have a fully qualified domain name.
1426 Try to find one in the list of alternate names */
1427 char **alias = hp->h_aliases;
1428 while (*alias
1429 && (!strchr (*alias, '.')
1430 || !strcmp (*alias, "localhost.localdomain")))
1431 alias++;
1432 if (*alias)
1433 fqdn = *alias;
1435 hostname = fqdn;
1437 #endif /* !HAVE_GETADDRINFO */
1439 #endif /* HAVE_SOCKETS */
1440 Vsystem_name = build_string (hostname);
1441 #endif /* HAVE_GETHOSTNAME */
1443 unsigned char *p;
1444 for (p = SDATA (Vsystem_name); *p; p++)
1445 if (*p == ' ' || *p == '\t')
1446 *p = '-';
1450 /* POSIX signals support - DJB */
1451 /* Anyone with POSIX signals should have ANSI C declarations */
1453 sigset_t empty_mask, full_mask;
1455 #ifndef WINDOWSNT
1457 signal_handler_t
1458 sys_signal (int signal_number, signal_handler_t action)
1460 struct sigaction new_action, old_action;
1461 sigemptyset (&new_action.sa_mask);
1462 new_action.sa_handler = action;
1463 new_action.sa_flags = 0;
1464 #if defined (SA_RESTART)
1465 /* Emacs mostly works better with restartable system services. If this
1466 flag exists, we probably want to turn it on here.
1467 However, on some systems this resets the timeout of `select'
1468 which means that `select' never finishes if it keeps getting signals.
1469 BROKEN_SA_RESTART is defined on those systems. */
1470 /* It's not clear why the comment above says "mostly works better". --Stef
1471 When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
1472 for pending input so we need long-running syscalls to be interrupted
1473 after a signal that sets the interrupt_input_pending flag. */
1474 /* Non-interactive keyboard input goes through stdio, where we always
1475 want restartable system calls. */
1476 # if defined (BROKEN_SA_RESTART) || defined(SYNC_INPUT)
1477 if (noninteractive)
1478 # endif
1479 new_action.sa_flags = SA_RESTART;
1480 #endif
1481 sigaction (signal_number, &new_action, &old_action);
1482 return (old_action.sa_handler);
1485 #endif /* WINDOWSNT */
1487 #ifndef __GNUC__
1488 /* If we're compiling with GCC, we don't need this function, since it
1489 can be written as a macro. */
1490 sigset_t
1491 sys_sigmask (int sig)
1493 sigset_t mask;
1494 sigemptyset (&mask);
1495 sigaddset (&mask, sig);
1496 return mask;
1498 #endif
1500 /* I'd like to have these guys return pointers to the mask storage in here,
1501 but there'd be trouble if the code was saving multiple masks. I'll be
1502 safe and pass the structure. It normally won't be more than 2 bytes
1503 anyhow. - DJB */
1505 sigset_t
1506 sys_sigblock (sigset_t new_mask)
1508 sigset_t old_mask;
1509 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
1510 return (old_mask);
1513 sigset_t
1514 sys_sigunblock (sigset_t new_mask)
1516 sigset_t old_mask;
1517 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
1518 return (old_mask);
1521 sigset_t
1522 sys_sigsetmask (sigset_t new_mask)
1524 sigset_t old_mask;
1525 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
1526 return (old_mask);
1530 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
1531 static char *my_sys_siglist[NSIG];
1532 # ifdef sys_siglist
1533 # undef sys_siglist
1534 # endif
1535 # define sys_siglist my_sys_siglist
1536 #endif
1538 void
1539 init_signals (void)
1541 sigemptyset (&empty_mask);
1542 sigfillset (&full_mask);
1544 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
1545 if (! initialized)
1547 # ifdef SIGABRT
1548 sys_siglist[SIGABRT] = "Aborted";
1549 # endif
1550 # ifdef SIGAIO
1551 sys_siglist[SIGAIO] = "LAN I/O interrupt";
1552 # endif
1553 # ifdef SIGALRM
1554 sys_siglist[SIGALRM] = "Alarm clock";
1555 # endif
1556 # ifdef SIGBUS
1557 sys_siglist[SIGBUS] = "Bus error";
1558 # endif
1559 # ifdef SIGCLD
1560 sys_siglist[SIGCLD] = "Child status changed";
1561 # endif
1562 # ifdef SIGCHLD
1563 sys_siglist[SIGCHLD] = "Child status changed";
1564 # endif
1565 # ifdef SIGCONT
1566 sys_siglist[SIGCONT] = "Continued";
1567 # endif
1568 # ifdef SIGDANGER
1569 sys_siglist[SIGDANGER] = "Swap space dangerously low";
1570 # endif
1571 # ifdef SIGDGNOTIFY
1572 sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
1573 # endif
1574 # ifdef SIGEMT
1575 sys_siglist[SIGEMT] = "Emulation trap";
1576 # endif
1577 # ifdef SIGFPE
1578 sys_siglist[SIGFPE] = "Arithmetic exception";
1579 # endif
1580 # ifdef SIGFREEZE
1581 sys_siglist[SIGFREEZE] = "SIGFREEZE";
1582 # endif
1583 # ifdef SIGGRANT
1584 sys_siglist[SIGGRANT] = "Monitor mode granted";
1585 # endif
1586 # ifdef SIGHUP
1587 sys_siglist[SIGHUP] = "Hangup";
1588 # endif
1589 # ifdef SIGILL
1590 sys_siglist[SIGILL] = "Illegal instruction";
1591 # endif
1592 # ifdef SIGINT
1593 sys_siglist[SIGINT] = "Interrupt";
1594 # endif
1595 # ifdef SIGIO
1596 sys_siglist[SIGIO] = "I/O possible";
1597 # endif
1598 # ifdef SIGIOINT
1599 sys_siglist[SIGIOINT] = "I/O intervention required";
1600 # endif
1601 # ifdef SIGIOT
1602 sys_siglist[SIGIOT] = "IOT trap";
1603 # endif
1604 # ifdef SIGKILL
1605 sys_siglist[SIGKILL] = "Killed";
1606 # endif
1607 # ifdef SIGLOST
1608 sys_siglist[SIGLOST] = "Resource lost";
1609 # endif
1610 # ifdef SIGLWP
1611 sys_siglist[SIGLWP] = "SIGLWP";
1612 # endif
1613 # ifdef SIGMSG
1614 sys_siglist[SIGMSG] = "Monitor mode data available";
1615 # endif
1616 # ifdef SIGPHONE
1617 sys_siglist[SIGWIND] = "SIGPHONE";
1618 # endif
1619 # ifdef SIGPIPE
1620 sys_siglist[SIGPIPE] = "Broken pipe";
1621 # endif
1622 # ifdef SIGPOLL
1623 sys_siglist[SIGPOLL] = "Pollable event occurred";
1624 # endif
1625 # ifdef SIGPROF
1626 sys_siglist[SIGPROF] = "Profiling timer expired";
1627 # endif
1628 # ifdef SIGPTY
1629 sys_siglist[SIGPTY] = "PTY I/O interrupt";
1630 # endif
1631 # ifdef SIGPWR
1632 sys_siglist[SIGPWR] = "Power-fail restart";
1633 # endif
1634 # ifdef SIGQUIT
1635 sys_siglist[SIGQUIT] = "Quit";
1636 # endif
1637 # ifdef SIGRETRACT
1638 sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
1639 # endif
1640 # ifdef SIGSAK
1641 sys_siglist[SIGSAK] = "Secure attention";
1642 # endif
1643 # ifdef SIGSEGV
1644 sys_siglist[SIGSEGV] = "Segmentation violation";
1645 # endif
1646 # ifdef SIGSOUND
1647 sys_siglist[SIGSOUND] = "Sound completed";
1648 # endif
1649 # ifdef SIGSTOP
1650 sys_siglist[SIGSTOP] = "Stopped (signal)";
1651 # endif
1652 # ifdef SIGSTP
1653 sys_siglist[SIGSTP] = "Stopped (user)";
1654 # endif
1655 # ifdef SIGSYS
1656 sys_siglist[SIGSYS] = "Bad argument to system call";
1657 # endif
1658 # ifdef SIGTERM
1659 sys_siglist[SIGTERM] = "Terminated";
1660 # endif
1661 # ifdef SIGTHAW
1662 sys_siglist[SIGTHAW] = "SIGTHAW";
1663 # endif
1664 # ifdef SIGTRAP
1665 sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
1666 # endif
1667 # ifdef SIGTSTP
1668 sys_siglist[SIGTSTP] = "Stopped (user)";
1669 # endif
1670 # ifdef SIGTTIN
1671 sys_siglist[SIGTTIN] = "Stopped (tty input)";
1672 # endif
1673 # ifdef SIGTTOU
1674 sys_siglist[SIGTTOU] = "Stopped (tty output)";
1675 # endif
1676 # ifdef SIGURG
1677 sys_siglist[SIGURG] = "Urgent I/O condition";
1678 # endif
1679 # ifdef SIGUSR1
1680 sys_siglist[SIGUSR1] = "User defined signal 1";
1681 # endif
1682 # ifdef SIGUSR2
1683 sys_siglist[SIGUSR2] = "User defined signal 2";
1684 # endif
1685 # ifdef SIGVTALRM
1686 sys_siglist[SIGVTALRM] = "Virtual timer expired";
1687 # endif
1688 # ifdef SIGWAITING
1689 sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
1690 # endif
1691 # ifdef SIGWINCH
1692 sys_siglist[SIGWINCH] = "Window size changed";
1693 # endif
1694 # ifdef SIGWIND
1695 sys_siglist[SIGWIND] = "SIGWIND";
1696 # endif
1697 # ifdef SIGXCPU
1698 sys_siglist[SIGXCPU] = "CPU time limit exceeded";
1699 # endif
1700 # ifdef SIGXFSZ
1701 sys_siglist[SIGXFSZ] = "File size limit exceeded";
1702 # endif
1704 #endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
1707 #ifndef HAVE_RANDOM
1708 #ifdef random
1709 #define HAVE_RANDOM
1710 #endif
1711 #endif
1713 /* Figure out how many bits the system's random number generator uses.
1714 `random' and `lrand48' are assumed to return 31 usable bits.
1715 BSD `rand' returns a 31 bit value but the low order bits are unusable;
1716 so we'll shift it and treat it like the 15-bit USG `rand'. */
1718 #ifndef RAND_BITS
1719 # ifdef HAVE_RANDOM
1720 # define RAND_BITS 31
1721 # else /* !HAVE_RANDOM */
1722 # ifdef HAVE_LRAND48
1723 # define RAND_BITS 31
1724 # define random lrand48
1725 # else /* !HAVE_LRAND48 */
1726 # define RAND_BITS 15
1727 # if RAND_MAX == 32767
1728 # define random rand
1729 # else /* RAND_MAX != 32767 */
1730 # if RAND_MAX == 2147483647
1731 # define random() (rand () >> 16)
1732 # else /* RAND_MAX != 2147483647 */
1733 # ifdef USG
1734 # define random rand
1735 # else
1736 # define random() (rand () >> 16)
1737 # endif /* !USG */
1738 # endif /* RAND_MAX != 2147483647 */
1739 # endif /* RAND_MAX != 32767 */
1740 # endif /* !HAVE_LRAND48 */
1741 # endif /* !HAVE_RANDOM */
1742 #endif /* !RAND_BITS */
1744 void
1745 seed_random (long int arg)
1747 #ifdef HAVE_RANDOM
1748 srandom ((unsigned int)arg);
1749 #else
1750 # ifdef HAVE_LRAND48
1751 srand48 (arg);
1752 # else
1753 srand ((unsigned int)arg);
1754 # endif
1755 #endif
1759 * Build a full Emacs-sized word out of whatever we've got.
1760 * This suffices even for a 64-bit architecture with a 15-bit rand.
1762 long
1763 get_random (void)
1765 long val = random ();
1766 #if VALBITS > RAND_BITS
1767 val = (val << RAND_BITS) ^ random ();
1768 #if VALBITS > 2*RAND_BITS
1769 val = (val << RAND_BITS) ^ random ();
1770 #if VALBITS > 3*RAND_BITS
1771 val = (val << RAND_BITS) ^ random ();
1772 #if VALBITS > 4*RAND_BITS
1773 val = (val << RAND_BITS) ^ random ();
1774 #endif /* need at least 5 */
1775 #endif /* need at least 4 */
1776 #endif /* need at least 3 */
1777 #endif /* need at least 2 */
1778 return val & ((1L << VALBITS) - 1);
1781 #ifndef HAVE_STRERROR
1782 #ifndef WINDOWSNT
1783 char *
1784 strerror (errnum)
1785 int errnum;
1787 extern char *sys_errlist[];
1788 extern int sys_nerr;
1790 if (errnum >= 0 && errnum < sys_nerr)
1791 return sys_errlist[errnum];
1792 return (char *) "Unknown error";
1794 #endif /* not WINDOWSNT */
1795 #endif /* ! HAVE_STRERROR */
1798 emacs_open (const char *path, int oflag, int mode)
1800 register int rtnval;
1802 while ((rtnval = open (path, oflag, mode)) == -1
1803 && (errno == EINTR))
1804 QUIT;
1805 return (rtnval);
1809 emacs_close (int fd)
1811 int did_retry = 0;
1812 register int rtnval;
1814 while ((rtnval = close (fd)) == -1
1815 && (errno == EINTR))
1816 did_retry = 1;
1818 /* If close is interrupted SunOS 4.1 may or may not have closed the
1819 file descriptor. If it did the second close will fail with
1820 errno = EBADF. That means we have succeeded. */
1821 if (rtnval == -1 && did_retry && errno == EBADF)
1822 return 0;
1824 return rtnval;
1828 emacs_read (int fildes, char *buf, unsigned int nbyte)
1830 register int rtnval;
1832 while ((rtnval = read (fildes, buf, nbyte)) == -1
1833 && (errno == EINTR))
1834 QUIT;
1835 return (rtnval);
1839 emacs_write (int fildes, const char *buf, unsigned int nbyte)
1841 register int rtnval, bytes_written;
1843 bytes_written = 0;
1845 while (nbyte > 0)
1847 rtnval = write (fildes, buf, nbyte);
1849 if (rtnval == -1)
1851 if (errno == EINTR)
1853 #ifdef SYNC_INPUT
1854 /* I originally used `QUIT' but that might causes files to
1855 be truncated if you hit C-g in the middle of it. --Stef */
1856 process_pending_signals ();
1857 #endif
1858 continue;
1860 else
1861 return (bytes_written ? bytes_written : -1);
1864 buf += rtnval;
1865 nbyte -= rtnval;
1866 bytes_written += rtnval;
1868 return (bytes_written);
1871 #ifdef USG
1873 * All of the following are for USG.
1875 * On USG systems the system calls are INTERRUPTIBLE by signals
1876 * that the user program has elected to catch. Thus the system call
1877 * must be retried in these cases. To handle this without massive
1878 * changes in the source code, we remap the standard system call names
1879 * to names for our own functions in sysdep.c that do the system call
1880 * with retries. Actually, for portability reasons, it is good
1881 * programming practice, as this example shows, to limit all actual
1882 * system calls to a single occurrence in the source. Sure, this
1883 * adds an extra level of function call overhead but it is almost
1884 * always negligible. Fred Fish, Unisoft Systems Inc.
1888 * Warning, this function may not duplicate 4.2 action properly
1889 * under error conditions.
1892 #ifndef MAXPATHLEN
1893 /* In 4.1, param.h fails to define this. */
1894 #define MAXPATHLEN 1024
1895 #endif
1897 #ifndef HAVE_GETWD
1899 char *
1900 getwd (char *pathname)
1902 char *npath, *spath;
1903 extern char *getcwd (char *, size_t);
1905 BLOCK_INPUT; /* getcwd uses malloc */
1906 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
1907 if (spath == 0)
1909 UNBLOCK_INPUT;
1910 return spath;
1912 /* On Altos 3068, getcwd can return @hostname/dir, so discard
1913 up to first slash. Should be harmless on other systems. */
1914 while (*npath && *npath != '/')
1915 npath++;
1916 strcpy (pathname, npath);
1917 free (spath); /* getcwd uses malloc */
1918 UNBLOCK_INPUT;
1919 return pathname;
1922 #endif /* HAVE_GETWD */
1925 * Emulate rename using unlink/link. Note that this is
1926 * only partially correct. Also, doesn't enforce restriction
1927 * that files be of same type (regular->regular, dir->dir, etc).
1930 #ifndef HAVE_RENAME
1933 rename (const char *from, const char *to)
1935 if (access (from, 0) == 0)
1937 unlink (to);
1938 if (link (from, to) == 0)
1939 if (unlink (from) == 0)
1940 return (0);
1942 return (-1);
1945 #endif
1948 #if defined(HPUX) && !defined(HAVE_PERROR)
1950 /* HPUX curses library references perror, but as far as we know
1951 it won't be called. Anyway this definition will do for now. */
1953 void
1954 perror (void)
1957 #endif /* HPUX and not HAVE_PERROR */
1959 #ifndef HAVE_DUP2
1962 * Emulate BSD dup2. First close newd if it already exists.
1963 * Then, attempt to dup oldd. If not successful, call dup2 recursively
1964 * until we are, then close the unsuccessful ones.
1968 dup2 (int oldd, int newd)
1970 register int fd, ret;
1972 emacs_close (newd);
1974 #ifdef F_DUPFD
1975 return fcntl (oldd, F_DUPFD, newd);
1976 #else
1977 fd = dup (old);
1978 if (fd == -1)
1979 return -1;
1980 if (fd == new)
1981 return new;
1982 ret = dup2 (old,new);
1983 emacs_close (fd);
1984 return ret;
1985 #endif
1988 #endif /* not HAVE_DUP2 */
1991 * Gettimeofday. Simulate as much as possible. Only accurate
1992 * to nearest second. Emacs doesn't use tzp so ignore it for now.
1993 * Only needed when subprocesses are defined.
1996 #ifndef HAVE_GETTIMEOFDAY
1997 #ifdef HAVE_TIMEVAL
2000 gettimeofday (struct timeval *tp, struct timezone *tzp)
2002 extern long time (long);
2004 tp->tv_sec = time ((long *)0);
2005 tp->tv_usec = 0;
2006 if (tzp != 0)
2007 tzp->tz_minuteswest = -1;
2008 return 0;
2011 #endif
2012 #endif /* !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
2015 * This function will go away as soon as all the stubs fixed. (fnf)
2018 void
2019 croak (char *badfunc)
2021 printf ("%s not yet implemented\r\n", badfunc);
2022 reset_all_sys_modes ();
2023 exit (1);
2026 #endif /* USG */
2028 /* Directory routines for systems that don't have them. */
2030 #ifdef HAVE_DIRENT_H
2032 #include <dirent.h>
2034 #if !defined (HAVE_CLOSEDIR)
2037 closedir (DIR *dirp /* stream from opendir */)
2039 int rtnval;
2041 rtnval = emacs_close (dirp->dd_fd);
2042 xfree ((char *) dirp);
2044 return rtnval;
2046 #endif /* not HAVE_CLOSEDIR */
2047 #endif /* HAVE_DIRENT_H */
2051 set_file_times (const char *filename, EMACS_TIME atime, EMACS_TIME mtime)
2053 #ifdef HAVE_UTIMES
2054 struct timeval tv[2];
2055 tv[0] = atime;
2056 tv[1] = mtime;
2057 return utimes (filename, tv);
2058 #else /* not HAVE_UTIMES */
2059 struct utimbuf utb;
2060 utb.actime = EMACS_SECS (atime);
2061 utb.modtime = EMACS_SECS (mtime);
2062 return utime (filename, &utb);
2063 #endif /* not HAVE_UTIMES */
2066 /* mkdir and rmdir functions, for systems which don't have them. */
2068 #ifndef HAVE_MKDIR
2070 * Written by Robert Rother, Mariah Corporation, August 1985.
2072 * If you want it, it's yours. All I ask in return is that if you
2073 * figure out how to do this in a Bourne Shell script you send me
2074 * a copy.
2075 * sdcsvax!rmr or rmr@uscd
2077 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
2078 * subroutine. 11Mar86; hoptoad!gnu
2080 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
2081 * subroutine didn't return EEXIST. It does now.
2085 * Make a directory.
2088 mkdir (char *dpath, int dmode)
2090 int cpid, status, fd;
2091 struct stat statbuf;
2093 if (stat (dpath, &statbuf) == 0)
2095 errno = EEXIST; /* Stat worked, so it already exists */
2096 return -1;
2099 /* If stat fails for a reason other than non-existence, return error */
2100 if (errno != ENOENT)
2101 return -1;
2103 synch_process_alive = 1;
2104 switch (cpid = fork ())
2107 case -1: /* Error in fork */
2108 return (-1); /* Errno is set already */
2110 case 0: /* Child process */
2112 * Cheap hack to set mode of new directory. Since this
2113 * child process is going away anyway, we zap its umask.
2114 * FIXME, this won't suffice to set SUID, SGID, etc. on this
2115 * directory. Does anybody care?
2117 status = umask (0); /* Get current umask */
2118 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
2119 fd = emacs_open ("/dev/null", O_RDWR, 0);
2120 if (fd >= 0)
2122 dup2 (fd, 0);
2123 dup2 (fd, 1);
2124 dup2 (fd, 2);
2126 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
2127 _exit (-1); /* Can't exec /bin/mkdir */
2129 default: /* Parent process */
2130 wait_for_termination (cpid);
2133 if (synch_process_death != 0 || synch_process_retcode != 0
2134 || synch_process_termsig != 0)
2136 errno = EIO; /* We don't know why, but */
2137 return -1; /* /bin/mkdir failed */
2140 return 0;
2142 #endif /* not HAVE_MKDIR */
2144 #ifndef HAVE_RMDIR
2146 rmdir (char *dpath)
2148 int cpid, status, fd;
2149 struct stat statbuf;
2151 if (stat (dpath, &statbuf) != 0)
2153 /* Stat just set errno. We don't have to */
2154 return -1;
2157 synch_process_alive = 1;
2158 switch (cpid = fork ())
2161 case -1: /* Error in fork */
2162 return (-1); /* Errno is set already */
2164 case 0: /* Child process */
2165 fd = emacs_open ("/dev/null", O_RDWR, 0);
2166 if (fd >= 0)
2168 dup2 (fd, 0);
2169 dup2 (fd, 1);
2170 dup2 (fd, 2);
2172 execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
2173 _exit (-1); /* Can't exec /bin/rmdir */
2175 default: /* Parent process */
2176 wait_for_termination (cpid);
2179 if (synch_process_death != 0 || synch_process_retcode != 0
2180 || synch_process_termsig != 0)
2182 errno = EIO; /* We don't know why, but */
2183 return -1; /* /bin/rmdir failed */
2186 return 0;
2188 #endif /* !HAVE_RMDIR */
2191 #ifndef HAVE_MEMSET
2192 void *
2193 memset (void *b, int n, size_t length)
2195 unsigned char *p = b;
2196 while (length-- > 0)
2197 *p++ = n;
2198 return b;
2200 #endif /* !HAVE_MEMSET */
2202 #ifndef HAVE_MEMCPY
2203 void *
2204 memcpy (void *b1, void *b2, size_t length)
2206 unsigned char *p1 = b1, *p2 = b2;
2207 while (length-- > 0)
2208 *p1++ = *p2++;
2209 return b1;
2211 #endif /* !HAVE_MEMCPY */
2213 #ifndef HAVE_MEMMOVE
2214 void *
2215 memmove (void *b1, void *b2, size_t length)
2217 unsigned char *p1 = b1, *p2 = b2;
2218 if (p1 < p2 || p1 >= p2 + length)
2219 while (length-- > 0)
2220 *p1++ = *p2++;
2221 else
2223 p1 += length;
2224 p2 += length;
2225 while (length-- > 0)
2226 *--p1 = *--p2;
2228 return b1;
2230 #endif /* !HAVE_MEMCPY */
2232 #ifndef HAVE_MEMCMP
2234 memcmp (void *b1, void *b2, size_t length)
2236 unsigned char *p1 = b1, *p2 = b2;
2237 while (length-- > 0)
2238 if (*p1++ != *p2++)
2239 return p1[-1] < p2[-1] ? -1 : 1;
2240 return 0;
2242 #endif /* !HAVE_MEMCMP */
2244 #ifndef HAVE_STRSIGNAL
2245 char *
2246 strsignal (int code)
2248 char *signame = 0;
2250 if (0 <= code && code < NSIG)
2252 /* Cast to suppress warning if the table has const char *. */
2253 signame = (char *) sys_siglist[code];
2256 return signame;
2258 #endif /* HAVE_STRSIGNAL */
2260 #ifndef DOS_NT
2261 /* For make-serial-process */
2263 serial_open (char *port)
2265 int fd = -1;
2267 fd = emacs_open ((char*) port,
2268 O_RDWR
2269 #ifdef O_NONBLOCK
2270 | O_NONBLOCK
2271 #else
2272 | O_NDELAY
2273 #endif
2274 #ifdef O_NOCTTY
2275 | O_NOCTTY
2276 #endif
2277 , 0);
2278 if (fd < 0)
2280 error ("Could not open %s: %s",
2281 port, emacs_strerror (errno));
2283 #ifdef TIOCEXCL
2284 ioctl (fd, TIOCEXCL, (char *) 0);
2285 #endif
2287 return fd;
2290 #if !defined (HAVE_CFMAKERAW)
2291 /* Workaround for targets which are missing cfmakeraw. */
2292 /* Pasted from man page. */
2293 static void
2294 cfmakeraw (struct termios *termios_p)
2296 termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
2297 termios_p->c_oflag &= ~OPOST;
2298 termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
2299 termios_p->c_cflag &= ~(CSIZE|PARENB);
2300 termios_p->c_cflag |= CS8;
2302 #endif /* !defined (HAVE_CFMAKERAW */
2304 #if !defined (HAVE_CFSETSPEED)
2305 /* Workaround for targets which are missing cfsetspeed. */
2306 static int
2307 cfsetspeed (struct termios *termios_p, speed_t vitesse)
2309 return (cfsetispeed (termios_p, vitesse)
2310 + cfsetospeed (termios_p, vitesse));
2312 #endif
2314 /* For serial-process-configure */
2315 void
2316 serial_configure (struct Lisp_Process *p,
2317 Lisp_Object contact)
2319 Lisp_Object childp2 = Qnil;
2320 Lisp_Object tem = Qnil;
2321 struct termios attr;
2322 int err = -1;
2323 char summary[4] = "???"; /* This usually becomes "8N1". */
2325 childp2 = Fcopy_sequence (p->childp);
2327 /* Read port attributes and prepare default configuration. */
2328 err = tcgetattr (p->outfd, &attr);
2329 if (err != 0)
2330 error ("tcgetattr() failed: %s", emacs_strerror (errno));
2331 cfmakeraw (&attr);
2332 #if defined (CLOCAL)
2333 attr.c_cflag |= CLOCAL;
2334 #endif
2335 #if defined (CREAD)
2336 attr.c_cflag |= CREAD;
2337 #endif
2339 /* Configure speed. */
2340 if (!NILP (Fplist_member (contact, QCspeed)))
2341 tem = Fplist_get (contact, QCspeed);
2342 else
2343 tem = Fplist_get (p->childp, QCspeed);
2344 CHECK_NUMBER (tem);
2345 err = cfsetspeed (&attr, XINT (tem));
2346 if (err != 0)
2347 error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
2348 childp2 = Fplist_put (childp2, QCspeed, tem);
2350 /* Configure bytesize. */
2351 if (!NILP (Fplist_member (contact, QCbytesize)))
2352 tem = Fplist_get (contact, QCbytesize);
2353 else
2354 tem = Fplist_get (p->childp, QCbytesize);
2355 if (NILP (tem))
2356 tem = make_number (8);
2357 CHECK_NUMBER (tem);
2358 if (XINT (tem) != 7 && XINT (tem) != 8)
2359 error (":bytesize must be nil (8), 7, or 8");
2360 summary[0] = XINT (tem) + '0';
2361 #if defined (CSIZE) && defined (CS7) && defined (CS8)
2362 attr.c_cflag &= ~CSIZE;
2363 attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
2364 #else
2365 /* Don't error on bytesize 8, which should be set by cfmakeraw. */
2366 if (XINT (tem) != 8)
2367 error ("Bytesize cannot be changed");
2368 #endif
2369 childp2 = Fplist_put (childp2, QCbytesize, tem);
2371 /* Configure parity. */
2372 if (!NILP (Fplist_member (contact, QCparity)))
2373 tem = Fplist_get (contact, QCparity);
2374 else
2375 tem = Fplist_get (p->childp, QCparity);
2376 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
2377 error (":parity must be nil (no parity), `even', or `odd'");
2378 #if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
2379 attr.c_cflag &= ~(PARENB | PARODD);
2380 attr.c_iflag &= ~(IGNPAR | INPCK);
2381 if (NILP (tem))
2383 summary[1] = 'N';
2385 else if (EQ (tem, Qeven))
2387 summary[1] = 'E';
2388 attr.c_cflag |= PARENB;
2389 attr.c_iflag |= (IGNPAR | INPCK);
2391 else if (EQ (tem, Qodd))
2393 summary[1] = 'O';
2394 attr.c_cflag |= (PARENB | PARODD);
2395 attr.c_iflag |= (IGNPAR | INPCK);
2397 #else
2398 /* Don't error on no parity, which should be set by cfmakeraw. */
2399 if (!NILP (tem))
2400 error ("Parity cannot be configured");
2401 #endif
2402 childp2 = Fplist_put (childp2, QCparity, tem);
2404 /* Configure stopbits. */
2405 if (!NILP (Fplist_member (contact, QCstopbits)))
2406 tem = Fplist_get (contact, QCstopbits);
2407 else
2408 tem = Fplist_get (p->childp, QCstopbits);
2409 if (NILP (tem))
2410 tem = make_number (1);
2411 CHECK_NUMBER (tem);
2412 if (XINT (tem) != 1 && XINT (tem) != 2)
2413 error (":stopbits must be nil (1 stopbit), 1, or 2");
2414 summary[2] = XINT (tem) + '0';
2415 #if defined (CSTOPB)
2416 attr.c_cflag &= ~CSTOPB;
2417 if (XINT (tem) == 2)
2418 attr.c_cflag |= CSTOPB;
2419 #else
2420 /* Don't error on 1 stopbit, which should be set by cfmakeraw. */
2421 if (XINT (tem) != 1)
2422 error ("Stopbits cannot be configured");
2423 #endif
2424 childp2 = Fplist_put (childp2, QCstopbits, tem);
2426 /* Configure flowcontrol. */
2427 if (!NILP (Fplist_member (contact, QCflowcontrol)))
2428 tem = Fplist_get (contact, QCflowcontrol);
2429 else
2430 tem = Fplist_get (p->childp, QCflowcontrol);
2431 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
2432 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
2433 #if defined (CRTSCTS)
2434 attr.c_cflag &= ~CRTSCTS;
2435 #endif
2436 #if defined (CNEW_RTSCTS)
2437 attr.c_cflag &= ~CNEW_RTSCTS;
2438 #endif
2439 #if defined (IXON) && defined (IXOFF)
2440 attr.c_iflag &= ~(IXON | IXOFF);
2441 #endif
2442 if (NILP (tem))
2444 /* Already configured. */
2446 else if (EQ (tem, Qhw))
2448 #if defined (CRTSCTS)
2449 attr.c_cflag |= CRTSCTS;
2450 #elif defined (CNEW_RTSCTS)
2451 attr.c_cflag |= CNEW_RTSCTS;
2452 #else
2453 error ("Hardware flowcontrol (RTS/CTS) not supported");
2454 #endif
2456 else if (EQ (tem, Qsw))
2458 #if defined (IXON) && defined (IXOFF)
2459 attr.c_iflag |= (IXON | IXOFF);
2460 #else
2461 error ("Software flowcontrol (XON/XOFF) not supported");
2462 #endif
2464 childp2 = Fplist_put (childp2, QCflowcontrol, tem);
2466 /* Activate configuration. */
2467 err = tcsetattr (p->outfd, TCSANOW, &attr);
2468 if (err != 0)
2469 error ("tcsetattr() failed: %s", emacs_strerror (errno));
2471 childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
2472 p->childp = childp2;
2475 #endif /* not DOS_NT */
2477 /* System depended enumeration of and access to system processes a-la ps(1). */
2479 #ifdef HAVE_PROCFS
2481 /* Process enumeration and access via /proc. */
2483 Lisp_Object
2484 list_system_processes (void)
2486 Lisp_Object procdir, match, proclist, next;
2487 struct gcpro gcpro1, gcpro2;
2488 register Lisp_Object tail;
2490 GCPRO2 (procdir, match);
2491 /* For every process on the system, there's a directory in the
2492 "/proc" pseudo-directory whose name is the numeric ID of that
2493 process. */
2494 procdir = build_string ("/proc");
2495 match = build_string ("[0-9]+");
2496 proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil);
2498 /* `proclist' gives process IDs as strings. Destructively convert
2499 each string into a number. */
2500 for (tail = proclist; CONSP (tail); tail = next)
2502 next = XCDR (tail);
2503 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
2505 UNGCPRO;
2507 /* directory_files_internal returns the files in reverse order; undo
2508 that. */
2509 proclist = Fnreverse (proclist);
2510 return proclist;
2513 /* The WINDOWSNT implementation is in w32.c.
2514 The MSDOS implementation is in dosfns.c. */
2515 #elif !defined (WINDOWSNT) && !defined (MSDOS)
2517 Lisp_Object
2518 list_system_processes (void)
2520 return Qnil;
2523 #endif /* !defined (WINDOWSNT) */
2525 #ifdef GNU_LINUX
2526 static void
2527 time_from_jiffies (unsigned long long tval, long hz,
2528 time_t *sec, unsigned *usec)
2530 unsigned long long ullsec;
2532 *sec = tval / hz;
2533 ullsec = *sec;
2534 tval -= ullsec * hz;
2535 /* Careful: if HZ > 1 million, then integer division by it yields zero. */
2536 if (hz <= 1000000)
2537 *usec = tval * 1000000 / hz;
2538 else
2539 *usec = tval / (hz / 1000000);
2542 static Lisp_Object
2543 ltime_from_jiffies (unsigned long long tval, long hz)
2545 time_t sec;
2546 unsigned usec;
2548 time_from_jiffies (tval, hz, &sec, &usec);
2550 return list3 (make_number ((sec >> 16) & 0xffff),
2551 make_number (sec & 0xffff),
2552 make_number (usec));
2555 static void
2556 get_up_time (time_t *sec, unsigned *usec)
2558 FILE *fup;
2560 *sec = *usec = 0;
2562 BLOCK_INPUT;
2563 fup = fopen ("/proc/uptime", "r");
2565 if (fup)
2567 double uptime, idletime;
2569 /* The numbers in /proc/uptime use C-locale decimal point, but
2570 we already set ourselves to the C locale (see `fixup_locale'
2571 in emacs.c). */
2572 if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime))
2574 *sec = uptime;
2575 *usec = (uptime - *sec) * 1000000;
2577 fclose (fup);
2579 UNBLOCK_INPUT;
2582 #define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
2583 #define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
2585 static Lisp_Object
2586 procfs_ttyname (int rdev)
2588 FILE *fdev = NULL;
2589 char name[PATH_MAX];
2591 BLOCK_INPUT;
2592 fdev = fopen ("/proc/tty/drivers", "r");
2594 if (fdev)
2596 unsigned major;
2597 unsigned long minor_beg, minor_end;
2598 char minor[25]; /* 2 32-bit numbers + dash */
2599 char *endp;
2601 while (!feof (fdev) && !ferror (fdev))
2603 if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
2604 && major == MAJOR (rdev))
2606 minor_beg = strtoul (minor, &endp, 0);
2607 if (*endp == '\0')
2608 minor_end = minor_beg;
2609 else if (*endp == '-')
2610 minor_end = strtoul (endp + 1, &endp, 0);
2611 else
2612 continue;
2614 if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
2616 sprintf (name + strlen (name), "%u", MINOR (rdev));
2617 break;
2621 fclose (fdev);
2623 UNBLOCK_INPUT;
2624 return build_string (name);
2627 static unsigned long
2628 procfs_get_total_memory (void)
2630 FILE *fmem = NULL;
2631 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
2633 BLOCK_INPUT;
2634 fmem = fopen ("/proc/meminfo", "r");
2636 if (fmem)
2638 unsigned long entry_value;
2639 char entry_name[20]; /* the longest I saw is 13+1 */
2641 while (!feof (fmem) && !ferror (fmem))
2643 if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
2644 && strcmp (entry_name, "MemTotal:") == 0)
2646 retval = entry_value;
2647 break;
2650 fclose (fmem);
2652 UNBLOCK_INPUT;
2653 return retval;
2656 Lisp_Object
2657 system_process_attributes (Lisp_Object pid)
2659 char procfn[PATH_MAX], fn[PATH_MAX];
2660 struct stat st;
2661 struct passwd *pw;
2662 struct group *gr;
2663 long clocks_per_sec;
2664 char *procfn_end;
2665 char procbuf[1025], *p, *q;
2666 int fd;
2667 ssize_t nread;
2668 const char *cmd = NULL;
2669 char *cmdline = NULL;
2670 size_t cmdsize = 0, cmdline_size;
2671 unsigned char c;
2672 int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
2673 unsigned long long utime, stime, cutime, cstime, start;
2674 long priority, nice, rss;
2675 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
2676 time_t sec;
2677 unsigned usec;
2678 EMACS_TIME tnow, tstart, tboot, telapsed;
2679 double pcpu, pmem;
2680 Lisp_Object attrs = Qnil;
2681 Lisp_Object cmd_str, decoded_cmd, tem;
2682 struct gcpro gcpro1, gcpro2;
2683 EMACS_INT uid_eint, gid_eint;
2685 CHECK_NUMBER_OR_FLOAT (pid);
2686 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
2687 sprintf (procfn, "/proc/%u", proc_id);
2688 if (stat (procfn, &st) < 0)
2689 return attrs;
2691 GCPRO2 (attrs, decoded_cmd);
2693 /* euid egid */
2694 uid = st.st_uid;
2695 /* Use of EMACS_INT stops GCC whining about limited range of data type. */
2696 uid_eint = uid;
2697 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
2698 BLOCK_INPUT;
2699 pw = getpwuid (uid);
2700 UNBLOCK_INPUT;
2701 if (pw)
2702 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
2704 gid = st.st_gid;
2705 gid_eint = gid;
2706 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
2707 BLOCK_INPUT;
2708 gr = getgrgid (gid);
2709 UNBLOCK_INPUT;
2710 if (gr)
2711 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
2713 strcpy (fn, procfn);
2714 procfn_end = fn + strlen (fn);
2715 strcpy (procfn_end, "/stat");
2716 fd = emacs_open (fn, O_RDONLY, 0);
2717 if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof (procbuf) - 1)) > 0)
2719 procbuf[nread] = '\0';
2720 p = procbuf;
2722 p = strchr (p, '(');
2723 if (p != NULL)
2725 q = strrchr (p + 1, ')');
2726 /* comm */
2727 if (q != NULL)
2729 cmd = p + 1;
2730 cmdsize = q - cmd;
2733 else
2734 q = NULL;
2735 if (cmd == NULL)
2737 cmd = "???";
2738 cmdsize = 3;
2740 /* Command name is encoded in locale-coding-system; decode it. */
2741 cmd_str = make_unibyte_string (cmd, cmdsize);
2742 decoded_cmd = code_convert_string_norecord (cmd_str,
2743 Vlocale_coding_system, 0);
2744 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
2746 if (q)
2748 EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint;
2749 p = q + 2;
2750 /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */
2751 sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld",
2752 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
2753 &minflt, &cminflt, &majflt, &cmajflt,
2754 &utime, &stime, &cutime, &cstime,
2755 &priority, &nice, &thcount, &start, &vsize, &rss);
2757 char state_str[2];
2759 state_str[0] = c;
2760 state_str[1] = '\0';
2761 tem = build_string (state_str);
2762 attrs = Fcons (Fcons (Qstate, tem), attrs);
2764 /* Stops GCC whining about limited range of data type. */
2765 ppid_eint = ppid;
2766 pgrp_eint = pgrp;
2767 sess_eint = sess;
2768 tpgid_eint = tpgid;
2769 thcount_eint = thcount;
2770 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs);
2771 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs);
2772 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs);
2773 attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
2774 attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs);
2775 attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs);
2776 attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs);
2777 attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs);
2778 attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs);
2779 clocks_per_sec = sysconf (_SC_CLK_TCK);
2780 if (clocks_per_sec < 0)
2781 clocks_per_sec = 100;
2782 attrs = Fcons (Fcons (Qutime,
2783 ltime_from_jiffies (utime, clocks_per_sec)),
2784 attrs);
2785 attrs = Fcons (Fcons (Qstime,
2786 ltime_from_jiffies (stime, clocks_per_sec)),
2787 attrs);
2788 attrs = Fcons (Fcons (Qtime,
2789 ltime_from_jiffies (stime+utime, clocks_per_sec)),
2790 attrs);
2791 attrs = Fcons (Fcons (Qcutime,
2792 ltime_from_jiffies (cutime, clocks_per_sec)),
2793 attrs);
2794 attrs = Fcons (Fcons (Qcstime,
2795 ltime_from_jiffies (cstime, clocks_per_sec)),
2796 attrs);
2797 attrs = Fcons (Fcons (Qctime,
2798 ltime_from_jiffies (cstime+cutime, clocks_per_sec)),
2799 attrs);
2800 attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
2801 attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs);
2802 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
2803 EMACS_GET_TIME (tnow);
2804 get_up_time (&sec, &usec);
2805 EMACS_SET_SECS (telapsed, sec);
2806 EMACS_SET_USECS (telapsed, usec);
2807 EMACS_SUB_TIME (tboot, tnow, telapsed);
2808 time_from_jiffies (start, clocks_per_sec, &sec, &usec);
2809 EMACS_SET_SECS (tstart, sec);
2810 EMACS_SET_USECS (tstart, usec);
2811 EMACS_ADD_TIME (tstart, tboot, tstart);
2812 attrs = Fcons (Fcons (Qstart,
2813 list3 (make_number
2814 ((EMACS_SECS (tstart) >> 16) & 0xffff),
2815 make_number
2816 (EMACS_SECS (tstart) & 0xffff),
2817 make_number
2818 (EMACS_USECS (tstart)))),
2819 attrs);
2820 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
2821 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
2822 EMACS_SUB_TIME (telapsed, tnow, tstart);
2823 attrs = Fcons (Fcons (Qetime,
2824 list3 (make_number
2825 ((EMACS_SECS (telapsed) >> 16) & 0xffff),
2826 make_number
2827 (EMACS_SECS (telapsed) & 0xffff),
2828 make_number
2829 (EMACS_USECS (telapsed)))),
2830 attrs);
2831 time_from_jiffies (utime + stime, clocks_per_sec, &sec, &usec);
2832 pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
2833 if (pcpu > 1.0)
2834 pcpu = 1.0;
2835 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
2836 pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
2837 if (pmem > 100)
2838 pmem = 100;
2839 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
2842 if (fd >= 0)
2843 emacs_close (fd);
2845 /* args */
2846 strcpy (procfn_end, "/cmdline");
2847 fd = emacs_open (fn, O_RDONLY, 0);
2848 if (fd >= 0)
2850 for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++)
2852 if (isspace (c) || c == '\\')
2853 cmdline_size++; /* for later quoting, see below */
2855 if (cmdline_size)
2857 cmdline = xmalloc (cmdline_size + 1);
2858 lseek (fd, 0L, SEEK_SET);
2859 cmdline[0] = '\0';
2860 if ((nread = read (fd, cmdline, cmdline_size)) >= 0)
2861 cmdline[nread++] = '\0';
2862 else
2864 /* Assigning zero to `nread' makes us skip the following
2865 two loops, assign zero to cmdline_size, and enter the
2866 following `if' clause that handles unknown command
2867 lines. */
2868 nread = 0;
2870 /* We don't want trailing null characters. */
2871 for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
2872 nread--;
2873 for (p = cmdline; p < cmdline + nread; p++)
2875 /* Escape-quote whitespace and backslashes. */
2876 if (isspace (*p) || *p == '\\')
2878 memmove (p + 1, p, nread - (p - cmdline));
2879 nread++;
2880 *p++ = '\\';
2882 else if (*p == '\0')
2883 *p = ' ';
2885 cmdline_size = nread;
2887 if (!cmdline_size)
2889 if (!cmd)
2890 cmd = "???";
2891 if (!cmdsize)
2892 cmdsize = strlen (cmd);
2893 cmdline_size = cmdsize + 2;
2894 cmdline = xmalloc (cmdline_size + 1);
2895 strcpy (cmdline, "[");
2896 strcat (strncat (cmdline, cmd, cmdsize), "]");
2898 emacs_close (fd);
2899 /* Command line is encoded in locale-coding-system; decode it. */
2900 cmd_str = make_unibyte_string (cmdline, cmdline_size);
2901 decoded_cmd = code_convert_string_norecord (cmd_str,
2902 Vlocale_coding_system, 0);
2903 xfree (cmdline);
2904 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
2907 UNGCPRO;
2908 return attrs;
2911 #elif defined (SOLARIS2) && defined (HAVE_PROCFS)
2913 /* The <procfs.h> header does not like to be included if _LP64 is defined and
2914 __FILE_OFFSET_BITS == 64. This is an ugly workaround that. */
2915 #if !defined (_LP64) && defined (_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
2916 #define PROCFS_FILE_OFFSET_BITS_HACK 1
2917 #undef _FILE_OFFSET_BITS
2918 #else
2919 #define PROCFS_FILE_OFFSET_BITS_HACK 0
2920 #endif
2922 #include <procfs.h>
2924 #if PROCFS_FILE_OFFSET_BITS_HACK == 1
2925 #define _FILE_OFFSET_BITS 64
2926 #endif /* PROCFS_FILE_OFFSET_BITS_HACK == 1 */
2928 Lisp_Object
2929 system_process_attributes (Lisp_Object pid)
2931 char procfn[PATH_MAX], fn[PATH_MAX];
2932 struct stat st;
2933 struct passwd *pw;
2934 struct group *gr;
2935 char *procfn_end;
2936 struct psinfo pinfo;
2937 int fd;
2938 ssize_t nread;
2939 int proc_id, uid, gid;
2940 Lisp_Object attrs = Qnil;
2941 Lisp_Object decoded_cmd, tem;
2942 struct gcpro gcpro1, gcpro2;
2943 EMACS_INT uid_eint, gid_eint;
2945 CHECK_NUMBER_OR_FLOAT (pid);
2946 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
2947 sprintf (procfn, "/proc/%u", proc_id);
2948 if (stat (procfn, &st) < 0)
2949 return attrs;
2951 GCPRO2 (attrs, decoded_cmd);
2953 /* euid egid */
2954 uid = st.st_uid;
2955 /* Use of EMACS_INT stops GCC whining about limited range of data type. */
2956 uid_eint = uid;
2957 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
2958 BLOCK_INPUT;
2959 pw = getpwuid (uid);
2960 UNBLOCK_INPUT;
2961 if (pw)
2962 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
2964 gid = st.st_gid;
2965 gid_eint = gid;
2966 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
2967 BLOCK_INPUT;
2968 gr = getgrgid (gid);
2969 UNBLOCK_INPUT;
2970 if (gr)
2971 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
2973 strcpy (fn, procfn);
2974 procfn_end = fn + strlen (fn);
2975 strcpy (procfn_end, "/psinfo");
2976 fd = emacs_open (fn, O_RDONLY, 0);
2977 if (fd >= 0
2978 && (nread = read (fd, (char*)&pinfo, sizeof (struct psinfo)) > 0))
2980 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (pinfo.pr_ppid)), attrs);
2981 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pinfo.pr_pgid)), attrs);
2982 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (pinfo.pr_sid)), attrs);
2985 char state_str[2];
2986 state_str[0] = pinfo.pr_lwp.pr_sname;
2987 state_str[1] = '\0';
2988 tem = build_string (state_str);
2989 attrs = Fcons (Fcons (Qstate, tem), attrs);
2992 /* FIXME: missing Qttyname. psinfo.pr_ttydev is a dev_t,
2993 need to get a string from it. */
2995 /* FIXME: missing: Qtpgid */
2997 /* FIXME: missing:
2998 Qminflt
2999 Qmajflt
3000 Qcminflt
3001 Qcmajflt
3003 Qutime
3004 Qcutime
3005 Qstime
3006 Qcstime
3007 Are they available? */
3009 attrs = Fcons (Fcons (Qtime,
3010 list3 (make_number (pinfo.pr_time.tv_sec >> 16),
3011 make_number (pinfo.pr_time.tv_sec & 0xffff),
3012 make_number (pinfo.pr_time.tv_nsec))),
3013 attrs);
3015 attrs = Fcons (Fcons (Qctime,
3016 list3 (make_number (pinfo.pr_ctime.tv_sec >> 16),
3017 make_number (pinfo.pr_ctime.tv_sec & 0xffff),
3018 make_number (pinfo.pr_ctime.tv_nsec))),
3019 attrs);
3021 attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs);
3022 attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs);
3023 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs);
3025 attrs = Fcons (Fcons (Qstart,
3026 list3 (make_number (pinfo.pr_start.tv_sec >> 16),
3027 make_number (pinfo.pr_start.tv_sec & 0xffff),
3028 make_number (pinfo.pr_start.tv_nsec))),
3029 attrs);
3030 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs);
3031 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs);
3033 /* pr_pctcpu and pr_pctmem are encoded as a fixed point 16 bit number in [0 ... 1]. */
3034 attrs = Fcons (Fcons (Qpcpu, (pinfo.pr_pctcpu * 100.0) / (double)0x8000), attrs);
3035 attrs = Fcons (Fcons (Qpmem, (pinfo.pr_pctmem * 100.0) / (double)0x8000), attrs);
3037 decoded_cmd
3038 = code_convert_string_norecord (make_unibyte_string (pinfo.pr_fname,
3039 strlen (pinfo.pr_fname)),
3040 Vlocale_coding_system, 0);
3041 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3042 decoded_cmd
3043 = code_convert_string_norecord (make_unibyte_string (pinfo.pr_psargs,
3044 strlen (pinfo.pr_psargs)),
3045 Vlocale_coding_system, 0);
3046 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3049 if (fd >= 0)
3050 emacs_close (fd);
3052 UNGCPRO;
3053 return attrs;
3056 /* The WINDOWSNT implementation is in w32.c.
3057 The MSDOS implementation is in dosfns.c. */
3058 #elif !defined (WINDOWSNT) && !defined (MSDOS)
3060 Lisp_Object
3061 system_process_attributes (Lisp_Object pid)
3063 return Qnil;
3066 #endif /* !defined (WINDOWSNT) */