X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/959116ef2c7755aaffd6d6104b4edaee477e11ba..ce1b23bb4edc6a43f9fae2d2a8f57a21c144d311:/src/sysdep.c diff --git a/src/sysdep.c b/src/sysdep.c index 84e7a6749e..221febd0d7 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1,13 +1,14 @@ /* Interfaces to system-dependent kernel and library entries. Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,48 +16,42 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ #ifdef HAVE_CONFIG_H #include #endif +#include #include #include #include +#ifdef HAVE_PWD_H +#include +#include +#endif /* HAVE_PWD_H */ +#ifdef HAVE_LIMITS_H +#include +#endif /* HAVE_LIMITS_H */ #ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_ALLOCA_H +#include +#endif /* HAVE_ALLOCA_H */ + #include "lisp.h" /* Including stdlib.h isn't necessarily enough to get srandom declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2. */ -#ifdef HAVE_RANDOM -#if 0 /* It turns out that defining _OSF_SOURCE in osf5-0.h gets - random prototyped as returning `int'. It looks to me as - though the best way to DTRT is to prefer the rand48 functions - (per libc.info). -- fx */ -extern long int random P_ ((void)); -#endif -#if 0 /* Don't prototype srandom; it takes an unsigned argument on - some systems, and an unsigned long on others, like FreeBSD - 4.1. */ -extern void srandom P_ ((unsigned int)); -#endif + +/* The w32 build defines select stuff in w32.h, which is included by + sys/select.h (included below). */ +#ifndef WINDOWSNT +#include "sysselect.h" #endif #include "blockinput.h" -#ifdef MAC_OS8 -#include - -#ifndef subprocesses -/* Nonzero means delete a process right away if it exits (process.c). */ -static int delete_exited_processes; -#endif -#endif /* MAC_OS8 */ - #ifdef WINDOWSNT #define read sys_read #define write sys_write @@ -107,32 +102,7 @@ extern int errno; #endif #endif -#ifdef VMS -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __GNUC__ -#include -#else -#include -#endif -#undef F_SETFL -#ifndef RAB$C_BID -#include -#endif -#define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */ -#endif /* VMS */ - -#ifndef VMS #include -#endif /* not VMS */ #ifdef HAVE_FCNTL_H #include @@ -145,26 +115,10 @@ extern int errno; #include "systty.h" #include "syswait.h" -#ifdef BROKEN_TIOCGWINSZ -#undef TIOCGWINSZ -#undef TIOCSWINSZ -#endif - -#if defined (USG) || defined (DGUX) +#if defined (USG) #include -#ifndef MEMORY_IN_STRING_H #include -#endif -#if defined (TIOCGWINSZ) || defined (ISC4_0) -#ifdef NEED_SIOCTL -#include -#endif -#ifdef NEED_PTEM_H -#include -#include -#endif -#endif /* TIOCGWINSZ or ISC4_0 */ -#endif /* USG or DGUX */ +#endif /* USG */ extern int quit_char; @@ -176,20 +130,22 @@ extern int quit_char; #include "termopts.h" #include "dispextern.h" #include "process.h" +#include "cm.h" /* for reset_sys_modes */ + +/* For serial_configure and serial_open. */ +extern Lisp_Object QCport, QCspeed, QCprocess; +extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven; +extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary; #ifdef WINDOWSNT #include /* In process.h which conflicts with the local copy. */ #define _P_WAIT 0 -int _CRTAPI1 _spawnlp (int, const char *, const char *, ...); -int _CRTAPI1 _getpid (void); +int _cdecl _spawnlp (int, const char *, const char *, ...); +int _cdecl _getpid (void); extern char *getwd (char *); #endif -#ifdef NONSYSTEM_DIR_LIBRARY -#include "ndir.h" -#endif /* NONSYSTEM_DIR_LIBRARY */ - #include "syssignal.h" #include "systime.h" #ifdef HAVE_UTIME_H @@ -212,19 +168,11 @@ struct utimbuf { #define LPASS8 0 #endif -#ifdef BSD4_1 -#define LNOFLSH 0100000 -#endif - static int baud_convert[] = -#ifdef BAUD_CONVERT - BAUD_CONVERT; -#else { 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 }; -#endif #ifdef HAVE_SPEED_T #include @@ -239,18 +187,8 @@ static int baud_convert[] = int emacs_ospeed; -/* The file descriptor for Emacs's input terminal. - Under Unix, this is normally zero except when using X; - under VMS, we place the input channel number here. */ -int input_fd; - void croak P_ ((char *)) NO_RETURN; -#ifdef AIXHFT -void hft_init (); -void hft_reset (); -#endif - /* Temporary used by `sigblock' when defined in terms of signprocmask. */ SIGMASKTYPE sigprocmask_set; @@ -331,16 +269,7 @@ get_current_dir_name () #endif -/* Specify a different file descriptor for further input operations. */ - -void -change_input_fd (fd) - int fd; -{ - input_fd = fd; -} - -/* Discard pending input on descriptor input_fd. */ +/* Discard pending input on all input descriptors. */ void discard_tty_input () @@ -351,54 +280,42 @@ discard_tty_input () if (noninteractive) return; - /* Discarding input is not safe when the input could contain - replies from the X server. So don't do it. */ - if (read_socket_hook) - return; - -#ifdef VMS - end_kbd_input (); - SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0, - &buf.main, 0, 0, terminator_mask, 0, 0); - queue_kbd_input (); -#else /* not VMS */ -#ifdef APOLLO - { - int zero = 0; - ioctl (input_fd, TIOCFLUSH, &zero); - } -#else /* not Apollo */ #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ while (dos_keyread () != -1) ; #else /* not MSDOS */ - EMACS_GET_TTY (input_fd, &buf); - EMACS_SET_TTY (input_fd, &buf, 0); + { + struct tty_display_info *tty; + for (tty = tty_list; tty; tty = tty->next) + { + if (tty->input) /* Is the device suspended? */ + { + EMACS_GET_TTY (fileno (tty->input), &buf); + EMACS_SET_TTY (fileno (tty->input), &buf, 0); + } + } + } #endif /* not MSDOS */ -#endif /* not Apollo */ -#endif /* not VMS */ #endif /* not WINDOWSNT */ } + #ifdef SIGTSTP /* Arrange for character C to be read as the next input from - the terminal. */ + the terminal. + XXX What if we have multiple ttys? +*/ void -#ifdef PROTOTYPES stuff_char (char c) -#else -stuff_char (c) - char c; -#endif { - if (read_socket_hook) + if (! FRAME_TERMCAP_P (SELECTED_FRAME ())) return; /* Should perhaps error if in batch mode */ #ifdef TIOCSTI - ioctl (input_fd, TIOCSTI, &c); + ioctl (fileno (CURTTY()->input), TIOCSTI, &c); #else /* no TIOCSTI */ error ("Cannot stuff terminal input characters in this version of Unix"); #endif /* no TIOCSTI */ @@ -407,59 +324,42 @@ stuff_char (c) #endif /* SIGTSTP */ void -init_baud_rate () +init_baud_rate (int fd) { if (noninteractive) emacs_ospeed = 0; else { -#ifdef INIT_BAUD_RATE - INIT_BAUD_RATE (); -#else #ifdef DOS_NT emacs_ospeed = 15; #else /* not DOS_NT */ -#ifdef VMS - struct sensemode sg; - - SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0, - &sg.class, 12, 0, 0, 0, 0 ); - emacs_ospeed = sg.xmit_baud; -#else /* not VMS */ #ifdef HAVE_TERMIOS struct termios sg; sg.c_cflag = B9600; - tcgetattr (input_fd, &sg); + tcgetattr (fd, &sg); emacs_ospeed = cfgetospeed (&sg); -#if defined (USE_GETOBAUD) && defined (getobaud) - /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */ - if (emacs_ospeed == 0) - emacs_ospeed = getobaud (sg.c_cflag); -#endif -#else /* neither VMS nor TERMIOS */ +#else /* not TERMIOS */ #ifdef HAVE_TERMIO struct termio sg; sg.c_cflag = B9600; #ifdef HAVE_TCATTR - tcgetattr (input_fd, &sg); + tcgetattr (fd, &sg); #else - ioctl (input_fd, TCGETA, &sg); + ioctl (fd, TCGETA, &sg); #endif emacs_ospeed = sg.c_cflag & CBAUD; -#else /* neither VMS nor TERMIOS nor TERMIO */ +#else /* neither TERMIOS nor TERMIO */ struct sgttyb sg; sg.sg_ospeed = B9600; - if (ioctl (input_fd, TIOCGETP, &sg) < 0) + if (ioctl (fd, TIOCGETP, &sg) < 0) abort (); emacs_ospeed = sg.sg_ospeed; #endif /* not HAVE_TERMIO */ #endif /* not HAVE_TERMIOS */ -#endif /* not VMS */ #endif /* not DOS_NT */ -#endif /* not INIT_BAUD_RATE */ } baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0] @@ -468,6 +368,7 @@ init_baud_rate () baud_rate = 1200; } + /*ARGSUSED*/ void set_exclusive_use (fd) @@ -510,13 +411,7 @@ wait_for_termination (pid) while (1) { #ifdef subprocesses -#ifdef VMS - int status; - - status = SYS$FORCEX (&pid, 0, 0); - break; -#else /* not VMS */ -#if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5)) +#if defined (BSD_SYSTEM) || defined (HPUX) /* Note that kill returns -1 even if the process is just a zombie now. But inevitably a SIGCHLD interrupt should be generated and child_sig will do wait3 and make the process go away. */ @@ -536,11 +431,6 @@ wait_for_termination (pid) else sigpause (SIGEMPTYMASK); #else /* not BSD_SYSTEM, and not HPUX version >= 6 */ -#if defined (UNIPLUS) - if (0 > kill (pid, 0)) - break; - wait (0); -#else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */ #ifdef POSIX_SIGNALS /* would this work for GNU/Linux as well? */ sigblock (sigmask (SIGCHLD)); errno = 0; @@ -574,23 +464,14 @@ wait_for_termination (pid) #endif /* not WINDOWSNT */ #endif /* not HAVE_SYSV_SIGPAUSE */ #endif /* not POSIX_SIGNALS */ -#endif /* not UNIPLUS */ #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */ -#endif /* not VMS */ #else /* not subprocesses */ #if __DJGPP__ > 1 break; #else /* not __DJGPP__ > 1 */ -#ifndef BSD4_1 if (kill (pid, 0) < 0) break; wait (0); -#else /* BSD4_1 */ - int status; - status = wait (0); - if (status == pid || status == -1) - break; -#endif /* BSD4_1 */ #endif /* not __DJGPP__ > 1*/ #endif /* not subprocesses */ } @@ -625,7 +506,6 @@ flush_pending_output (channel) #endif } -#ifndef VMS /* Set up the terminal at the other end of a pseudo-terminal that we will be controlling an inferior through. It should not echo or do line-editing, since that is done @@ -644,18 +524,18 @@ child_setup_tty (out) s.main.c_oflag |= OPOST; /* Enable output postprocessing */ s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */ #ifdef NLDLY + /* http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00406.html + Some versions of GNU Hurd do not have FFDLY? */ +#ifdef FFDLY s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); /* No output delays */ +#else + s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY); + /* No output delays */ +#endif #endif s.main.c_lflag &= ~ECHO; /* Disable echo */ s.main.c_lflag |= ISIG; /* Enable signals */ -#if 0 /* This causes bugs in (for instance) telnet to certain sites. */ - s.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ -#ifdef INLCR /* Just being cautious, since I can't check how - widespread INLCR is--rms. */ - s.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */ -#endif -#endif #ifdef IUCLC s.main.c_iflag &= ~IUCLC; /* Disable downcasing on input. */ #endif @@ -667,12 +547,6 @@ child_setup_tty (out) #endif s.main.c_oflag &= ~TAB3; /* Disable tab expansion */ s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */ -#if 0 - /* Said to be unnecessary: */ - s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */ - s.main.c_cc[VTIME] = 0; /* wait forever for at least 1 character */ -#endif - s.main.c_lflag |= ICANON; /* Enable erase/kill and eof processing */ s.main.c_cc[VEOF] = 04; /* insure that EOF is Control-D */ s.main.c_cc[VERASE] = CDISABLE; /* disable erase processing */ @@ -727,19 +601,8 @@ child_setup_tty (out) EMACS_SET_TTY (out, &s, 0); -#ifdef BSD4_1 - if (interrupt_input) - reset_sigio (); -#endif /* BSD4_1 */ -#ifdef RTU - { - int zero = 0; - ioctl (out, FIOASYNC, &zero); - } -#endif /* RTU */ #endif /* not DOS_NT */ } -#endif /* not VMS */ #endif /* subprocesses */ @@ -758,47 +621,6 @@ static void restore_signal_handlers P_ ((struct save_signal *)); void sys_suspend () { -#ifdef VMS - /* "Foster" parentage allows emacs to return to a subprocess that attached - to the current emacs as a cheaper than starting a whole new process. This - is set up by KEPTEDITOR.COM. */ - unsigned long parent_id, foster_parent_id; - char *fpid_string; - - fpid_string = getenv ("EMACS_PARENT_PID"); - if (fpid_string != NULL) - { - sscanf (fpid_string, "%x", &foster_parent_id); - if (foster_parent_id != 0) - parent_id = foster_parent_id; - else - parent_id = getppid (); - } - else - parent_id = getppid (); - - xfree (fpid_string); /* On VMS, this was malloc'd */ - - if (parent_id && parent_id != 0xffffffff) - { - SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN); - int status = LIB$ATTACH (&parent_id) & 1; - signal (SIGINT, oldsig); - return status; - } - else - { - struct { - int l; - char *a; - } d_prompt; - d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */ - d_prompt.a = "Emacs: "; /* Just a reminder */ - LIB$SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0); - return 1; - } - return -1; -#else #if defined (SIGTSTP) && !defined (MSDOS) { @@ -820,16 +642,13 @@ sys_suspend () #endif /* no USG_JOBCTRL */ #endif /* no SIGTSTP */ -#endif /* not VMS */ } /* Fork a subshell. */ -#ifndef MAC_OS8 void sys_subshell () { -#ifndef VMS #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */ int st; char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */ @@ -929,10 +748,6 @@ sys_subshell () if (epwd) putenv (old_pwd); /* restore previous value */ } -#if 0 /* This is also reported if last command executed in subshell failed, KFS */ - if (st) - report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil)); -#endif #else /* not MSDOS */ #ifdef WINDOWSNT /* Waits for process completion */ @@ -959,9 +774,7 @@ sys_subshell () #endif restore_signal_handlers (saved_handlers); synch_process_alive = 0; -#endif /* !VMS */ } -#endif /* !MAC_OS8 */ static void save_signal_handlers (saved_handlers) @@ -986,118 +799,90 @@ restore_signal_handlers (saved_handlers) } } -#ifdef F_SETFL - -int old_fcntl_flags; - +#ifndef SIGIO +/* If SIGIO is broken, don't do anything. */ void -init_sigio (fd) - int fd; +init_sigio (int fd) { -#ifdef FASYNC - old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC; - fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC); -#endif - interrupts_deferred = 0; } void -reset_sigio () +reset_sigio (int fd) { - unrequest_sigio (); } -#ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */ - void -request_sigio () +request_sigio (void) { - if (noninteractive || read_socket_hook) - return; - -#ifdef SIGWINCH - sigunblock (sigmask (SIGWINCH)); -#endif - fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC); - - interrupts_deferred = 0; } void -unrequest_sigio () +unrequest_sigio (void) { - if (noninteractive || read_socket_hook) - return; - -#ifdef SIGWINCH - sigblock (sigmask (SIGWINCH)); -#endif - fcntl (input_fd, F_SETFL, old_fcntl_flags); - interrupts_deferred = 1; } -#else /* no FASYNC */ -#ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */ +#else +#ifdef F_SETFL + +int old_fcntl_flags[MAXDESC]; void -request_sigio () +init_sigio (fd) + int fd; { - int on = 1; - - if (noninteractive || read_socket_hook) - return; - - ioctl (input_fd, FIOASYNC, &on); +#ifdef FASYNC + old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC; + fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC); +#endif interrupts_deferred = 0; } void -unrequest_sigio () +reset_sigio (fd) + int fd; { - int off = 0; - - if (noninteractive || read_socket_hook) - return; - - ioctl (input_fd, FIOASYNC, &off); - interrupts_deferred = 1; +#ifdef FASYNC + fcntl (fd, F_SETFL, old_fcntl_flags[fd]); +#endif } -#else /* not FASYNC, not STRIDE */ - -#ifdef _CX_UX - -#include +#ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */ +/* XXX Uhm, FASYNC is not used anymore here. */ +/* XXX Yeah, but you need it for SIGIO, don't you? */ void request_sigio () { - int on = 1; - sigset_t st; - - if (noninteractive || read_socket_hook) + if (noninteractive) return; - sigemptyset (&st); - sigaddset (&st, SIGIO); - ioctl (input_fd, FIOASYNC, &on); +#ifdef SIGWINCH + sigunblock (sigmask (SIGWINCH)); +#endif + sigunblock (sigmask (SIGIO)); + interrupts_deferred = 0; - sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0); } void -unrequest_sigio () -{ - int off = 0; +unrequest_sigio (void) +{ + if (noninteractive) + return; - if (noninteractive || read_socket_hook) +#if 0 /* XXX What's wrong with blocking SIGIO under X? */ + if (x_display_list) return; +#endif - ioctl (input_fd, FIOASYNC, &off); +#ifdef SIGWINCH + sigblock (sigmask (SIGWINCH)); +#endif + sigblock (sigmask (SIGIO)); interrupts_deferred = 1; } -#else /* ! _CX_UX */ +#else /* no FASYNC */ #ifndef MSDOS void @@ -1119,10 +904,9 @@ unrequest_sigio () } #endif /* MSDOS */ -#endif /* _CX_UX */ -#endif /* STRIDE */ #endif /* FASYNC */ #endif /* F_SETFL */ +#endif /* SIGIO */ /* Saving and restoring the process group of Emacs's terminal. */ @@ -1145,30 +929,39 @@ unrequest_sigio () the tty's pgroup just like any other terminal setting. If inherited_group was not the tty's pgroup, then we'll get a SIGTTmumble when we try to change the tty's pgroup, and a CONT if - it goes foreground in the future, which is what should happen. */ + it goes foreground in the future, which is what should happen. + + This variable is initialized in emacs.c. */ int inherited_pgroup; -/* Split off the foreground process group to Emacs alone. - When we are in the foreground, but not started in our own process - group, redirect the TTY to point to our own process group. We need - to be in our own process group to receive SIGIO properly. */ -void -narrow_foreground_group () +/* Split off the foreground process group to Emacs alone. When we are + in the foreground, but not started in our own process group, + redirect the tty device handle FD to point to our own process + group. We need to be in our own process group to receive SIGIO + properly. */ +static void +narrow_foreground_group (int fd) { int me = getpid (); setpgrp (0, inherited_pgroup); +#if 0 + /* XXX inherited_pgroup should not be zero here, but GTK seems to + mess this up. */ + if (! inherited_pgroup) + abort (); /* Should not happen. */ +#endif if (inherited_pgroup != me) - EMACS_SET_TTY_PGRP (input_fd, &me); + EMACS_SET_TTY_PGRP (fd, &me); /* XXX This only works on the controlling tty. */ setpgrp (0, me); } /* Set the tty to our original foreground group. */ -void -widen_foreground_group () +static void +widen_foreground_group (int fd) { if (inherited_pgroup != getpid ()) - EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup); + EMACS_SET_TTY_PGRP (fd, &inherited_pgroup); setpgrp (0, inherited_pgroup); } @@ -1197,14 +990,6 @@ emacs_get_tty (fd, settings) if (ioctl (fd, TCGETA, &settings->main) < 0) return -1; -#else -#ifdef VMS - /* Vehemently Monstrous System? :-) */ - if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0, - &settings->main.class, 12, 0, 0, 0, 0) - & 1)) - return -1; - #else #ifndef DOS_NT /* I give up - I hope you have the BSD ioctls. */ @@ -1212,7 +997,6 @@ emacs_get_tty (fd, settings) return -1; #endif /* not DOS_NT */ #endif -#endif #endif /* Suivant - Do we have to get struct ltchars data? */ @@ -1289,14 +1073,6 @@ emacs_set_tty (fd, settings, flushp) if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0) return -1; -#else -#ifdef VMS - /* Vehemently Monstrous System? :-) */ - if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0, - &settings->main.class, 12, 0, 0, 0, 0) - & 1)) - return -1; - #else #ifndef DOS_NT /* I give up - I hope you have the BSD ioctls. */ @@ -1304,7 +1080,6 @@ emacs_set_tty (fd, settings, flushp) return -1; #endif /* not DOS_NT */ -#endif #endif #endif @@ -1326,40 +1101,20 @@ emacs_set_tty (fd, settings, flushp) } -/* The initial tty mode bits */ -struct emacs_tty old_tty; - -/* 1 if we have been through init_sys_modes. */ -int term_initted; -/* 1 if outer tty status has been recorded. */ -int old_tty_valid; - -#ifdef BSD4_1 -/* BSD 4.1 needs to keep track of the lmode bits in order to start - sigio. */ -int lmode; -#endif - -#ifndef F_SETOWN_BUG #ifdef F_SETOWN -int old_fcntl_owner; +int old_fcntl_owner[MAXDESC]; #endif /* F_SETOWN */ -#endif /* F_SETOWN_BUG */ /* This may also be defined in stdio, but if so, this does no harm, and using the same name avoids wasting the other one's space. */ -#ifdef nec_ews_svr4 -extern char *_sobuf ; -#else -#if defined (USG) || defined (DGUX) +#if defined (USG) unsigned char _sobuf[BUFSIZ+8]; #else char _sobuf[BUFSIZ]; #endif -#endif #ifdef HAVE_LTCHARS static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1}; @@ -1368,377 +1123,327 @@ static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1}; static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1}; #endif +/* Initialize the terminal mode on all tty devices that are currently + open. */ + void -init_sys_modes () +init_all_sys_modes (void) { - struct emacs_tty tty; + struct tty_display_info *tty; + for (tty = tty_list; tty; tty = tty->next) + init_sys_modes (tty); +} -#ifdef VMS -#if 0 - static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */ - extern int (*interrupt_signal) (); -#endif -#endif +/* Initialize the terminal mode on the given tty device. */ + +void +init_sys_modes (tty_out) + struct tty_display_info *tty_out; +{ + struct emacs_tty tty; Vtty_erase_char = Qnil; if (noninteractive) return; -#ifdef VMS - if (!input_ef) - input_ef = get_kbd_event_flag (); - /* LIB$GET_EF (&input_ef); */ - SYS$CLREF (input_ef); - waiting_for_ast = 0; - if (!timer_ef) - timer_ef = get_timer_event_flag (); - /* LIB$GET_EF (&timer_ef); */ - SYS$CLREF (timer_ef); -#if 0 - if (!process_ef) - { - LIB$GET_EF (&process_ef); - SYS$CLREF (process_ef); - } - if (input_ef / 32 != process_ef / 32) - croak ("Input and process event flags in different clusters."); -#endif - if (input_ef / 32 != timer_ef / 32) - croak ("Input and timer event flags in different clusters."); -#if 0 - input_eflist = ((unsigned) 1 << (input_ef % 32)) | - ((unsigned) 1 << (process_ef % 32)); -#endif - timer_eflist = ((unsigned) 1 << (input_ef % 32)) | - ((unsigned) 1 << (timer_ef % 32)); -#ifndef VMS4_4 - sys_access_reinit (); -#endif -#endif /* not VMS */ - + if (!tty_out->output) + return; /* The tty is suspended. */ + #ifdef BSD_PGRPS - if (! read_socket_hook && EQ (Vwindow_system, Qnil)) - narrow_foreground_group (); +#if 0 + /* read_socket_hook is not global anymore. I think doing this + unconditionally will not cause any problems. */ + if (! read_socket_hook && EQ (Vinitial_window_system, Qnil)) #endif - -#ifdef HAVE_WINDOW_SYSTEM - /* Emacs' window system on MSDOG uses the `internal terminal' and therefore - needs the initialization code below. */ - if (!read_socket_hook && EQ (Vwindow_system, Qnil)) + narrow_foreground_group (fileno (tty_out->input)); #endif - { - EMACS_GET_TTY (input_fd, &old_tty); - old_tty_valid = 1; + if (! tty_out->old_tty) + tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty)); + + EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty); - tty = old_tty; + tty = *tty_out->old_tty; #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS) - XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]); + XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]); -#ifdef DGUX - /* This allows meta to be sent on 8th bit. */ - tty.main.c_iflag &= ~INPCK; /* don't check input for parity */ -#endif - tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */ - tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ + tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */ + tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ #ifdef INLCR /* I'm just being cautious, since I can't check how widespread INLCR is--rms. */ - tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */ + tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */ #endif #ifdef ISTRIP - tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */ + tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */ #endif - tty.main.c_lflag &= ~ECHO; /* Disable echo */ - tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */ + tty.main.c_lflag &= ~ECHO; /* Disable echo */ + tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */ #ifdef IEXTEN - tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */ + tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */ #endif - tty.main.c_lflag |= ISIG; /* Enable signals */ - if (flow_control) - { - tty.main.c_iflag |= IXON; /* Enable start/stop output control */ + tty.main.c_lflag |= ISIG; /* Enable signals */ + if (tty_out->flow_control) + { + tty.main.c_iflag |= IXON; /* Enable start/stop output control */ #ifdef IXANY - tty.main.c_iflag &= ~IXANY; + tty.main.c_iflag &= ~IXANY; #endif /* IXANY */ - } - else - tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */ - tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL - on output */ - tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */ + } + else + tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */ + tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL + on output */ + tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */ #ifdef CS8 - if (meta_key) - { - tty.main.c_cflag |= CS8; /* allow 8th bit on input */ - tty.main.c_cflag &= ~PARENB;/* Don't check parity */ - } + if (tty_out->meta_key) + { + tty.main.c_cflag |= CS8; /* allow 8th bit on input */ + tty.main.c_cflag &= ~PARENB;/* Don't check parity */ + } #endif + if (tty_out->input == stdin) + { tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */ /* Set up C-g for both SIGQUIT and SIGINT. - We don't know which we will get, but we handle both alike - so which one it really gives us does not matter. */ + We don't know which we will get, but we handle both alike + so which one it really gives us does not matter. */ tty.main.c_cc[VQUIT] = quit_char; - tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ - tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */ + } + else + { + /* We normally don't get interrupt or quit signals from tty + devices other than our controlling terminal; therefore, + we must handle C-g as normal input. Unfortunately, this + means that the interrupt and quit feature must be + disabled on secondary ttys, or we would not even see the + keypress. + + Note that even though emacsclient could have special code + to pass SIGINT to Emacs, we should _not_ enable + interrupt/quit keys for emacsclient frames. This means + that we can't break out of loops in C code from a + secondary tty frame, but we can always decide what + display the C-g came from, which is more important from a + usability point of view. (Consider the case when two + people work together using the same Emacs instance.) */ + tty.main.c_cc[VINTR] = CDISABLE; + tty.main.c_cc[VQUIT] = CDISABLE; + } + tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ + tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */ #ifdef VSWTCH - tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use + tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use of C-z */ #endif /* VSWTCH */ - -#if defined (mips) || defined (HAVE_TCATTR) + +#if defined (__mips__) || defined (HAVE_TCATTR) #ifdef VSUSP - tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */ + tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */ #endif /* VSUSP */ #ifdef V_DSUSP - tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */ + tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */ #endif /* V_DSUSP */ #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */ - tty.main.c_cc[VDSUSP] = CDISABLE; + tty.main.c_cc[VDSUSP] = CDISABLE; #endif /* VDSUSP */ #ifdef VLNEXT - tty.main.c_cc[VLNEXT] = CDISABLE; + tty.main.c_cc[VLNEXT] = CDISABLE; #endif /* VLNEXT */ #ifdef VREPRINT - tty.main.c_cc[VREPRINT] = CDISABLE; + tty.main.c_cc[VREPRINT] = CDISABLE; #endif /* VREPRINT */ #ifdef VWERASE - tty.main.c_cc[VWERASE] = CDISABLE; + tty.main.c_cc[VWERASE] = CDISABLE; #endif /* VWERASE */ #ifdef VDISCARD - tty.main.c_cc[VDISCARD] = CDISABLE; + tty.main.c_cc[VDISCARD] = CDISABLE; #endif /* VDISCARD */ - if (flow_control) - { + if (tty_out->flow_control) + { #ifdef VSTART - tty.main.c_cc[VSTART] = '\021'; + tty.main.c_cc[VSTART] = '\021'; #endif /* VSTART */ #ifdef VSTOP - tty.main.c_cc[VSTOP] = '\023'; + tty.main.c_cc[VSTOP] = '\023'; #endif /* VSTOP */ - } - else - { + } + else + { #ifdef VSTART - tty.main.c_cc[VSTART] = CDISABLE; + tty.main.c_cc[VSTART] = CDISABLE; #endif /* VSTART */ #ifdef VSTOP - tty.main.c_cc[VSTOP] = CDISABLE; + tty.main.c_cc[VSTOP] = CDISABLE; #endif /* VSTOP */ - } + } #endif /* mips or HAVE_TCATTR */ -#ifdef SET_LINE_DISCIPLINE - /* Need to explicitly request TERMIODISC line discipline or - Ultrix's termios does not work correctly. */ - tty.main.c_line = SET_LINE_DISCIPLINE; -#endif #ifdef AIX #ifndef IBMR2AIX - /* AIX enhanced edit loses NULs, so disable it. */ - tty.main.c_line = 0; - tty.main.c_iflag &= ~ASCEDIT; + /* AIX enhanced edit loses NULs, so disable it. */ + tty.main.c_line = 0; + tty.main.c_iflag &= ~ASCEDIT; #else - tty.main.c_cc[VSTRT] = CDISABLE; - tty.main.c_cc[VSTOP] = CDISABLE; - tty.main.c_cc[VSUSP] = CDISABLE; - tty.main.c_cc[VDSUSP] = CDISABLE; + tty.main.c_cc[VSTRT] = CDISABLE; + tty.main.c_cc[VSTOP] = CDISABLE; + tty.main.c_cc[VSUSP] = CDISABLE; + tty.main.c_cc[VDSUSP] = CDISABLE; #endif /* IBMR2AIX */ - if (flow_control) - { + if (tty_out->flow_control) + { #ifdef VSTART - tty.main.c_cc[VSTART] = '\021'; + tty.main.c_cc[VSTART] = '\021'; #endif /* VSTART */ #ifdef VSTOP - tty.main.c_cc[VSTOP] = '\023'; + tty.main.c_cc[VSTOP] = '\023'; #endif /* VSTOP */ - } - /* Also, PTY overloads NUL and BREAK. - don't ignore break, but don't signal either, so it looks like NUL. - This really serves a purpose only if running in an XTERM window - or via TELNET or the like, but does no harm elsewhere. */ - tty.main.c_iflag &= ~IGNBRK; - tty.main.c_iflag &= ~BRKINT; + } + /* Also, PTY overloads NUL and BREAK. + don't ignore break, but don't signal either, so it looks like NUL. + This really serves a purpose only if running in an XTERM window + or via TELNET or the like, but does no harm elsewhere. */ + tty.main.c_iflag &= ~IGNBRK; + tty.main.c_iflag &= ~BRKINT; #endif #else /* if not HAVE_TERMIO */ -#ifdef VMS - tty.main.tt_char |= TT$M_NOECHO; - if (meta_key) - tty.main.tt_char |= TT$M_EIGHTBIT; - if (flow_control) - tty.main.tt_char |= TT$M_TTSYNC; - else - tty.main.tt_char &= ~TT$M_TTSYNC; - tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON; -#else /* not VMS (BSD, that is) */ #ifndef DOS_NT - XSETINT (Vtty_erase_char, tty.main.sg_erase); - tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS); - if (meta_key) - tty.main.sg_flags |= ANYP; - tty.main.sg_flags |= interrupt_input ? RAW : CBREAK; + XSETINT (Vtty_erase_char, tty.main.sg_erase); + tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS); + if (meta_key) + tty.main.sg_flags |= ANYP; + tty.main.sg_flags |= interrupt_input ? RAW : CBREAK; #endif /* not DOS_NT */ -#endif /* not VMS (BSD, that is) */ #endif /* not HAVE_TERMIO */ - /* If going to use CBREAK mode, we must request C-g to interrupt - and turn off start and stop chars, etc. If not going to use - CBREAK mode, do this anyway so as to turn off local flow - control for user coming over network on 4.2; in this case, - only t_stopc and t_startc really matter. */ + /* If going to use CBREAK mode, we must request C-g to interrupt + and turn off start and stop chars, etc. If not going to use + CBREAK mode, do this anyway so as to turn off local flow + control for user coming over network on 4.2; in this case, + only t_stopc and t_startc really matter. */ #ifndef HAVE_TERMIO #ifdef HAVE_TCHARS - /* Note: if not using CBREAK mode, it makes no difference how we - set this */ - tty.tchars = new_tchars; - tty.tchars.t_intrc = quit_char; - if (flow_control) - { - tty.tchars.t_startc = '\021'; - tty.tchars.t_stopc = '\023'; - } - - tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode; -#ifdef ultrix - /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt - anything, and leaving it in breaks the meta key. Go figure. */ - tty.lmode &= ~LLITOUT; -#endif - -#ifdef BSD4_1 - lmode = tty.lmode; -#endif - + /* Note: if not using CBREAK mode, it makes no difference how we + set this */ + tty.tchars = new_tchars; + tty.tchars.t_intrc = quit_char; + if (tty_out->flow_control) + { + tty.tchars.t_startc = '\021'; + tty.tchars.t_stopc = '\023'; + } + + tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->old_tty.lmode; + #endif /* HAVE_TCHARS */ #endif /* not HAVE_TERMIO */ #ifdef HAVE_LTCHARS - tty.ltchars = new_ltchars; + tty.ltchars = new_ltchars; #endif /* HAVE_LTCHARS */ #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */ - if (!term_initted) - internal_terminal_init (); - dos_ttraw (); + if (!tty_out->term_initted) + internal_terminal_init (); + dos_ttraw (tty_out); #endif - EMACS_SET_TTY (input_fd, &tty, 0); + EMACS_SET_TTY (fileno (tty_out->input), &tty, 0); - /* This code added to insure that, if flow-control is not to be used, - we have an unlocked terminal at the start. */ + /* This code added to insure that, if flow-control is not to be used, + we have an unlocked terminal at the start. */ #ifdef TCXONC - if (!flow_control) ioctl (input_fd, TCXONC, 1); + if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1); #endif -#ifndef APOLLO #ifdef TIOCSTART - if (!flow_control) ioctl (input_fd, TIOCSTART, 0); -#endif + if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0); #endif -#if defined (HAVE_TERMIOS) || defined (HPUX9) +#if defined (HAVE_TERMIOS) || defined (HPUX) #ifdef TCOON - if (!flow_control) tcflow (input_fd, TCOON); -#endif + if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON); #endif - -#ifdef AIXHFT - hft_init (); -#ifdef IBMR2AIX - { - /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it - to be only LF. This is the way that is done. */ - struct termio tty; - - if (ioctl (1, HFTGETID, &tty) != -1) - write (1, "\033[20l", 5); - } #endif -#endif /* AIXHFT */ - -#ifdef VMS -/* Appears to do nothing when in PASTHRU mode. - SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0, - interrupt_signal, oob_chars, 0, 0, 0, 0); -*/ - queue_kbd_input (0); -#endif /* VMS */ - } #ifdef F_SETFL -#ifndef F_SETOWN_BUG #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */ - if (interrupt_input - && ! read_socket_hook && EQ (Vwindow_system, Qnil)) + if (interrupt_input) { - old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0); - fcntl (input_fd, F_SETOWN, getpid ()); - init_sigio (input_fd); + old_fcntl_owner[fileno (tty_out->input)] = + fcntl (fileno (tty_out->input), F_GETOWN, 0); + fcntl (fileno (tty_out->input), F_SETOWN, getpid ()); + init_sigio (fileno (tty_out->input)); +#ifdef HAVE_GPM + if (gpm_tty == tty_out) + { + /* Arrange for mouse events to give us SIGIO signals. */ + fcntl (gpm_fd, F_SETOWN, getpid ()); + fcntl (gpm_fd, F_SETFL, fcntl (gpm_fd, F_GETFL, 0) | O_NONBLOCK); + init_sigio (gpm_fd); + } +#endif /* HAVE_GPM */ } #endif /* F_GETOWN */ -#endif /* F_SETOWN_BUG */ #endif /* F_SETFL */ -#ifdef BSD4_1 - if (interrupt_input) - init_sigio (input_fd); -#endif - -#ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */ -#undef _IOFBF -#endif #ifdef _IOFBF /* This symbol is defined on recent USG systems. Someone says without this call USG won't really buffer the file even with a call to setbuf. */ - setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf); + setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf); #else - setbuf (stdout, (char *) _sobuf); -#endif -#ifdef HAVE_WINDOW_SYSTEM - /* Emacs' window system on MSDOG uses the `internal terminal' and therefore - needs the initialization code below. */ - if (EQ (Vwindow_system, Qnil) -#ifndef WINDOWSNT - /* When running in tty mode on NT/Win95, we have a read_socket - hook, but still need the rest of the initialization code below. */ - && (! read_socket_hook) -#endif - ) + setbuf (tty_out->output, (char *) _sobuf); #endif - set_terminal_modes (); - if (!term_initted - && FRAMEP (Vterminal_frame) - && FRAME_TERMCAP_P (XFRAME (Vterminal_frame))) - init_frame_faces (XFRAME (Vterminal_frame)); + if (tty_out->terminal->set_terminal_modes_hook) + tty_out->terminal->set_terminal_modes_hook (tty_out->terminal); - if (term_initted && no_redraw_on_reenter) + if (!tty_out->term_initted) { + Lisp_Object tail, frame; + FOR_EACH_FRAME (tail, frame) + { + /* XXX This needs to be revised. */ + if (FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (frame)) == tty_out) + init_frame_faces (XFRAME (frame)); + } + } + + if (tty_out->term_initted && no_redraw_on_reenter) + { + /* XXX This seems wrong on multi-tty. */ if (display_completed) direct_output_forward_char (0); } else { + Lisp_Object tail, frame; frame_garbaged = 1; - if (FRAMEP (Vterminal_frame)) - FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1; + FOR_EACH_FRAME (tail, frame) + { + if ((FRAME_TERMCAP_P (XFRAME (frame)) + || FRAME_MSDOS_P (XFRAME (frame))) + && FRAME_TTY (XFRAME (frame)) == tty_out) + FRAME_GARBAGED_P (XFRAME (frame)) = 1; + } } - term_initted = 1; + tty_out->term_initted = 1; } /* Return nonzero if safe to use tabs in output. At the time this is called, init_sys_modes has not been done yet. */ int -tabs_safe_p () +tabs_safe_p (int fd) { - struct emacs_tty tty; + struct emacs_tty etty; - EMACS_GET_TTY (input_fd, &tty); - return EMACS_TTY_TABS_OK (&tty); + EMACS_GET_TTY (fd, &etty); + return EMACS_TTY_TABS_OK (&etty); } /* Get terminal size from system. @@ -1746,8 +1451,7 @@ tabs_safe_p () We store 0 if there's no valid information. */ void -get_frame_size (widthp, heightp) - int *widthp, *heightp; +get_tty_size (int fd, int *widthp, int *heightp) { #ifdef TIOCGWINSZ @@ -1755,7 +1459,7 @@ get_frame_size (widthp, heightp) /* BSD-style. */ struct winsize size; - if (ioctl (input_fd, TIOCGWINSZ, &size) == -1) + if (ioctl (fd, TIOCGWINSZ, &size) == -1) *widthp = *heightp = 0; else { @@ -1769,7 +1473,7 @@ get_frame_size (widthp, heightp) /* SunOS - style. */ struct ttysize size; - if (ioctl (input_fd, TIOCGSIZE, &size) == -1) + if (ioctl (fd, TIOCGSIZE, &size) == -1) *widthp = *heightp = 0; else { @@ -1777,22 +1481,6 @@ get_frame_size (widthp, heightp) *heightp = size.ts_lines; } -#else -#ifdef VMS - - /* Use a fresh channel since the current one may have stale info - (for example, from prior to a suspend); and to avoid a dependency - in the init sequence. */ - int chan; - struct sensemode tty; - - SYS$ASSIGN (&input_dsc, &chan, 0, 0); - SYS$QIOW (0, chan, IO$_SENSEMODE, &tty, 0, 0, - &tty.class, 12, 0, 0, 0, 0); - SYS$DASSGN (chan); - *widthp = tty.scr_wid; - *heightp = tty.scr_len; - #else #ifdef MSDOS *widthp = ScreenCols (); @@ -1801,8 +1489,6 @@ get_frame_size (widthp, heightp) *widthp = 0; *heightp = 0; #endif - -#endif /* not VMS */ #endif /* not SunOS-style */ #endif /* not BSD-style */ } @@ -1845,97 +1531,92 @@ set_window_size (fd, height, width) } -/* Prepare the terminal for exiting Emacs; move the cursor to the - bottom of the frame, turn off interrupt-driven I/O, etc. */ + +/* Prepare all terminal devices for exiting Emacs. */ + void -reset_sys_modes () +reset_all_sys_modes (void) { - struct frame *sf; + struct tty_display_info *tty; + for (tty = tty_list; tty; tty = tty->next) + reset_sys_modes (tty); +} + +/* Prepare the terminal for closing it; move the cursor to the + bottom of the frame, turn off interrupt-driven I/O, etc. */ +void +reset_sys_modes (tty_out) + struct tty_display_info *tty_out; +{ if (noninteractive) { fflush (stdout); return; } - if (!term_initted) - return; -#ifdef HAVE_WINDOW_SYSTEM - /* Emacs' window system on MSDOG uses the `internal terminal' and therefore - needs the clean-up code below. */ - if (!EQ (Vwindow_system, Qnil) -#ifndef WINDOWSNT - /* When running in tty mode on NT/Win95, we have a read_socket - hook, but still need the rest of the clean-up code below. */ - || read_socket_hook -#endif - ) + if (!tty_out->term_initted) return; -#endif - sf = SELECTED_FRAME (); - cursor_to (FRAME_LINES (sf) - 1, 0); - clear_end_of_line (FRAME_COLS (sf)); - /* clear_end_of_line may move the cursor */ - cursor_to (FRAME_LINES (sf) - 1, 0); -#if defined (IBMR2AIX) && defined (AIXHFT) - { - /* HFT devices normally use ^J as a LF/CR. We forced it to - do the LF only. Now, we need to reset it. */ - struct termio tty; - if (ioctl (1, HFTGETID, &tty) != -1) - write (1, "\033[20h", 5); - } -#endif + if (!tty_out->output) + return; /* The tty is suspended. */ + + /* Go to and clear the last line of the terminal. */ + + cmgoto (tty_out, FrameRows (tty_out) - 1, 0); + + /* Code adapted from tty_clear_end_of_line. */ + if (tty_out->TS_clr_line) + { + emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc); + } + else + { /* have to do it the hard way */ + int i; + tty_turn_off_insert (tty_out); + + for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++) + { + fputc (' ', tty_out->output); + } + } + + cmgoto (tty_out, FrameRows (tty_out) - 1, 0); + fflush (tty_out->output); + + if (tty_out->terminal->reset_terminal_modes_hook) + tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal); - reset_terminal_modes (); - fflush (stdout); #ifdef BSD_SYSTEM -#ifndef BSD4_1 /* Avoid possible loss of output when changing terminal modes. */ - fsync (fileno (stdout)); -#endif + fsync (fileno (tty_out->output)); #endif #ifdef F_SETFL -#ifndef F_SETOWN_BUG #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */ if (interrupt_input) { - reset_sigio (); - fcntl (input_fd, F_SETOWN, old_fcntl_owner); + reset_sigio (fileno (tty_out->input)); + fcntl (fileno (tty_out->input), F_SETOWN, + old_fcntl_owner[fileno (tty_out->input)]); } #endif /* F_SETOWN */ -#endif /* F_SETOWN_BUG */ #ifdef O_NDELAY - fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY); + fcntl (fileno (tty_out->input), F_SETFL, + fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY); #endif #endif /* F_SETFL */ -#ifdef BSD4_1 - if (interrupt_input) - reset_sigio (); -#endif /* BSD4_1 */ - if (old_tty_valid) - while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR) + if (tty_out->old_tty) + while (EMACS_SET_TTY (fileno (tty_out->input), + tty_out->old_tty, 0) < 0 && errno == EINTR) ; #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */ dos_ttcooked (); #endif -#ifdef SET_LINE_DISCIPLINE - /* Ultrix's termios *ignores* any line discipline except TERMIODISC. - A different old line discipline is therefore not restored, yet. - Restore the old line discipline by hand. */ - ioctl (0, TIOCSETD, &old_tty.main.c_line); -#endif - -#ifdef AIXHFT - hft_reset (); -#endif - #ifdef BSD_PGRPS - widen_foreground_group (); + widen_foreground_group (fileno (tty_out->input)); #endif } @@ -1971,287 +1652,17 @@ setup_pty (fd) Since the latter lossage is more benign, we may as well lose that way. -- cph */ #ifdef FIONBIO -#if defined(SYSV_PTYS) || defined(UNIX98_PTYS) +#if defined(UNIX98_PTYS) { int on = 1; ioctl (fd, FIONBIO, &on); } #endif #endif -#ifdef IBMRTAIX - /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */ - /* ignore SIGHUP once we've started a child on a pty. Note that this may */ - /* cause EMACS not to die when it should, i.e., when its own controlling */ - /* tty goes away. I've complained to the AIX developers, and they may */ - /* change this behavior, but I'm not going to hold my breath. */ - signal (SIGHUP, SIG_IGN); -#endif } #endif /* HAVE_PTYS */ -#ifdef VMS - -/* Assigning an input channel is done at the start of Emacs execution. - This is called each time Emacs is resumed, also, but does nothing - because input_chain is no longer zero. */ - -void -init_vms_input () -{ - int status; - - if (input_fd == 0) - { - status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0); - if (! (status & 1)) - LIB$STOP (status); - } -} - -/* Deassigning the input channel is done before exiting. */ - -void -stop_vms_input () -{ - return SYS$DASSGN (input_fd); -} - -short input_buffer; - -/* Request reading one character into the keyboard buffer. - This is done as soon as the buffer becomes empty. */ - -void -queue_kbd_input () -{ - int status; - extern kbd_input_ast (); - - waiting_for_ast = 0; - stop_input = 0; - status = SYS$QIO (0, input_fd, IO$_READVBLK, - &input_iosb, kbd_input_ast, 1, - &input_buffer, 1, 0, terminator_mask, 0, 0); -} - -int input_count; - -/* Ast routine that is called when keyboard input comes in - in accord with the SYS$QIO above. */ - -void -kbd_input_ast () -{ - register int c = -1; - int old_errno = errno; - extern EMACS_TIME *input_available_clear_time; - - if (waiting_for_ast) - SYS$SETEF (input_ef); - waiting_for_ast = 0; - input_count++; -#ifdef ASTDEBUG - if (input_count == 25) - exit (1); - printf ("Ast # %d,", input_count); - printf (" iosb = %x, %x, %x, %x", - input_iosb.offset, input_iosb.status, input_iosb.termlen, - input_iosb.term); -#endif - if (input_iosb.offset) - { - c = input_buffer; -#ifdef ASTDEBUG - printf (", char = 0%o", c); -#endif - } -#ifdef ASTDEBUG - printf ("\n"); - fflush (stdout); - sleep (1); -#endif - if (! stop_input) - queue_kbd_input (); - if (c >= 0) - { - struct input_event e; - EVENT_INIT (e); - - e.kind = ASCII_KEYSTROKE_EVENT; - XSETINT (e.code, c); - e.frame_or_window = selected_frame; - kbd_buffer_store_event (&e); - } - if (input_available_clear_time) - EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0); - errno = old_errno; -} - -/* Wait until there is something in kbd_buffer. */ - -void -wait_for_kbd_input () -{ - extern int have_process_input, process_exited; - - /* If already something, avoid doing system calls. */ - if (detect_input_pending ()) - { - return; - } - /* Clear a flag, and tell ast routine above to set it. */ - SYS$CLREF (input_ef); - waiting_for_ast = 1; - /* Check for timing error: ast happened while we were doing that. */ - if (!detect_input_pending ()) - { - /* No timing error: wait for flag to be set. */ - set_waiting_for_input (0); - SYS$WFLOR (input_ef, input_eflist); - clear_waiting_for_input (); - if (!detect_input_pending ()) - /* Check for subprocess input availability */ - { - int dsp = have_process_input || process_exited; - - SYS$CLREF (process_ef); - if (have_process_input) - process_command_input (); - if (process_exited) - process_exit (); - if (dsp) - { - update_mode_lines++; - prepare_menu_bars (); - redisplay_preserve_echo_area (18); - } - } - } - waiting_for_ast = 0; -} - -/* Get rid of any pending QIO, when we are about to suspend - or when we want to throw away pending input. - We wait for a positive sign that the AST routine has run - and therefore there is no I/O request queued when we return. - SYS$SETAST is used to avoid a timing error. */ - -void -end_kbd_input () -{ -#ifdef ASTDEBUG - printf ("At end_kbd_input.\n"); - fflush (stdout); - sleep (1); -#endif - if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */ - { - SYS$CANCEL (input_fd); - return; - } - - SYS$SETAST (0); - /* Clear a flag, and tell ast routine above to set it. */ - SYS$CLREF (input_ef); - waiting_for_ast = 1; - stop_input = 1; - SYS$CANCEL (input_fd); - SYS$SETAST (1); - SYS$WAITFR (input_ef); - waiting_for_ast = 0; -} - -/* Wait for either input available or time interval expiry. */ - -void -input_wait_timeout (timeval) - int timeval; /* Time to wait, in seconds */ -{ - int time [2]; - static int zero = 0; - static int large = -10000000; - - LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */ - - /* If already something, avoid doing system calls. */ - if (detect_input_pending ()) - { - return; - } - /* Clear a flag, and tell ast routine above to set it. */ - SYS$CLREF (input_ef); - waiting_for_ast = 1; - /* Check for timing error: ast happened while we were doing that. */ - if (!detect_input_pending ()) - { - /* No timing error: wait for flag to be set. */ - SYS$CANTIM (1, 0); - if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */ - SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */ - } - waiting_for_ast = 0; -} - -/* The standard `sleep' routine works some other way - and it stops working if you have ever quit out of it. - This one continues to work. */ - -sys_sleep (timeval) - int timeval; -{ - int time [2]; - static int zero = 0; - static int large = -10000000; - - LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */ - - SYS$CANTIM (1, 0); - if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */ - SYS$WAITFR (timer_ef); /* Wait for timer expiry only */ -} - -void -init_sigio (fd) - int fd; -{ - request_sigio (); -} - -reset_sigio () -{ - unrequest_sigio (); -} - -void -request_sigio () -{ - if (noninteractive) - return; - croak ("request sigio"); -} - -void -unrequest_sigio () -{ - if (noninteractive) - return; - croak ("unrequest sigio"); -} - -#endif /* VMS */ - -/* Note that VMS compiler won't accept defined (CANNOT_DUMP). */ -#ifndef CANNOT_DUMP -#define NEED_STARTS -#endif - -#ifndef SYSTEM_MALLOC -#ifndef NEED_STARTS -#define NEED_STARTS -#endif -#endif - -#ifdef NEED_STARTS +#if !defined(CANNOT_DUMP) || !defined(SYSTEM_MALLOC) /* Some systems that cannot dump also cannot implement these. */ /* @@ -2269,13 +1680,8 @@ start_of_text () #ifdef TEXT_START return ((char *) TEXT_START); #else -#ifdef GOULD - extern csrt (); - return ((char *) csrt); -#else /* not GOULD */ extern int _start (); return ((char *) _start); -#endif /* GOULD */ #endif /* TEXT_START */ } #endif /* not HAVE_TEXT_START */ @@ -2336,20 +1742,12 @@ start_of_data () /* init_system_name sets up the string for the Lisp function system-name to return. */ -#ifdef BSD4_1 -#include -#endif - extern Lisp_Object Vsystem_name; -#ifndef BSD4_1 -#ifndef VMS #ifdef HAVE_SOCKETS #include #include #endif /* HAVE_SOCKETS */ -#endif /* not VMS */ -#endif /* not BSD4_1 */ #ifdef TRY_AGAIN #ifndef HAVE_H_ERRNO @@ -2360,18 +1758,6 @@ extern int h_errno; void init_system_name () { -#ifdef BSD4_1 - Vsystem_name = build_string (sysname); -#else -#ifdef VMS - char *sp, *end; - if ((sp = egetenv ("SYS$NODE")) == 0) - Vsystem_name = build_string ("vax-vms"); - else if ((end = index (sp, ':')) == 0) - Vsystem_name = build_string (sp); - else - Vsystem_name = make_string (sp, end - sp); -#else #ifndef HAVE_GETHOSTNAME struct utsname uts; uname (&uts); @@ -2405,10 +1791,50 @@ init_system_name () #endif /* not CANNOT_DUMP */ if (! index (hostname, '.')) { - struct hostent *hp; int count; +#ifdef HAVE_GETADDRINFO + struct addrinfo *res; + struct addrinfo hints; + int ret; + + memset (&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + + for (count = 0;; count++) + { + if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0 + || ret != EAI_AGAIN) + break; + + if (count >= 5) + break; + Fsleep_for (make_number (1), Qnil); + } + + if (ret == 0) + { + struct addrinfo *it = res; + while (it) + { + char *fqdn = it->ai_canonname; + if (fqdn && index (fqdn, '.') + && strcmp (fqdn, "localhost.localdomain") != 0) + break; + it = it->ai_next; + } + if (it) + { + hostname = alloca (strlen (it->ai_canonname) + 1); + strcpy (hostname, it->ai_canonname); + } + freeaddrinfo (res); + } +#else /* !HAVE_GETADDRINFO */ + struct hostent *hp; for (count = 0;; count++) { + #ifdef TRY_AGAIN h_errno = 0; #endif @@ -2416,17 +1842,17 @@ init_system_name () #ifdef TRY_AGAIN if (! (hp == 0 && h_errno == TRY_AGAIN)) #endif + break; + if (count >= 5) break; Fsleep_for (make_number (1), Qnil); } + if (hp) { char *fqdn = (char *) hp->h_name; -#if 0 - char *p; -#endif if (!index (fqdn, '.')) { @@ -2441,65 +1867,12 @@ init_system_name () fqdn = *alias; } hostname = fqdn; -#if 0 - /* Convert the host name to lower case. */ - /* Using ctype.h here would introduce a possible locale - dependence that is probably wrong for hostnames. */ - p = hostname; - while (*p) - { - if (*p >= 'A' && *p <= 'Z') - *p += 'a' - 'A'; - p++; - } -#endif } +#endif /* !HAVE_GETADDRINFO */ } #endif /* HAVE_SOCKETS */ - /* We used to try using getdomainname here, - but NIIBE Yutaka says that - getdomainname gets the NIS/YP domain which often is not the same - as in Internet domain name. */ -#if 0 /* Turned off because sysinfo is not really likely to return the - correct Internet domain. */ -#if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN)) - if (! index (hostname, '.')) - { - /* The hostname is not fully qualified. Append the domain name. */ - - int hostlen = strlen (hostname); - int domain_size = 256; - - for (;;) - { - char *domain = (char *) alloca (domain_size + 1); - char *fqdn = (char *) alloca (hostlen + 1 + domain_size + 1); - int sys_domain_size = sysinfo (SI_SRPC_DOMAIN, domain, domain_size); - if (sys_domain_size <= 0) - break; - if (domain_size < sys_domain_size) - { - domain_size = sys_domain_size; - continue; - } - strcpy (fqdn, hostname); - if (domain[0] == '.') - strcpy (fqdn + hostlen, domain); - else if (domain[0] != 0) - { - fqdn[hostlen] = '.'; - strcpy (fqdn + hostlen + 1, domain); - } - hostname = fqdn; - break; - } - } -#endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */ -#endif /* 0 */ Vsystem_name = build_string (hostname); #endif /* HAVE_GETHOSTNAME */ -#endif /* VMS */ -#endif /* BSD4_1 */ { unsigned char *p; for (p = SDATA (Vsystem_name); *p; p++) @@ -2509,8 +1882,7 @@ init_system_name () } #ifndef MSDOS -#ifndef VMS -#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X) +#if !defined (HAVE_SELECT) #include "sysselect.h" #undef select @@ -2541,11 +1913,7 @@ SIGTYPE select_alarm () { select_alarmed = 1; -#ifdef BSD4_1 - sigrelse (SIGALRM); -#else /* not BSD4_1 */ signal (SIGALRM, SIG_IGN); -#endif /* not BSD4_1 */ SIGNAL_THREAD_CHECK (SIGALRM); if (read_alarm_should_throw) longjmp (read_alarm_throw, 1); @@ -2559,7 +1927,9 @@ sys_select (nfds, rfds, wfds, efds, timeout) SELECT_TYPE *rfds, *wfds, *efds; EMACS_TIME *timeout; { - int ravail = 0; + /* XXX This needs to be updated for multi-tty support. Is there + anybody who needs to emulate select these days? */ + int ravail = 0; SELECT_TYPE orfds; int timeoutval; int *local_timeout; @@ -2574,7 +1944,7 @@ sys_select (nfds, rfds, wfds, efds, timeout) #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS) /* If we're using X, then the native select will work; we only need the emulation for non-X usage. */ - if (!NILP (Vwindow_system)) + if (!NILP (Vinitial_window_system)) return select (nfds, rfds, wfds, efds, timeout); #endif timeoutval = timeout ? EMACS_SECS (*timeout) : 100000; @@ -2691,6 +2061,8 @@ sys_select (nfds, rfds, wfds, efds, timeout) void read_input_waiting () { + /* XXX This needs to be updated for multi-tty support. Is there + anybody who needs to emulate select these days? */ int nread, i; extern int quit_char; @@ -2744,139 +2116,60 @@ read_input_waiting () } } +#if !defined (HAVE_SELECT) +#define select sys_select +#endif + #endif /* not HAVE_SELECT */ -#endif /* not VMS */ #endif /* not MSDOS */ -#ifdef BSD4_1 -void -init_sigio (fd) - int fd; -{ - if (noninteractive) - return; - lmode = LINTRUP | lmode; - ioctl (fd, TIOCLSET, &lmode); -} +/* POSIX signals support - DJB */ +/* Anyone with POSIX signals should have ANSI C declarations */ -void -reset_sigio () +#ifdef POSIX_SIGNALS + +sigset_t empty_mask, full_mask; + +signal_handler_t +sys_signal (int signal_number, signal_handler_t action) { + struct sigaction new_action, old_action; + sigemptyset (&new_action.sa_mask); + new_action.sa_handler = action; + new_action.sa_flags = 0; +#if defined (SA_RESTART) + /* Emacs mostly works better with restartable system services. If this + flag exists, we probably want to turn it on here. + However, on some systems this resets the timeout of `select' + which means that `select' never finishes if it keeps getting signals. + BROKEN_SA_RESTART is defined on those systems. */ + /* It's not clear why the comment above says "mostly works better". --Stef + When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll + for pending input so we need long-running syscalls to be interrupted + after a signal that sets the interrupt_input_pending flag. */ + /* Non-interactive keyboard input goes through stdio, where we always + want restartable system calls. */ +# if defined (BROKEN_SA_RESTART) || defined(SYNC_INPUT) if (noninteractive) - return; - lmode = ~LINTRUP & lmode; - ioctl (0, TIOCLSET, &lmode); +# endif + new_action.sa_flags = SA_RESTART; +#endif + sigaction (signal_number, &new_action, &old_action); + return (old_action.sa_handler); } -void -request_sigio () +#ifndef __GNUC__ +/* If we're compiling with GCC, we don't need this function, since it + can be written as a macro. */ +sigset_t +sys_sigmask (int sig) { - if (noninteractive) - return; - sigrelse (SIGTINT); - - interrupts_deferred = 0; + sigset_t mask; + sigemptyset (&mask); + sigaddset (&mask, sig); + return mask; } - -void -unrequest_sigio () -{ - if (noninteractive) - return; - sighold (SIGTINT); - - interrupts_deferred = 1; -} - -/* still inside #ifdef BSD4_1 */ -#ifdef subprocesses - -int sigheld; /* Mask of held signals */ - -void -sigholdx (signum) - int signum; -{ - sigheld |= sigbit (signum); - sighold (signum); -} - -void -sigisheld (signum) - int signum; -{ - sigheld |= sigbit (signum); -} - -void -sigunhold (signum) - int signum; -{ - sigheld &= ~sigbit (signum); - sigrelse (signum); -} - -void -sigfree () /* Free all held signals */ -{ - int i; - for (i = 0; i < NSIG; i++) - if (sigheld & sigbit (i)) - sigrelse (i); - sigheld = 0; -} - -int -sigbit (i) -{ - return 1 << (i - 1); -} -#endif /* subprocesses */ -#endif /* BSD4_1 */ - -/* POSIX signals support - DJB */ -/* Anyone with POSIX signals should have ANSI C declarations */ - -#ifdef POSIX_SIGNALS - -sigset_t empty_mask, full_mask; - -signal_handler_t -sys_signal (int signal_number, signal_handler_t action) -{ - struct sigaction new_action, old_action; - sigemptyset (&new_action.sa_mask); - new_action.sa_handler = action; -#if defined (SA_RESTART) && ! defined (BROKEN_SA_RESTART) && !defined(SYNC_INPUT) - /* Emacs mostly works better with restartable system services. If this - flag exists, we probably want to turn it on here. - However, on some systems this resets the timeout of `select' - which means that `select' never finishes if it keeps getting signals. - BROKEN_SA_RESTART is defined on those systems. */ - /* It's not clear why the comment above says "mostly works better". --Stef - When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll - for pending input so we need long-running syscalls to be interrupted - after a signal that sets the interrupt_input_pending flag. */ - new_action.sa_flags = SA_RESTART; -#else - new_action.sa_flags = 0; -#endif - sigaction (signal_number, &new_action, &old_action); - return (old_action.sa_handler); -} - -#ifndef __GNUC__ -/* If we're compiling with GCC, we don't need this function, since it - can be written as a macro. */ -sigset_t -sys_sigmask (int sig) -{ - sigset_t mask; - sigemptyset (&mask); - sigaddset (&mask, sig); - return mask; -} -#endif +#endif /* I'd like to have these guys return pointers to the mask storage in here, but there'd be trouble if the code was saving multiple masks. I'll be @@ -3162,122 +2455,6 @@ get_random () #endif /* need at least 2 */ return val & ((1L << VALBITS) - 1); } - -#ifdef WRONG_NAME_INSQUE - -insque (q,p) - caddr_t q,p; -{ - _insque (q,p); -} - -#endif - -#ifdef VMS - -#ifdef getenv -/* If any place else asks for the TERM variable, - allow it to be overridden with the EMACS_TERM variable - before attempting to translate the logical name TERM. As a last - resort, ask for VAX C's special idea of the TERM variable. */ -#undef getenv -char * -sys_getenv (name) - char *name; -{ - register char *val; - static char buf[256]; - static struct dsc$descriptor_s equiv - = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf}; - static struct dsc$descriptor_s d_name - = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; - short eqlen; - - if (!strcmp (name, "TERM")) - { - val = (char *) getenv ("EMACS_TERM"); - if (val) - return val; - } - - d_name.dsc$w_length = strlen (name); - d_name.dsc$a_pointer = name; - if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1) - { - char *str = (char *) xmalloc (eqlen + 1); - bcopy (buf, str, eqlen); - str[eqlen] = '\0'; - /* This is a storage leak, but a pain to fix. With luck, - no one will ever notice. */ - return str; - } - return (char *) getenv (name); -} -#endif /* getenv */ - -#ifdef abort -/* Since VMS doesn't believe in core dumps, the only way to debug this beast is - to force a call on the debugger from within the image. */ -#undef abort -sys_abort () -{ - reset_sys_modes (); - LIB$SIGNAL (SS$_DEBUG); -} -#endif /* abort */ -#endif /* VMS */ - -#ifdef VMS -#ifdef LINK_CRTL_SHARE -#ifdef SHARABLE_LIB_BUG -/* Variables declared noshare and initialized in sharable libraries - cannot be shared. The VMS linker incorrectly forces you to use a private - version which is uninitialized... If not for this "feature", we - could use the C library definition of sys_nerr and sys_errlist. */ -int sys_nerr = 35; -char *sys_errlist[] = - { - "error 0", - "not owner", - "no such file or directory", - "no such process", - "interrupted system call", - "i/o error", - "no such device or address", - "argument list too long", - "exec format error", - "bad file number", - "no child process", - "no more processes", - "not enough memory", - "permission denied", - "bad address", - "block device required", - "mount devices busy", - "file exists", - "cross-device link", - "no such device", - "not a directory", - "is a directory", - "invalid argument", - "file table overflow", - "too many open files", - "not a typewriter", - "text file busy", - "file too big", - "no space left on device", - "illegal seek", - "read-only file system", - "too many links", - "broken pipe", - "math argument", - "result too large", - "I/O stream empty", - "vax/vms specific error code nontranslatable error" - }; -#endif /* SHARABLE_LIB_BUG */ -#endif /* LINK_CRTL_SHARE */ -#endif /* VMS */ #ifndef HAVE_STRERROR #ifndef WINDOWSNT @@ -3302,11 +2479,6 @@ emacs_open (path, oflag, mode) { register int rtnval; -#ifdef BSD4_1 - if (oflag & O_CREAT) - return creat (path, mode); -#endif - while ((rtnval = open (path, oflag, mode)) == -1 && (errno == EINTR)) QUIT; @@ -3320,15 +2492,6 @@ emacs_close (fd) int did_retry = 0; register int rtnval; -#if defined (MAC_OSX) && defined (HAVE_CARBON) - { - extern int mac_try_close_socket P_ ((int)); - - if (mac_try_close_socket (fd)) - return 0; - } -#endif - while ((rtnval = close (fd)) == -1 && (errno == EINTR)) did_retry = 1; @@ -3377,8 +2540,7 @@ emacs_write (fildes, buf, nbyte) #ifdef SYNC_INPUT /* I originally used `QUIT' but that might causes files to be truncated if you hit C-g in the middle of it. --Stef */ - if (interrupt_input_pending) - handle_async_input (); + process_pending_signals (); #endif continue; } @@ -3472,8 +2634,7 @@ rename (from, to) #endif -#ifdef HPUX -#ifndef HAVE_PERROR +#if defined(HPUX) && !defined(HAVE_PERROR) /* HPUX curses library references perror, but as far as we know it won't be called. Anyway this definition will do for now. */ @@ -3481,9 +2642,7 @@ rename (from, to) perror () { } - -#endif /* not HAVE_PERROR */ -#endif /* HPUX */ +#endif /* HPUX and not HAVE_PERROR */ #ifndef HAVE_DUP2 @@ -3524,7 +2683,6 @@ dup2 (oldd, newd) */ #ifdef subprocesses -#ifndef VMS #ifndef HAVE_GETTIMEOFDAY #ifdef HAVE_TIMEVAL @@ -3545,8 +2703,7 @@ gettimeofday (tp, tzp) #endif #endif -#endif -#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */ +#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */ /* * This function will go away as soon as all the stubs fixed. (fnf) @@ -3557,7 +2714,7 @@ croak (badfunc) char *badfunc; { printf ("%s not yet implemented\r\n", badfunc); - reset_sys_modes (); + reset_all_sys_modes (); exit (1); } @@ -3569,11 +2726,10 @@ croak (badfunc) #include -#if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR) +#if !defined (HAVE_CLOSEDIR) int -closedir (dirp) - register DIR *dirp; /* stream from opendir */ +closedir (DIR *dirp /* stream from opendir */) { int rtnval; @@ -3582,160 +2738,16 @@ closedir (dirp) /* Some systems (like Solaris) allocate the buffer and the DIR all in one block. Why in the world are we freeing this ourselves anyway? */ -#if ! (defined (sun) && defined (USG5_4)) +#if ! defined (SOLARIS2) xfree ((char *) dirp->dd_buf); /* directory block defined in */ #endif xfree ((char *) dirp); return rtnval; } -#endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */ +#endif /* not HAVE_CLOSEDIR */ #endif /* SYSV_SYSTEM_DIR */ -#ifdef NONSYSTEM_DIR_LIBRARY - -DIR * -opendir (filename) - char *filename; /* name of directory */ -{ - register DIR *dirp; /* -> malloc'ed storage */ - register int fd; /* file descriptor for read */ - struct stat sbuf; /* result of fstat */ - - fd = emacs_open (filename, O_RDONLY, 0); - if (fd < 0) - return 0; - - BLOCK_INPUT; - if (fstat (fd, &sbuf) < 0 - || (sbuf.st_mode & S_IFMT) != S_IFDIR - || (dirp = (DIR *) xmalloc (sizeof (DIR))) == 0) - { - emacs_close (fd); - UNBLOCK_INPUT; - return 0; /* bad luck today */ - } - UNBLOCK_INPUT; - - dirp->dd_fd = fd; - dirp->dd_loc = dirp->dd_size = 0; /* refill needed */ - - return dirp; -} - -void -closedir (dirp) - register DIR *dirp; /* stream from opendir */ -{ - emacs_close (dirp->dd_fd); - xfree ((char *) dirp); -} - - -#ifndef VMS -#define DIRSIZ 14 -struct olddir - { - ino_t od_ino; /* inode */ - char od_name[DIRSIZ]; /* filename */ - }; -#endif /* not VMS */ - -struct direct dir_static; /* simulated directory contents */ - -/* ARGUSED */ -struct direct * -readdir (dirp) - register DIR *dirp; /* stream from opendir */ -{ -#ifndef VMS - register struct olddir *dp; /* -> directory data */ -#else /* VMS */ - register struct dir$_name *dp; /* -> directory data */ - register struct dir$_version *dv; /* -> version data */ -#endif /* VMS */ - - for (; ;) - { - if (dirp->dd_loc >= dirp->dd_size) - dirp->dd_loc = dirp->dd_size = 0; - - if (dirp->dd_size == 0 /* refill buffer */ - && (dirp->dd_size = emacs_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0) - return 0; - -#ifndef VMS - dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc]; - dirp->dd_loc += sizeof (struct olddir); - - if (dp->od_ino != 0) /* not deleted entry */ - { - dir_static.d_ino = dp->od_ino; - strncpy (dir_static.d_name, dp->od_name, DIRSIZ); - dir_static.d_name[DIRSIZ] = '\0'; - dir_static.d_namlen = strlen (dir_static.d_name); - dir_static.d_reclen = sizeof (struct direct) - - MAXNAMLEN + 3 - + dir_static.d_namlen - dir_static.d_namlen % 4; - return &dir_static; /* -> simulated structure */ - } -#else /* VMS */ - dp = (struct dir$_name *) dirp->dd_buf; - if (dirp->dd_loc == 0) - dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1 - : dp->dir$b_namecount; - dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc]; - dir_static.d_ino = dv->dir$w_fid_num; - dir_static.d_namlen = dp->dir$b_namecount; - dir_static.d_reclen = sizeof (struct direct) - - MAXNAMLEN + 3 - + dir_static.d_namlen - dir_static.d_namlen % 4; - strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount); - dir_static.d_name[dir_static.d_namlen] = '\0'; - dirp->dd_loc = dirp->dd_size; /* only one record at a time */ - return &dir_static; -#endif /* VMS */ - } -} - -#ifdef VMS -/* readdirver is just like readdir except it returns all versions of a file - as separate entries. */ - -/* ARGUSED */ -struct direct * -readdirver (dirp) - register DIR *dirp; /* stream from opendir */ -{ - register struct dir$_name *dp; /* -> directory data */ - register struct dir$_version *dv; /* -> version data */ - - if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name)) - dirp->dd_loc = dirp->dd_size = 0; - - if (dirp->dd_size == 0 /* refill buffer */ - && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0) - return 0; - - dp = (struct dir$_name *) dirp->dd_buf; - if (dirp->dd_loc == 0) - dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1 - : dp->dir$b_namecount; - dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc]; - strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount); - sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version); - dir_static.d_namlen = strlen (dir_static.d_name); - dir_static.d_ino = dv->dir$w_fid_num; - dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 - + dir_static.d_namlen - dir_static.d_namlen % 4; - dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name); - return &dir_static; -} - -#endif /* VMS */ - -#endif /* NONSYSTEM_DIR_LIBRARY */ - int set_file_times (filename, atime, mtime) @@ -3886,1505 +2898,880 @@ rmdir (dpath) } #endif /* !HAVE_RMDIR */ - -/* Functions for VMS */ -#ifdef VMS -#include -#include -#include +#ifndef BSTRING -/* Return as a string the VMS error string pertaining to STATUS. - Reuses the same static buffer each time it is called. */ +#ifndef bzero -char * -vmserrstr (status) - int status; /* VMS status code */ +void +bzero (b, length) + register char *b; + register int length; { - int bufadr[2]; - short len; - static char buf[257]; - - bufadr[0] = sizeof buf - 1; - bufadr[1] = (int) buf; - if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1)) - return "untranslatable VMS error status"; - buf[len] = '\0'; - return buf; + while (length-- > 0) + *b++ = 0; } -#ifdef access -#undef access +#endif /* no bzero */ +#endif /* BSTRING */ -/* The following is necessary because 'access' emulation by VMS C (2.0) does - * not work correctly. (It also doesn't work well in version 2.3.) - */ +#if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) +#undef bcopy -#ifdef VMS4_4 - -#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \ - { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string } - -typedef union { - struct { - unsigned short s_buflen; - unsigned short s_code; - char *s_bufadr; - unsigned short *s_retlenadr; - } s; - int end; -} item; -#define buflen s.s_buflen -#define code s.s_code -#define bufadr s.s_bufadr -#define retlenadr s.s_retlenadr - -#define R_OK 4 /* test for read permission */ -#define W_OK 2 /* test for write permission */ -#define X_OK 1 /* test for execute (search) permission */ -#define F_OK 0 /* test for presence of file */ +/* Saying `void' requires a declaration, above, where bcopy is used + and that declaration causes pain for systems where bcopy is a macro. */ +bcopy (b1, b2, length) + register char *b1; + register char *b2; + register int length; +{ + while (length-- > 0) + *b2++ = *b1++; +} +#endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */ +#ifndef BSTRING +#ifndef bcmp int -sys_access (path, mode) - char *path; - int mode; +bcmp (b1, b2, length) /* This could be a macro! */ + register char *b1; + register char *b2; + register int length; { - static char *user = NULL; - char dir_fn[512]; - - /* translate possible directory spec into .DIR file name, so brain-dead - * access can treat the directory like a file. */ - if (directory_file_name (path, dir_fn)) - path = dir_fn; + while (length-- > 0) + if (*b1++ != *b2++) + return 1; - if (mode == F_OK) - return access (path, mode); - if (user == NULL && (user = (char *) getenv ("USER")) == NULL) - return -1; - { - int stat; - int flags; - int acces; - unsigned short int dummy; - item itemlst[3]; - static int constant = ACL$C_FILE; - DESCRIPTOR (path_desc, path); - DESCRIPTOR (user_desc, user); - - flags = 0; - acces = 0; - if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK)) - return stat; - if (mode & R_OK) - acces |= CHP$M_READ; - if (mode & W_OK) - acces |= CHP$M_WRITE; - itemlst[0].buflen = sizeof (int); - itemlst[0].code = CHP$_FLAGS; - itemlst[0].bufadr = (char *) &flags; - itemlst[0].retlenadr = &dummy; - itemlst[1].buflen = sizeof (int); - itemlst[1].code = CHP$_ACCESS; - itemlst[1].bufadr = (char *) &acces; - itemlst[1].retlenadr = &dummy; - itemlst[2].end = CHP$_END; - stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst); - return stat == SS$_NORMAL ? 0 : -1; - } + return 0; } - -#else /* not VMS4_4 */ - -#include -#define ACE$M_WRITE 2 -#define ACE$C_KEYID 1 - -static unsigned short memid, grpid; -static unsigned int uic; - -/* Called from init_sys_modes, so it happens not very often - but at least each time Emacs is loaded. */ -void -sys_access_reinit () +#endif /* no bcmp */ +#endif /* not BSTRING */ + +#ifndef HAVE_STRSIGNAL +char * +strsignal (code) + int code; { - uic = 0; -} + char *signame = 0; -int -sys_access (filename, type) - char * filename; - int type; -{ - struct FAB fab; - struct XABPRO xab; - int status, size, i, typecode, acl_controlled; - unsigned int *aclptr, *aclend, aclbuf[60]; - union prvdef prvmask; - - /* Get UIC and GRP values for protection checking. */ - if (uic == 0) + if (0 <= code && code < NSIG) { - status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0); - if (! (status & 1)) - return -1; - memid = uic & 0xFFFF; - grpid = uic >> 16; + /* Cast to suppress warning if the table has const char *. */ + signame = (char *) sys_siglist[code]; } - if (type != 2) /* not checking write access */ - return access (filename, type); - - /* Check write protection. */ - -#define CHECKPRIV(bit) (prvmask.bit) -#define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE)) - - /* Find privilege bits */ - status = SYS$SETPRV (0, 0, 0, prvmask); - if (! (status & 1)) - error ("Unable to find privileges: %s", vmserrstr (status)); - if (CHECKPRIV (PRV$V_BYPASS)) - return 0; /* BYPASS enabled */ - fab = cc$rms_fab; - fab.fab$b_fac = FAB$M_GET; - fab.fab$l_fna = filename; - fab.fab$b_fns = strlen (filename); - fab.fab$l_xab = &xab; - xab = cc$rms_xabpro; - xab.xab$l_aclbuf = aclbuf; - xab.xab$w_aclsiz = sizeof (aclbuf); - status = SYS$OPEN (&fab, 0, 0); - if (! (status & 1)) - return -1; - SYS$CLOSE (&fab, 0, 0); - /* Check system access */ - if (CHECKPRIV (PRV$V_SYSPRV) && WRITABLE (XAB$V_SYS)) - return 0; - /* Check ACL entries, if any */ - acl_controlled = 0; - if (xab.xab$w_acllen > 0) - { - aclptr = aclbuf; - aclend = &aclbuf[xab.xab$w_acllen / 4]; - while (*aclptr && aclptr < aclend) - { - size = (*aclptr & 0xff) / 4; - typecode = (*aclptr >> 8) & 0xff; - if (typecode == ACE$C_KEYID) - for (i = size - 1; i > 1; i--) - if (aclptr[i] == uic) - { - acl_controlled = 1; - if (aclptr[1] & ACE$M_WRITE) - return 0; /* Write access through ACL */ - } - aclptr = &aclptr[size]; - } - if (acl_controlled) /* ACL specified, prohibits write access */ - return -1; - } - /* No ACL entries specified, check normal protection */ - if (WRITABLE (XAB$V_WLD)) /* World writable */ - return 0; - if (WRITABLE (XAB$V_GRP) && - (unsigned short) (xab.xab$l_uic >> 16) == grpid) - return 0; /* Group writable */ - if (WRITABLE (XAB$V_OWN) && - (xab.xab$l_uic & 0xFFFF) == memid) - return 0; /* Owner writable */ - - return -1; /* Not writable */ + return signame; } -#endif /* not VMS4_4 */ -#endif /* access */ - -static char vtbuf[NAM$C_MAXRSS+1]; - -/* translate a vms file spec to a unix path */ -char * -sys_translate_vms (vfile) - char * vfile; +#endif /* HAVE_STRSIGNAL */ + +#ifdef HAVE_TERMIOS +/* For make-serial-process */ +int serial_open (char *port) { - char * p; - char * targ; - - if (!vfile) - return 0; - - targ = vtbuf; + int fd = -1; - /* leading device or logical name is a root directory */ - if (p = strchr (vfile, ':')) + fd = emacs_open ((char*) port, + O_RDWR +#ifdef O_NONBLOCK + | O_NONBLOCK +#else + | O_NDELAY +#endif +#ifdef O_NOCTTY + | O_NOCTTY +#endif + , 0); + if (fd < 0) { - *targ++ = '/'; - while (vfile < p) - *targ++ = *vfile++; - vfile++; - *targ++ = '/'; + error ("Could not open %s: %s", + port, emacs_strerror (errno)); } - p = vfile; - if (*p == '[' || *p == '<') - { - while (*++vfile != *p + 2) - switch (*vfile) - { - case '.': - if (vfile[-1] == *p) - *targ++ = '.'; - *targ++ = '/'; - break; +#ifdef TIOCEXCL + ioctl (fd, TIOCEXCL, (char *) 0); +#endif - case '-': - *targ++ = '.'; - *targ++ = '.'; - break; + return fd; +} +#endif /* TERMIOS */ - default: - *targ++ = *vfile; - break; - } - vfile++; - *targ++ = '/'; - } - while (*vfile) - *targ++ = *vfile++; +#ifdef HAVE_TERMIOS - return vtbuf; +#if !defined (HAVE_CFMAKERAW) +/* Workaround for targets which are missing cfmakeraw. */ +/* Pasted from man page. */ +static void cfmakeraw (struct termios *termios_p) +{ + termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + termios_p->c_oflag &= ~OPOST; + termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + termios_p->c_cflag &= ~(CSIZE|PARENB); + termios_p->c_cflag |= CS8; } +#endif /* !defined (HAVE_CFMAKERAW */ -static char utbuf[NAM$C_MAXRSS+1]; +#if !defined (HAVE_CFSETSPEED) +/* Workaround for targets which are missing cfsetspeed. */ +static int cfsetspeed (struct termios *termios_p, speed_t vitesse) +{ + return (cfsetispeed (termios_p, vitesse) + + cfsetospeed (termios_p, vitesse)); +} +#endif -/* translate a unix path to a VMS file spec */ -char * -sys_translate_unix (ufile) - char * ufile; +/* For serial-process-configure */ +void +serial_configure (struct Lisp_Process *p, + Lisp_Object contact) { - int slash_seen = 0; - char *p; - char * targ; + Lisp_Object childp2 = Qnil; + Lisp_Object tem = Qnil; + struct termios attr; + int err = -1; + char summary[4] = "???"; /* This usually becomes "8N1". */ - if (!ufile) - return 0; + childp2 = Fcopy_sequence (p->childp); - targ = utbuf; + /* Read port attributes and prepare default configuration. */ + err = tcgetattr (p->outfd, &attr); + if (err != 0) + error ("tcgetattr() failed: %s", emacs_strerror (errno)); + cfmakeraw (&attr); +#if defined (CLOCAL) + attr.c_cflag |= CLOCAL; +#endif +#if defined (CREAD) + attr.c_cflag |= CREAD; +#endif - if (*ufile == '/') - { - ufile++; - } - - while (*ufile) - { - switch (*ufile) - { - case '/': - if (slash_seen) - if (index (&ufile[1], '/')) - *targ++ = '.'; - else - *targ++ = ']'; - else - { - *targ++ = ':'; - if (index (&ufile[1], '/')) - *targ++ = '['; - slash_seen = 1; - } - break; - - case '.': - if (strncmp (ufile, "./", 2) == 0) - { - if (!slash_seen) - { - *targ++ = '['; - slash_seen = 1; - } - ufile++; /* skip the dot */ - if (index (&ufile[1], '/')) - *targ++ = '.'; - else - *targ++ = ']'; - } - else if (strncmp (ufile, "../", 3) == 0) - { - if (!slash_seen) - { - *targ++ = '['; - slash_seen = 1; - } - *targ++ = '-'; - ufile += 2; /* skip the dots */ - if (index (&ufile[1], '/')) - *targ++ = '.'; - else - *targ++ = ']'; - } - else - *targ++ = *ufile; - break; - - default: - *targ++ = *ufile; - break; - } - ufile++; - } - *targ = '\0'; - - return utbuf; -} - -char * -getwd (pathname) - char *pathname; -{ - char *ptr, *val; - extern char *getcwd (); - -#define MAXPATHLEN 1024 - - ptr = xmalloc (MAXPATHLEN); - val = getcwd (ptr, MAXPATHLEN); - if (val == 0) - { - xfree (ptr); - return val; - } - strcpy (pathname, ptr); - xfree (ptr); - - return pathname; -} - -int -getppid () -{ - long item_code = JPI$_OWNER; - unsigned long parent_id; - int status; - - if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0) - { - errno = EVMSERR; - vaxc$errno = status; - return -1; - } - return parent_id; -} - -#undef getuid -unsigned -sys_getuid () -{ - return (getgid () << 16) | getuid (); -} - -#undef read -int -sys_read (fildes, buf, nbyte) - int fildes; - char *buf; - unsigned int nbyte; -{ - return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE)); -} - -#if 0 -int -sys_write (fildes, buf, nbyte) - int fildes; - char *buf; - unsigned int nbyte; -{ - register int nwrote, rtnval = 0; - - while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) { - nbyte -= nwrote; - buf += nwrote; - rtnval += nwrote; - } - if (nwrote < 0) - return rtnval ? rtnval : -1; - if ((nwrote = write (fildes, buf, nbyte)) < 0) - return rtnval ? rtnval : -1; - return (rtnval + nwrote); -} -#endif /* 0 */ - -/* - * VAX/VMS VAX C RTL really loses. It insists that records - * end with a newline (carriage return) character, and if they - * don't it adds one (nice of it isn't it!) - * - * Thus we do this stupidity below. - */ - -#undef write -int -sys_write (fildes, buf, nbytes) - int fildes; - char *buf; - unsigned int nbytes; -{ - register char *p; - register char *e; - int sum = 0; - struct stat st; + /* Configure speed. */ + if (!NILP (Fplist_member (contact, QCspeed))) + tem = Fplist_get (contact, QCspeed); + else + tem = Fplist_get (p->childp, QCspeed); + CHECK_NUMBER (tem); + err = cfsetspeed (&attr, XINT (tem)); + if (err != 0) + error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno)); + childp2 = Fplist_put (childp2, QCspeed, tem); + + /* Configure bytesize. */ + if (!NILP (Fplist_member (contact, QCbytesize))) + tem = Fplist_get (contact, QCbytesize); + else + tem = Fplist_get (p->childp, QCbytesize); + if (NILP (tem)) + tem = make_number (8); + CHECK_NUMBER (tem); + if (XINT (tem) != 7 && XINT (tem) != 8) + error (":bytesize must be nil (8), 7, or 8"); + summary[0] = XINT(tem) + '0'; +#if defined (CSIZE) && defined (CS7) && defined (CS8) + attr.c_cflag &= ~CSIZE; + attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8); +#else + /* Don't error on bytesize 8, which should be set by cfmakeraw. */ + if (XINT (tem) != 8) + error ("Bytesize cannot be changed"); +#endif + childp2 = Fplist_put (childp2, QCbytesize, tem); - fstat (fildes, &st); - p = buf; - while (nbytes > 0) + /* Configure parity. */ + if (!NILP (Fplist_member (contact, QCparity))) + tem = Fplist_get (contact, QCparity); + else + tem = Fplist_get (p->childp, QCparity); + if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd)) + error (":parity must be nil (no parity), `even', or `odd'"); +#if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK) + attr.c_cflag &= ~(PARENB | PARODD); + attr.c_iflag &= ~(IGNPAR | INPCK); + if (NILP (tem)) { - int len, retval; - - /* Handle fixed-length files with carriage control. */ - if (st.st_fab_rfm == FAB$C_FIX - && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)) - { - len = st.st_fab_mrs; - retval = write (fildes, p, min (len, nbytes)); - if (retval != len) - return -1; - retval++; /* This skips the implied carriage control */ - } - else - { - e = p + min (MAXIOSIZE, nbytes) - 1; - while (*e != '\n' && e > p) e--; - if (p == e) /* Ok.. so here we add a newline... sigh. */ - e = p + min (MAXIOSIZE, nbytes) - 1; - len = e + 1 - p; - retval = write (fildes, p, len); - if (retval != len) - return -1; - } - p += retval; - sum += retval; - nbytes -= retval; + summary[1] = 'N'; } - return sum; -} - -/* Create file NEW copying its attributes from file OLD. If - OLD is 0 or does not exist, create based on the value of - vms_stmlf_recfm. */ - -/* Protection value the file should ultimately have. - Set by create_copy_attrs, and use by rename_sansversions. */ -static unsigned short int fab_final_pro; - -int -creat_copy_attrs (old, new) - char *old, *new; -{ - struct FAB fab = cc$rms_fab; - struct XABPRO xabpro; - char aclbuf[256]; /* Choice of size is arbitrary. See below. */ - extern int vms_stmlf_recfm; - - if (old) + else if (EQ (tem, Qeven)) { - fab.fab$b_fac = FAB$M_GET; - fab.fab$l_fna = old; - fab.fab$b_fns = strlen (old); - fab.fab$l_xab = (char *) &xabpro; - xabpro = cc$rms_xabpro; - xabpro.xab$l_aclbuf = aclbuf; - xabpro.xab$w_aclsiz = sizeof aclbuf; - /* Call $OPEN to fill in the fab & xabpro fields. */ - if (SYS$OPEN (&fab, 0, 0) & 1) - { - SYS$CLOSE (&fab, 0, 0); - fab.fab$l_alq = 0; /* zero the allocation quantity */ - if (xabpro.xab$w_acllen > 0) - { - if (xabpro.xab$w_acllen > sizeof aclbuf) - /* If the acl buffer was too short, redo open with longer one. - Wouldn't need to do this if there were some system imposed - limit on the size of an ACL, but I can't find any such. */ - { - xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen); - xabpro.xab$w_aclsiz = xabpro.xab$w_acllen; - if (SYS$OPEN (&fab, 0, 0) & 1) - SYS$CLOSE (&fab, 0, 0); - else - old = 0; - } - } - else - xabpro.xab$l_aclbuf = 0; - } - else - old = 0; + summary[1] = 'E'; + attr.c_cflag |= PARENB; + attr.c_iflag |= (IGNPAR | INPCK); } - fab.fab$l_fna = new; - fab.fab$b_fns = strlen (new); - if (!old) + else if (EQ (tem, Qodd)) { - fab.fab$l_xab = 0; - fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR; - fab.fab$b_rat = FAB$M_CR; + summary[1] = 'O'; + attr.c_cflag |= (PARENB | PARODD); + attr.c_iflag |= (IGNPAR | INPCK); } +#else + /* Don't error on no parity, which should be set by cfmakeraw. */ + if (!NILP (tem)) + error ("Parity cannot be configured"); +#endif + childp2 = Fplist_put (childp2, QCparity, tem); - /* Set the file protections such that we will be able to manipulate - this file. Once we are done writing and renaming it, we will set - the protections back. */ - if (old) - fab_final_pro = xabpro.xab$w_pro; + /* Configure stopbits. */ + if (!NILP (Fplist_member (contact, QCstopbits))) + tem = Fplist_get (contact, QCstopbits); else - SYS$SETDFPROT (0, &fab_final_pro); - xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */ - - /* Create the new file with either default attrs or attrs copied - from old file. */ - if (!(SYS$CREATE (&fab, 0, 0) & 1)) - return -1; - SYS$CLOSE (&fab, 0, 0); - /* As this is a "replacement" for creat, return a file descriptor - opened for writing. */ - return open (new, O_WRONLY); -} + tem = Fplist_get (p->childp, QCstopbits); + if (NILP (tem)) + tem = make_number (1); + CHECK_NUMBER (tem); + if (XINT (tem) != 1 && XINT (tem) != 2) + error (":stopbits must be nil (1 stopbit), 1, or 2"); + summary[2] = XINT (tem) + '0'; +#if defined (CSTOPB) + attr.c_cflag &= ~CSTOPB; + if (XINT (tem) == 2) + attr.c_cflag |= CSTOPB; +#else + /* Don't error on 1 stopbit, which should be set by cfmakeraw. */ + if (XINT (tem) != 1) + error ("Stopbits cannot be configured"); +#endif + childp2 = Fplist_put (childp2, QCstopbits, tem); -#ifdef creat -#undef creat -#include -#ifdef __GNUC__ -#ifndef va_count -#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1)) + /* Configure flowcontrol. */ + if (!NILP (Fplist_member (contact, QCflowcontrol))) + tem = Fplist_get (contact, QCflowcontrol); + else + tem = Fplist_get (p->childp, QCflowcontrol); + if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw)) + error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'"); +#if defined (CRTSCTS) + attr.c_cflag &= ~CRTSCTS; #endif +#if defined (CNEW_RTSCTS) + attr.c_cflag &= ~CNEW_RTSCTS; #endif - -int -sys_creat (va_alist) - va_dcl -{ - va_list list_incrementer; - char *name; - int mode; - int rfd; /* related file descriptor */ - int fd; /* Our new file descriptor */ - int count; - struct stat st_buf; - char rfm[12]; - char rat[15]; - char mrs[13]; - char fsz[13]; - extern int vms_stmlf_recfm; - - va_count (count); - va_start (list_incrementer); - name = va_arg (list_incrementer, char *); - mode = va_arg (list_incrementer, int); - if (count > 2) - rfd = va_arg (list_incrementer, int); - va_end (list_incrementer); - if (count > 2) +#if defined (IXON) && defined (IXOFF) + attr.c_iflag &= ~(IXON | IXOFF); +#endif + if (NILP (tem)) { - /* Use information from the related file descriptor to set record - format of the newly created file. */ - fstat (rfd, &st_buf); - switch (st_buf.st_fab_rfm) - { - case FAB$C_FIX: - strcpy (rfm, "rfm = fix"); - sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs); - strcpy (rat, "rat = "); - if (st_buf.st_fab_rat & FAB$M_CR) - strcat (rat, "cr"); - else if (st_buf.st_fab_rat & FAB$M_FTN) - strcat (rat, "ftn"); - else if (st_buf.st_fab_rat & FAB$M_PRN) - strcat (rat, "prn"); - if (st_buf.st_fab_rat & FAB$M_BLK) - if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN)) - strcat (rat, ", blk"); - else - strcat (rat, "blk"); - return creat (name, 0, rfm, rat, mrs); - - case FAB$C_VFC: - strcpy (rfm, "rfm = vfc"); - sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz); - strcpy (rat, "rat = "); - if (st_buf.st_fab_rat & FAB$M_CR) - strcat (rat, "cr"); - else if (st_buf.st_fab_rat & FAB$M_FTN) - strcat (rat, "ftn"); - else if (st_buf.st_fab_rat & FAB$M_PRN) - strcat (rat, "prn"); - if (st_buf.st_fab_rat & FAB$M_BLK) - if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN)) - strcat (rat, ", blk"); - else - strcat (rat, "blk"); - return creat (name, 0, rfm, rat, fsz); - - case FAB$C_STM: - strcpy (rfm, "rfm = stm"); - break; - - case FAB$C_STMCR: - strcpy (rfm, "rfm = stmcr"); - break; - - case FAB$C_STMLF: - strcpy (rfm, "rfm = stmlf"); - break; - - case FAB$C_UDF: - strcpy (rfm, "rfm = udf"); - break; - - case FAB$C_VAR: - strcpy (rfm, "rfm = var"); - break; - } - strcpy (rat, "rat = "); - if (st_buf.st_fab_rat & FAB$M_CR) - strcat (rat, "cr"); - else if (st_buf.st_fab_rat & FAB$M_FTN) - strcat (rat, "ftn"); - else if (st_buf.st_fab_rat & FAB$M_PRN) - strcat (rat, "prn"); - if (st_buf.st_fab_rat & FAB$M_BLK) - if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN)) - strcat (rat, ", blk"); - else - strcat (rat, "blk"); + /* Already configured. */ } - else + else if (EQ (tem, Qhw)) { - strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var"); - strcpy (rat, "rat=cr"); +#if defined (CRTSCTS) + attr.c_cflag |= CRTSCTS; +#elif defined (CNEW_RTSCTS) + attr.c_cflag |= CNEW_RTSCTS; +#else + error ("Hardware flowcontrol (RTS/CTS) not supported"); +#endif } - /* Until the VAX C RTL fixes the many bugs with modes, always use - mode 0 to get the user's default protection. */ - fd = creat (name, 0, rfm, rat); - if (fd < 0 && errno == EEXIST) + else if (EQ (tem, Qsw)) { - if (unlink (name) < 0) - report_file_error ("delete", build_string (name)); - fd = creat (name, 0, rfm, rat); +#if defined (IXON) && defined (IXOFF) + attr.c_iflag |= (IXON | IXOFF); +#else + error ("Software flowcontrol (XON/XOFF) not supported"); +#endif } - return fd; -} -#endif /* creat */ + childp2 = Fplist_put (childp2, QCflowcontrol, tem); -/* fwrite to stdout is S L O W. Speed it up by using fputc...*/ -int -sys_fwrite (ptr, size, num, fp) - register char * ptr; - FILE * fp; -{ - register int tot = num * size; + /* Activate configuration. */ + err = tcsetattr (p->outfd, TCSANOW, &attr); + if (err != 0) + error ("tcsetattr() failed: %s", emacs_strerror (errno)); - while (tot--) - fputc (*ptr++, fp); - return num; -} + childp2 = Fplist_put (childp2, QCsummary, build_string (summary)); + p->childp = childp2; -/* - * The VMS C library routine creat actually creates a new version of an - * existing file rather than truncating the old version. There are times - * when this is not the desired behavior, for instance, when writing an - * auto save file (you only want one version), or when you don't have - * write permission in the directory containing the file (but the file - * itself is writable). Hence this routine, which is equivalent to - * "close (creat (fn, 0));" on Unix if fn already exists. - */ -int -vms_truncate (fn) - char *fn; -{ - struct FAB xfab = cc$rms_fab; - struct RAB xrab = cc$rms_rab; - int status; - - xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */ - xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */ - xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */ - xfab.fab$l_fna = fn; - xfab.fab$b_fns = strlen (fn); - xfab.fab$l_dna = ";0"; /* default to latest version of the file */ - xfab.fab$b_dns = 2; - xrab.rab$l_fab = &xfab; - - /* This gibberish opens the file, positions to the first record, and - deletes all records from there until the end of file. */ - if ((SYS$OPEN (&xfab) & 01) == 01) - { - if ((SYS$CONNECT (&xrab) & 01) == 01 && - (SYS$FIND (&xrab) & 01) == 01 && - (SYS$TRUNCATE (&xrab) & 01) == 01) - status = 0; - else - status = -1; - } - else - status = -1; - SYS$CLOSE (&xfab); - return status; } +#endif /* TERMIOS */ + +/* System depended enumeration of and access to system processes a-la ps(1). */ -/* Define this symbol to actually read SYSUAF.DAT. This requires either - SYSPRV or a readable SYSUAF.DAT. */ +#ifdef HAVE_PROCFS -#ifdef READ_SYSUAF -/* - * getuaf.c - * - * Routine to read the VMS User Authorization File and return - * a specific user's record. - */ - -static struct UAF retuaf; +/* Process enumeration and access via /proc. */ -struct UAF * -get_uaf_name (uname) - char * uname; +Lisp_Object +list_system_processes () { - register status; - struct FAB uaf_fab; - struct RAB uaf_rab; - - uaf_fab = cc$rms_fab; - uaf_rab = cc$rms_rab; - /* initialize fab fields */ - uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT"; - uaf_fab.fab$b_fns = 21; - uaf_fab.fab$b_fac = FAB$M_GET; - uaf_fab.fab$b_org = FAB$C_IDX; - uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL; - /* initialize rab fields */ - uaf_rab.rab$l_fab = &uaf_fab; - /* open the User Authorization File */ - status = SYS$OPEN (&uaf_fab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - status = SYS$CONNECT (&uaf_rab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - /* read the requested record - index is in uname */ - uaf_rab.rab$l_kbf = uname; - uaf_rab.rab$b_ksz = strlen (uname); - uaf_rab.rab$b_rac = RAB$C_KEY; - uaf_rab.rab$l_ubf = (char *)&retuaf; - uaf_rab.rab$w_usz = sizeof retuaf; - status = SYS$GET (&uaf_rab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - /* close the User Authorization File */ - status = SYS$DISCONNECT (&uaf_rab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - status = SYS$CLOSE (&uaf_fab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - return &retuaf; -} + Lisp_Object procdir, match, proclist, next; + struct gcpro gcpro1, gcpro2; + register Lisp_Object tail; -struct UAF * -get_uaf_uic (uic) - unsigned long uic; -{ - register status; - struct FAB uaf_fab; - struct RAB uaf_rab; - - uaf_fab = cc$rms_fab; - uaf_rab = cc$rms_rab; - /* initialize fab fields */ - uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT"; - uaf_fab.fab$b_fns = 21; - uaf_fab.fab$b_fac = FAB$M_GET; - uaf_fab.fab$b_org = FAB$C_IDX; - uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL; - /* initialize rab fields */ - uaf_rab.rab$l_fab = &uaf_fab; - /* open the User Authorization File */ - status = SYS$OPEN (&uaf_fab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - status = SYS$CONNECT (&uaf_rab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - /* read the requested record - index is in uic */ - uaf_rab.rab$b_krf = 1; /* 1st alternate key */ - uaf_rab.rab$l_kbf = (char *) &uic; - uaf_rab.rab$b_ksz = sizeof uic; - uaf_rab.rab$b_rac = RAB$C_KEY; - uaf_rab.rab$l_ubf = (char *)&retuaf; - uaf_rab.rab$w_usz = sizeof retuaf; - status = SYS$GET (&uaf_rab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - /* close the User Authorization File */ - status = SYS$DISCONNECT (&uaf_rab); - if (!(status&1)) - { - errno = EVMSERR; - vaxc$errno = status; - return 0; - } - status = SYS$CLOSE (&uaf_fab); - if (!(status&1)) + GCPRO2 (procdir, match); + /* For every process on the system, there's a directory in the + "/proc" pseudo-directory whose name is the numeric ID of that + process. */ + procdir = build_string ("/proc"); + match = build_string ("[0-9]+"); + proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil); + + /* `proclist' gives process IDs as strings. Destructively convert + each string into a number. */ + for (tail = proclist; CONSP (tail); tail = next) { - errno = EVMSERR; - vaxc$errno = status; - return 0; + next = XCDR (tail); + XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil)); } - return &retuaf; + UNGCPRO; + + /* directory_files_internal returns the files in reverse order; undo + that. */ + proclist = Fnreverse (proclist); + return proclist; } -static struct passwd retpw; +/* The WINDOWSNT implementation is on w32.c. + The MSDOS implementation is on dosfns.c. */ +#elif !defined (WINDOWSNT) && !defined (MSDOS) -struct passwd * -cnv_uaf_pw (up) - struct UAF * up; +Lisp_Object +list_system_processes () { - char * ptr; - - /* copy these out first because if the username is 32 chars, the next - section will overwrite the first byte of the UIC */ - retpw.pw_uid = up->uaf$w_mem; - retpw.pw_gid = up->uaf$w_grp; - - /* I suppose this is not the best style, to possibly overwrite one - byte beyond the end of the field, but what the heck... */ - ptr = &up->uaf$t_username[UAF$S_USERNAME]; - while (ptr[-1] == ' ') - ptr--; - *ptr = '\0'; - strcpy (retpw.pw_name, up->uaf$t_username); - - /* the rest of these are counted ascii strings */ - strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]); - retpw.pw_gecos[up->uaf$t_owner[0]] = '\0'; - strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]); - retpw.pw_dir[up->uaf$t_defdev[0]] = '\0'; - strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]); - retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0'; - strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]); - retpw.pw_shell[up->uaf$t_defcli[0]] = '\0'; - - return &retpw; + return Qnil; } -#else /* not READ_SYSUAF */ -static struct passwd retpw; -#endif /* not READ_SYSUAF */ -struct passwd * -getpwnam (name) - char * name; -{ -#ifdef READ_SYSUAF - struct UAF *up; -#else - char * user; - char * dir; - unsigned char * full; -#endif /* READ_SYSUAF */ - char *ptr = name; +#endif /* !defined (WINDOWSNT) */ - while (*ptr) - { - if ('a' <= *ptr && *ptr <= 'z') - *ptr -= 040; - ptr++; - } -#ifdef READ_SYSUAF - if (!(up = get_uaf_name (name))) - return 0; - return cnv_uaf_pw (up); -#else - if (strcmp (name, getenv ("USER")) == 0) - { - retpw.pw_uid = getuid (); - retpw.pw_gid = getgid (); - strcpy (retpw.pw_name, name); - if (full = egetenv ("FULLNAME")) - strcpy (retpw.pw_gecos, full); - else - *retpw.pw_gecos = '\0'; - strcpy (retpw.pw_dir, egetenv ("HOME")); - *retpw.pw_shell = '\0'; - return &retpw; - } - else - return 0; -#endif /* not READ_SYSUAF */ -} - -struct passwd * -getpwuid (uid) - unsigned long uid; +#ifdef GNU_LINUX +static void +time_from_jiffies (unsigned long long tval, long hz, + time_t *sec, unsigned *usec) { -#ifdef READ_SYSUAF - struct UAF * up; + unsigned long long ullsec; - if (!(up = get_uaf_uic (uid))) - return 0; - return cnv_uaf_pw (up); -#else - if (uid == sys_getuid ()) - return getpwnam (egetenv ("USER")); + *sec = tval / hz; + ullsec = *sec; + tval -= ullsec * hz; + /* Careful: if HZ > 1 million, then integer division by it yields zero. */ + if (hz <= 1000000) + *usec = tval * 1000000 / hz; else - return 0; -#endif /* not READ_SYSUAF */ + *usec = tval / (hz / 1000000); } -/* return total address space available to the current process. This is - the sum of the current p0 size, p1 size and free page table entries - available. */ -int -vlimit () +static Lisp_Object +ltime_from_jiffies (unsigned long long tval, long hz) { - int item_code; - unsigned long free_pages; - unsigned long frep0va; - unsigned long frep1va; - register status; - - item_code = JPI$_FREPTECNT; - if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0) - { - errno = EVMSERR; - vaxc$errno = status; - return -1; - } - free_pages *= 512; + time_t sec; + unsigned usec; - item_code = JPI$_FREP0VA; - if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0) - { - errno = EVMSERR; - vaxc$errno = status; - return -1; - } - item_code = JPI$_FREP1VA; - if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0) - { - errno = EVMSERR; - vaxc$errno = status; - return -1; - } + time_from_jiffies (tval, hz, &sec, &usec); - return free_pages + frep0va + (0x7fffffff - frep1va); + return list3 (make_number ((sec >> 16) & 0xffff), + make_number (sec & 0xffff), + make_number (usec)); } -int -define_logical_name (varname, string) - char *varname; - char *string; +static void +get_up_time (time_t *sec, unsigned *usec) { - struct dsc$descriptor_s strdsc = - {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string}; - struct dsc$descriptor_s envdsc = - {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname}; - struct dsc$descriptor_s lnmdsc = - {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"}; - - return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0); -} + FILE *fup; -int -delete_logical_name (varname) - char *varname; -{ - struct dsc$descriptor_s envdsc = - {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname}; - struct dsc$descriptor_s lnmdsc = - {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"}; + *sec = *usec = 0; - return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc); -} + BLOCK_INPUT; + fup = fopen ("/proc/uptime", "r"); -int -ulimit () -{ - return 0; -} + if (fup) + { + double uptime, idletime; -int -setpgrp () -{ - return 0; + /* The numbers in /proc/uptime use C-locale decimal point, but + we already set ourselves to the C locale (see `fixup_locale' + in emacs.c). */ + if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime)) + { + *sec = uptime; + *usec = (uptime - *sec) * 1000000; + } + fclose (fup); + } + UNBLOCK_INPUT; } -int -execvp () -{ - error ("execvp system call not implemented"); - return -1; -} +#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff) +#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12)) -int -rename (from, to) - char *from, *to; +static Lisp_Object +procfs_ttyname (int rdev) { - int status; - struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab; - struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam; - char from_esn[NAM$C_MAXRSS]; - char to_esn[NAM$C_MAXRSS]; - - from_fab.fab$l_fna = from; - from_fab.fab$b_fns = strlen (from); - from_fab.fab$l_nam = &from_nam; - from_fab.fab$l_fop = FAB$M_NAM; + FILE *fdev = NULL; + char name[PATH_MAX]; - from_nam.nam$l_esa = from_esn; - from_nam.nam$b_ess = sizeof from_esn; - - to_fab.fab$l_fna = to; - to_fab.fab$b_fns = strlen (to); - to_fab.fab$l_nam = &to_nam; - to_fab.fab$l_fop = FAB$M_NAM; + BLOCK_INPUT; + fdev = fopen ("/proc/tty/drivers", "r"); - to_nam.nam$l_esa = to_esn; - to_nam.nam$b_ess = sizeof to_esn; + if (fdev) + { + unsigned major; + unsigned long minor_beg, minor_end; + char minor[25]; /* 2 32-bit numbers + dash */ + char *endp; - status = SYS$RENAME (&from_fab, 0, 0, &to_fab); + while (!feof (fdev) && !ferror (fdev)) + { + if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor) + && major == MAJOR (rdev)) + { + minor_beg = strtoul (minor, &endp, 0); + if (*endp == '\0') + minor_end = minor_beg; + else if (*endp == '-') + minor_end = strtoul (endp + 1, &endp, 0); + else + continue; - if (status & 1) - return 0; - else - { - if (status == RMS$_DEV) - errno = EXDEV; - else - errno = EVMSERR; - vaxc$errno = status; - return -1; + if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end) + { + sprintf (name + strlen (name), "%lu", MINOR (rdev)); + break; + } + } + } + fclose (fdev); } + UNBLOCK_INPUT; + return build_string (name); } -/* This function renames a file like `rename', but it strips - the version number from the "to" filename, such that the "to" file is - will always be a new version. It also sets the file protection once it is - finished. The protection that we will use is stored in fab_final_pro, - and was set when we did a creat_copy_attrs to create the file that we - are renaming. - - We could use the chmod function, but Eunichs uses 3 bits per user category - to describe the protection, and VMS uses 4 (write and delete are separate - bits). To maintain portability, the VMS implementation of `chmod' wires - the W and D bits together. */ +static unsigned long +procfs_get_total_memory (void) +{ + FILE *fmem = NULL; + unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ + BLOCK_INPUT; + fmem = fopen ("/proc/meminfo", "r"); -static struct fibdef fib; /* We need this initialized to zero */ -char vms_file_written[NAM$C_MAXRSS]; + if (fmem) + { + unsigned long entry_value; + char entry_name[20]; /* the longest I saw is 13+1 */ -int -rename_sans_version (from,to) - char *from, *to; -{ - short int chan; - int stat; - short int iosb[4]; - int status; - struct FAB to_fab = cc$rms_fab; - struct NAM to_nam = cc$rms_nam; - struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib}; - struct dsc$descriptor fib_attr[2] - = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}}; - char to_esn[NAM$C_MAXRSS]; - - $DESCRIPTOR (disk,to_esn); - - to_fab.fab$l_fna = to; - to_fab.fab$b_fns = strlen (to); - to_fab.fab$l_nam = &to_nam; - to_fab.fab$l_fop = FAB$M_NAM; - - to_nam.nam$l_esa = to_esn; - to_nam.nam$b_ess = sizeof to_esn; - - status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */ - - if (to_nam.nam$l_fnb && NAM$M_EXP_VER) - *(to_nam.nam$l_ver) = '\0'; - - stat = rename (from, to_esn); - if (stat < 0) - return stat; - - strcpy (vms_file_written, to_esn); - - to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */ - to_fab.fab$b_fns = strlen (vms_file_written); - - /* Now set the file protection to the correct value */ - SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */ - - /* Copy these fields into the fib */ - fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0]; - fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1]; - fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2]; - - SYS$CLOSE (&to_fab, 0, 0); - - stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */ - if (!stat) - LIB$SIGNAL (stat); - stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d, - 0, 0, 0, &fib_attr, 0); - if (!stat) - LIB$SIGNAL (stat); - stat = SYS$DASSGN (chan); - if (!stat) - LIB$SIGNAL (stat); - strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/ - return 0; + while (!feof (fmem) && !ferror (fmem)) + { + if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value) + && strcmp (entry_name, "MemTotal:") == 0) + { + retval = entry_value; + break; + } + } + fclose (fmem); + } + UNBLOCK_INPUT; + return retval; } -int -link (file, new) - char * file, * new; +Lisp_Object +system_process_attributes (Lisp_Object pid) { - register status; - struct FAB fab; - struct NAM nam; - unsigned short fid[3]; - char esa[NAM$C_MAXRSS]; - - fab = cc$rms_fab; - fab.fab$l_fop = FAB$M_OFP; - fab.fab$l_fna = file; - fab.fab$b_fns = strlen (file); - fab.fab$l_nam = &nam; - - nam = cc$rms_nam; - nam.nam$l_esa = esa; - nam.nam$b_ess = NAM$C_MAXRSS; - - status = SYS$PARSE (&fab); - if ((status & 1) == 0) - { - errno = EVMSERR; - vaxc$errno = status; - return -1; - } - status = SYS$SEARCH (&fab); - if ((status & 1) == 0) - { - errno = EVMSERR; - vaxc$errno = status; - return -1; - } - - fid[0] = nam.nam$w_fid[0]; - fid[1] = nam.nam$w_fid[1]; - fid[2] = nam.nam$w_fid[2]; + char procfn[PATH_MAX], fn[PATH_MAX]; + struct stat st; + struct passwd *pw; + struct group *gr; + long clocks_per_sec; + char *procfn_end; + char procbuf[1025], *p, *q; + int fd; + ssize_t nread; + const char *cmd = NULL; + char *cmdline = NULL; + size_t cmdsize = 0, cmdline_size; + unsigned char c; + int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount; + unsigned long long utime, stime, cutime, cstime, start; + long priority, nice, rss; + unsigned long minflt, majflt, cminflt, cmajflt, vsize; + time_t sec; + unsigned usec; + EMACS_TIME tnow, tstart, tboot, telapsed,ttotal; + double pcpu, pmem; + Lisp_Object attrs = Qnil; + Lisp_Object cmd_str, decoded_cmd, tem; + struct gcpro gcpro1, gcpro2; + EMACS_INT uid_eint, gid_eint; + + CHECK_NUMBER_OR_FLOAT (pid); + proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid); + sprintf (procfn, "/proc/%lu", proc_id); + if (stat (procfn, &st) < 0) + return attrs; + + GCPRO2 (attrs, decoded_cmd); + + /* euid egid */ + uid = st.st_uid; + /* Use of EMACS_INT stops GCC whining about limited range of data type. */ + uid_eint = uid; + attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs); + BLOCK_INPUT; + pw = getpwuid (uid); + UNBLOCK_INPUT; + if (pw) + attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); - fab.fab$l_fna = new; - fab.fab$b_fns = strlen (new); + gid = st.st_gid; + gid_eint = gid; + attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs); + BLOCK_INPUT; + gr = getgrgid (gid); + UNBLOCK_INPUT; + if (gr) + attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); - status = SYS$PARSE (&fab); - if ((status & 1) == 0) + strcpy (fn, procfn); + procfn_end = fn + strlen (fn); + strcpy (procfn_end, "/stat"); + fd = emacs_open (fn, O_RDONLY, 0); + if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof(procbuf) - 1)) > 0) { - errno = EVMSERR; - vaxc$errno = status; - return -1; - } + procbuf[nread] = '\0'; + p = procbuf; - nam.nam$w_fid[0] = fid[0]; - nam.nam$w_fid[1] = fid[1]; - nam.nam$w_fid[2] = fid[2]; + p = strchr (p, '('); + if (p != NULL) + { + q = strrchr (p + 1, ')'); + /* comm */ + if (q != NULL) + { + cmd = p + 1; + cmdsize = q - cmd; + } + } + else + q = NULL; + if (cmd == NULL) + { + cmd = "???"; + cmdsize = 3; + } + /* Command name is encoded in locale-coding-system; decode it. */ + cmd_str = make_unibyte_string (cmd, cmdsize); + decoded_cmd = code_convert_string_norecord (cmd_str, + Vlocale_coding_system, 0); + attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs); - nam.nam$l_esa = nam.nam$l_name; - nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver; + if (q) + { + EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint; + p = q + 2; + /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */ + sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld", + &c, &ppid, &pgrp, &sess, &tty, &tpgid, + &minflt, &cminflt, &majflt, &cmajflt, + &utime, &stime, &cutime, &cstime, + &priority, &nice, &thcount, &start, &vsize, &rss); + { + char state_str[2]; + + state_str[0] = c; + state_str[1] = '\0'; + tem = build_string (state_str); + attrs = Fcons (Fcons (Qstate, tem), attrs); + } + /* Stops GCC whining about limited range of data type. */ + ppid_eint = ppid; + pgrp_eint = pgrp; + sess_eint = sess; + tpgid_eint = tpgid; + thcount_eint = thcount; + attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs); + attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs); + attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs); + attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs); + attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs); + attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs); + attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs); + attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs); + attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs); + clocks_per_sec = sysconf (_SC_CLK_TCK); + if (clocks_per_sec < 0) + clocks_per_sec = 100; + attrs = Fcons (Fcons (Qutime, + ltime_from_jiffies (utime, clocks_per_sec)), + attrs); + attrs = Fcons (Fcons (Qstime, + ltime_from_jiffies (stime, clocks_per_sec)), + attrs); + attrs = Fcons (Fcons (Qtime, + ltime_from_jiffies (stime+utime, clocks_per_sec)), + attrs); + attrs = Fcons (Fcons (Qcutime, + ltime_from_jiffies (cutime, clocks_per_sec)), + attrs); + attrs = Fcons (Fcons (Qcstime, + ltime_from_jiffies (cstime, clocks_per_sec)), + attrs); + attrs = Fcons (Fcons (Qctime, + ltime_from_jiffies (cstime+cutime, clocks_per_sec)), + attrs); + attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs); + attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs); + attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs); + EMACS_GET_TIME (tnow); + get_up_time (&sec, &usec); + EMACS_SET_SECS (telapsed, sec); + EMACS_SET_USECS (telapsed, usec); + EMACS_SUB_TIME (tboot, tnow, telapsed); + time_from_jiffies (start, clocks_per_sec, &sec, &usec); + EMACS_SET_SECS (tstart, sec); + EMACS_SET_USECS (tstart, usec); + EMACS_ADD_TIME (tstart, tboot, tstart); + attrs = Fcons (Fcons (Qstart, + list3 (make_number + ((EMACS_SECS (tstart) >> 16) & 0xffff), + make_number + (EMACS_SECS (tstart) & 0xffff), + make_number + (EMACS_USECS (tstart)))), + attrs); + attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs); + attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs); + EMACS_SUB_TIME (telapsed, tnow, tstart); + attrs = Fcons (Fcons (Qetime, + list3 (make_number + ((EMACS_SECS (telapsed) >> 16) & 0xffff), + make_number + (EMACS_SECS (telapsed) & 0xffff), + make_number + (EMACS_USECS (telapsed)))), + attrs); + time_from_jiffies (utime + stime, clocks_per_sec, &sec, &usec); + pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0); + if (pcpu > 1.0) + pcpu = 1.0; + attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs); + pmem = 4.0 * 100 * rss / procfs_get_total_memory (); + if (pmem > 100) + pmem = 100; + attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs); + } + } + if (fd >= 0) + emacs_close (fd); - status = SYS$ENTER (&fab); - if ((status & 1) == 0) + /* args */ + strcpy (procfn_end, "/cmdline"); + fd = emacs_open (fn, O_RDONLY, 0); + if (fd >= 0) { - errno = EVMSERR; - vaxc$errno = status; - return -1; + for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++) + { + if (isspace (c) || c == '\\') + cmdline_size++; /* for later quoting, see below */ + } + if (cmdline_size) + { + cmdline = xmalloc (cmdline_size + 1); + lseek (fd, 0L, SEEK_SET); + cmdline[0] = '\0'; + if ((nread = read (fd, cmdline, cmdline_size)) >= 0) + cmdline[nread++] = '\0'; + else + { + /* Assigning zero to `nread' makes us skip the following + two loops, assign zero to cmdline_size, and enter the + following `if' clause that handles unknown command + lines. */ + nread = 0; + } + /* We don't want trailing null characters. */ + for (p = cmdline + nread - 1; p > cmdline && !*p; p--) + nread--; + for (p = cmdline; p < cmdline + nread; p++) + { + /* Escape-quote whitespace and backslashes. */ + if (isspace (*p) || *p == '\\') + { + memmove (p + 1, p, nread - (p - cmdline)); + nread++; + *p++ = '\\'; + } + else if (*p == '\0') + *p = ' '; + } + cmdline_size = nread; + } + if (!cmdline_size) + { + if (!cmd) + cmd = "???"; + if (!cmdsize) + cmdsize = strlen (cmd); + cmdline_size = cmdsize + 2; + cmdline = xmalloc (cmdline_size + 1); + strcpy (cmdline, "["); + strcat (strncat (cmdline, cmd, cmdsize), "]"); + } + emacs_close (fd); + /* Command line is encoded in locale-coding-system; decode it. */ + cmd_str = make_unibyte_string (cmdline, cmdline_size); + decoded_cmd = code_convert_string_norecord (cmd_str, + Vlocale_coding_system, 0); + xfree (cmdline); + attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs); } - return 0; + UNGCPRO; + return attrs; } -void -croak (badfunc) - char *badfunc; -{ - printf ("%s not yet implemented\r\n", badfunc); - reset_sys_modes (); - exit (1); -} +#elif defined (SOLARIS2) && defined (HAVE_PROCFS) -long -random () -{ - /* Arrange to return a range centered on zero. */ - return rand () - (1 << 30); -} +/* The header does not like to be included if _LP64 is defined and + __FILE_OFFSET_BITS == 64. This is an ugly workaround that. */ +#if !defined (_LP64) && defined (_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) +#define PROCFS_FILE_OFFSET_BITS_HACK 1 +#undef _FILE_OFFSET_BITS +#else +#define PROCFS_FILE_OFFSET_BITS_HACK 0 +#endif -void -srandom (seed) -{ - srand (seed); -} -#endif /* VMS */ - -#ifdef AIXHFT +#include -/* Called from init_sys_modes. */ -void -hft_init () -{ - int junk; +#if PROCFS_FILE_OFFSET_BITS_HACK == 1 +#define _FILE_OFFSET_BITS 64 +#endif /* PROCFS_FILE_OFFSET_BITS_HACK == 1 */ - /* If we're not on an HFT we shouldn't do any of this. We determine - if we are on an HFT by trying to get an HFT error code. If this - call fails, we're not on an HFT. */ -#ifdef IBMR2AIX - if (ioctl (0, HFQERROR, &junk) < 0) - return; -#else /* not IBMR2AIX */ - if (ioctl (0, HFQEIO, 0) < 0) - return; -#endif /* not IBMR2AIX */ - - /* On AIX the default hft keyboard mapping uses backspace rather than delete - as the rubout key's ASCII code. Here this is changed. The bug is that - there's no way to determine the old mapping, so in reset_sys_modes - we need to assume that the normal map had been present. Of course, this - code also doesn't help if on a terminal emulator which doesn't understand - HFT VTD's. */ - { - struct hfbuf buf; - struct hfkeymap keymap; - - buf.hf_bufp = (char *)&keymap; - buf.hf_buflen = sizeof (keymap); - keymap.hf_nkeys = 2; - keymap.hfkey[0].hf_kpos = 15; - keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE; -#ifdef IBMR2AIX - keymap.hfkey[0].hf_keyidh = '<'; -#else /* not IBMR2AIX */ - keymap.hfkey[0].hf_page = '<'; -#endif /* not IBMR2AIX */ - keymap.hfkey[0].hf_char = 127; - keymap.hfkey[1].hf_kpos = 15; - keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT; -#ifdef IBMR2AIX - keymap.hfkey[1].hf_keyidh = '<'; -#else /* not IBMR2AIX */ - keymap.hfkey[1].hf_page = '<'; -#endif /* not IBMR2AIX */ - keymap.hfkey[1].hf_char = 127; - hftctl (0, HFSKBD, &buf); - } - /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly - at times. */ - line_ins_del_ok = char_ins_del_ok = 0; -} +Lisp_Object +system_process_attributes (Lisp_Object pid) +{ + char procfn[PATH_MAX], fn[PATH_MAX]; + struct stat st; + struct passwd *pw; + struct group *gr; + char *procfn_end; + struct psinfo pinfo; + int fd; + ssize_t nread; + int proc_id, uid, gid; + Lisp_Object attrs = Qnil; + Lisp_Object decoded_cmd, tem; + struct gcpro gcpro1, gcpro2; + EMACS_INT uid_eint, gid_eint; + + CHECK_NUMBER_OR_FLOAT (pid); + proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid); + sprintf (procfn, "/proc/%u", proc_id); + if (stat (procfn, &st) < 0) + return attrs; + + GCPRO2 (attrs, decoded_cmd); + + /* euid egid */ + uid = st.st_uid; + /* Use of EMACS_INT stops GCC whining about limited range of data type. */ + uid_eint = uid; + attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs); + BLOCK_INPUT; + pw = getpwuid (uid); + UNBLOCK_INPUT; + if (pw) + attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); -/* Reset the rubout key to backspace. */ + gid = st.st_gid; + gid_eint = gid; + attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs); + BLOCK_INPUT; + gr = getgrgid (gid); + UNBLOCK_INPUT; + if (gr) + attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); -void -hft_reset () -{ - struct hfbuf buf; - struct hfkeymap keymap; - int junk; + strcpy (fn, procfn); + procfn_end = fn + strlen (fn); + strcpy (procfn_end, "/psinfo"); + fd = emacs_open (fn, O_RDONLY, 0); + if (fd >= 0 + && (nread = read (fd, (char*)&pinfo, sizeof(struct psinfo)) > 0)) + { + attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (pinfo.pr_ppid)), attrs); + attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pinfo.pr_pgid)), attrs); + attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (pinfo.pr_sid)), attrs); -#ifdef IBMR2AIX - if (ioctl (0, HFQERROR, &junk) < 0) - return; -#else /* not IBMR2AIX */ - if (ioctl (0, HFQEIO, 0) < 0) - return; -#endif /* not IBMR2AIX */ - - buf.hf_bufp = (char *)&keymap; - buf.hf_buflen = sizeof (keymap); - keymap.hf_nkeys = 2; - keymap.hfkey[0].hf_kpos = 15; - keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE; -#ifdef IBMR2AIX - keymap.hfkey[0].hf_keyidh = '<'; -#else /* not IBMR2AIX */ - keymap.hfkey[0].hf_page = '<'; -#endif /* not IBMR2AIX */ - keymap.hfkey[0].hf_char = 8; - keymap.hfkey[1].hf_kpos = 15; - keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT; -#ifdef IBMR2AIX - keymap.hfkey[1].hf_keyidh = '<'; -#else /* not IBMR2AIX */ - keymap.hfkey[1].hf_page = '<'; -#endif /* not IBMR2AIX */ - keymap.hfkey[1].hf_char = 8; - hftctl (0, HFSKBD, &buf); -} + { + char state_str[2]; + state_str[0] = pinfo.pr_lwp.pr_sname; + state_str[1] = '\0'; + tem = build_string (state_str); + attrs = Fcons (Fcons (Qstate, tem), attrs); + } -#endif /* AIXHFT */ + /* FIXME: missing Qttyname. psinfo.pr_ttydev is a dev_t, + need to get a string from it. */ -#ifdef USE_DL_STUBS + /* FIXME: missing: Qtpgid */ -/* These are included on Sunos 4.1 when we do not use shared libraries. - X11 libraries may refer to these functions but (we hope) do not - actually call them. */ + /* FIXME: missing: + Qminflt + Qmajflt + Qcminflt + Qcmajflt -void * -dlopen () -{ - return 0; -} + Qutime + Qcutime + Qstime + Qcstime + Are they available? */ -void * -dlsym () -{ - return 0; -} + attrs = Fcons (Fcons (Qtime, + list3 (make_number (pinfo.pr_time.tv_sec >> 16), + make_number (pinfo.pr_time.tv_sec & 0xffff), + make_number (pinfo.pr_time.tv_nsec))), + attrs); -int -dlclose () -{ - return -1; -} + attrs = Fcons (Fcons (Qctime, + list3 (make_number (pinfo.pr_ctime.tv_sec >> 16), + make_number (pinfo.pr_ctime.tv_sec & 0xffff), + make_number (pinfo.pr_ctime.tv_nsec))), + attrs); -#endif /* USE_DL_STUBS */ - -#ifndef BSTRING + attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs); + attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs); + attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs); -#ifndef bzero + attrs = Fcons (Fcons (Qstart, + list3 (make_number (pinfo.pr_start.tv_sec >> 16), + make_number (pinfo.pr_start.tv_sec & 0xffff), + make_number (pinfo.pr_start.tv_nsec))), + attrs); + attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs); + attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs); -void -bzero (b, length) - register char *b; - register int length; -{ -#ifdef VMS - short zero = 0; - long max_str = 65535; - - while (length > max_str) { - (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b); - length -= max_str; - b += max_str; - } - max_str = length; - (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b); -#else - while (length-- > 0) - *b++ = 0; -#endif /* not VMS */ -} + /* pr_pctcpu and pr_pctmem are encoded as a fixed point 16 bit number in [0 ... 1]. */ + attrs = Fcons (Fcons (Qpcpu, (pinfo.pr_pctcpu * 100.0) / (double)0x8000), attrs); + attrs = Fcons (Fcons (Qpmem, (pinfo.pr_pctmem * 100.0) / (double)0x8000), attrs); -#endif /* no bzero */ -#endif /* BSTRING */ + decoded_cmd + = code_convert_string_norecord (make_unibyte_string (pinfo.pr_fname, + strlen (pinfo.pr_fname)), + Vlocale_coding_system, 0); + attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs); + decoded_cmd + = code_convert_string_norecord (make_unibyte_string (pinfo.pr_psargs, + strlen (pinfo.pr_psargs)), + Vlocale_coding_system, 0); + attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs); + } -#if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) -#undef bcopy + if (fd >= 0) + emacs_close (fd); -/* Saying `void' requires a declaration, above, where bcopy is used - and that declaration causes pain for systems where bcopy is a macro. */ -bcopy (b1, b2, length) - register char *b1; - register char *b2; - register int length; -{ -#ifdef VMS - long max_str = 65535; - - while (length > max_str) { - (void) LIB$MOVC3 (&max_str, b1, b2); - length -= max_str; - b1 += max_str; - b2 += max_str; - } - max_str = length; - (void) LIB$MOVC3 (&length, b1, b2); -#else - while (length-- > 0) - *b2++ = *b1++; -#endif /* not VMS */ + UNGCPRO; + return attrs; } -#endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */ -#ifndef BSTRING -#ifndef bcmp -int -bcmp (b1, b2, length) /* This could be a macro! */ - register char *b1; - register char *b2; - register int length; -{ -#ifdef VMS - struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1}; - struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2}; +/* The WINDOWSNT implementation is on w32.c. + The MSDOS implementation is on dosfns.c. */ +#elif !defined (WINDOWSNT) && !defined (MSDOS) - return STR$COMPARE (&src1, &src2); -#else - while (length-- > 0) - if (*b1++ != *b2++) - return 1; - - return 0; -#endif /* not VMS */ -} -#endif /* no bcmp */ -#endif /* not BSTRING */ - -#ifndef HAVE_STRSIGNAL -char * -strsignal (code) - int code; +Lisp_Object +system_process_attributes (Lisp_Object pid) { - char *signame = 0; + return Qnil; +} - if (0 <= code && code < NSIG) - { -#ifdef VMS - signame = sys_errlist[code]; -#else - /* Cast to suppress warning if the table has const char *. */ - signame = (char *) sys_siglist[code]; -#endif - } +#endif /* !defined (WINDOWSNT) */ - return signame; -} -#endif /* HAVE_STRSIGNAL */ /* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf (do not change this comment) */