/* 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, 2008
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
#endif
+#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#include <grp.h>
+#endif /* HAVE_PWD_H */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif /* HAVE_LIMITS_H */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+
#include "lisp.h"
/* Including stdlib.h isn't necessarily enough to get srandom
declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2. */
#endif
#endif /* not WINDOWSNT */
-/* Does anyone other than VMS need this? */
-#ifndef fwrite
-#define sys_fwrite fwrite
-#else
-#undef fwrite
-#endif
-
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#ifdef HAVE_SETPGID
-#if !defined (USG) || defined (BSD_PGRPS)
+#if !defined (USG)
#undef setpgrp
#define setpgrp setpgid
#endif
#include "msdos.h"
#include <sys/param.h>
-#if __DJGPP__ > 1
extern int etext;
extern unsigned start __asm__ ("start");
#endif
-#endif
-
-#ifndef USE_CRT_DLL
-#ifndef errno
-extern int errno;
-#endif
-#endif
#include <sys/file.h>
#define LPASS8 0
#endif
-static int baud_convert[] =
+static const int baud_convert[] =
{
0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
1800, 2400, 4800, 9600, 19200, 38400
int emacs_ospeed;
-void croak P_ ((char *)) NO_RETURN;
+void croak (char *) NO_RETURN;
/* Temporary used by `sigblock' when defined in terms of signprocmask. */
Any other returned value must be freed with free. This is used
only when get_current_dir_name is not defined on the system. */
char*
-get_current_dir_name ()
+get_current_dir_name (void)
{
char *buf;
char *pwd;
/* Discard pending input on all input descriptors. */
void
-discard_tty_input ()
+discard_tty_input (void)
{
#ifndef WINDOWSNT
struct emacs_tty buf;
\f
/*ARGSUSED*/
void
-set_exclusive_use (fd)
- int fd;
+set_exclusive_use (int fd)
{
#ifdef FIOCLEX
ioctl (fd, FIOCLEX, 0);
\f
#ifndef subprocesses
-wait_without_blocking ()
+void
+wait_without_blocking (void)
{
-#ifdef BSD_SYSTEM
- wait3 (0, WNOHANG | WUNTRACED, 0);
-#else
croak ("wait_without_blocking");
-#endif
synch_process_alive = 0;
}
(at least for bsd). */
SIGTYPE
-wait_for_termination_signal ()
+wait_for_termination_signal (void)
{}
/* Wait for subprocess with process id `pid' to terminate and
make sure it will get eliminated (not remain forever as a zombie) */
void
-wait_for_termination (pid)
- int pid;
+wait_for_termination (int pid)
{
while (1)
{
else
sigpause (SIGEMPTYMASK);
#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
-#ifdef POSIX_SIGNALS /* would this work for GNU/Linux as well? */
+#ifdef WINDOWSNT
+ wait (0);
+ break;
+#else /* not WINDOWSNT */
sigblock (sigmask (SIGCHLD));
errno = 0;
if (kill (pid, 0) == -1 && errno == ESRCH)
}
sigsuspend (&empty_mask);
-#else /* not POSIX_SIGNALS */
-#ifdef HAVE_SYSV_SIGPAUSE
- sighold (SIGCHLD);
- if (0 > kill (pid, 0))
- {
- sigrelse (SIGCHLD);
- break;
- }
- sigpause (SIGCHLD);
-#else /* not HAVE_SYSV_SIGPAUSE */
-#ifdef WINDOWSNT
- wait (0);
- break;
-#else /* not WINDOWSNT */
- if (0 > kill (pid, 0))
- break;
- /* Using sleep instead of pause avoids timing error.
- If the inferior dies just before the sleep,
- we lose just one second. */
- sleep (1);
#endif /* not WINDOWSNT */
-#endif /* not HAVE_SYSV_SIGPAUSE */
-#endif /* not POSIX_SIGNALS */
#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
#else /* not subprocesses */
-#if __DJGPP__ > 1
break;
-#else /* not __DJGPP__ > 1 */
- if (kill (pid, 0) < 0)
- break;
- wait (0);
-#endif /* not __DJGPP__ > 1*/
#endif /* not subprocesses */
}
}
*/
void
-flush_pending_output (channel)
- int channel;
+flush_pending_output (int channel)
{
#ifdef HAVE_TERMIOS
/* If we try this, we get hit with SIGTTIN, because
in Emacs. No padding needed for insertion into an Emacs buffer. */
void
-child_setup_tty (out)
- int out;
+child_setup_tty (int out)
{
#ifndef DOS_NT
struct emacs_tty s;
#endif
s.main.c_oflag &= ~TAB3; /* Disable tab expansion */
s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
- 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 */
s.main.c_cc[VKILL] = CDISABLE; /* disable kill processing */
#endif /* not SIGNALS_VIA_CHARACTERS */
#ifdef AIX
-/* AIX enhanced edit loses NULs, so disable it */
-#ifndef IBMR2AIX
- s.main.c_line = 0;
- s.main.c_iflag &= ~ASCEDIT;
-#endif
/* Also, PTY overloads NUL and BREAK.
don't ignore break, but don't signal either, so it looks like NUL. */
s.main.c_iflag &= ~IGNBRK;
/* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
unconditionally. Then a SIGNALS_VIA_CHARACTERS conditional
would force it to 0377. That looks like duplicated code. */
-#ifndef SIGNALS_VIA_CHARACTERS
- /* QUIT and INTR work better as signals, so disable character forms */
- s.main.c_cc[VQUIT] = CDISABLE;
- s.main.c_cc[VINTR] = CDISABLE;
- s.main.c_lflag &= ~ISIG;
-#endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
- s.main.c_cc[VEOL] = CDISABLE;
s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
#endif /* AIX */
+ /* We used to enable ICANON (and set VEOF to 04), but this leads to
+ problems where process.c wants to send EOFs every once in a while
+ to force the output, which leads to weird effects when the
+ subprocess has disabled ICANON and ends up seeing those spurious
+ extra EOFs. So we don't send EOFs any more in
+ process.c:send_process, and instead we disable ICANON by default,
+ so if a subsprocess sets up ICANON, it's his problem (or the Elisp
+ package that talks to it) to deal with lines that are too long. */
+ s.main.c_lflag &= ~ICANON; /* Disable line editing and eof processing */
+ s.main.c_cc[VMIN] = 1;
+ s.main.c_cc[VTIME] = 0;
+
#else /* not HAVE_TERMIO */
s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
struct save_signal
{
int code;
- SIGTYPE (*handler) P_ ((int));
+ SIGTYPE (*handler) (int);
};
-static void save_signal_handlers P_ ((struct save_signal *));
-static void restore_signal_handlers P_ ((struct save_signal *));
+static void save_signal_handlers (struct save_signal *);
+static void restore_signal_handlers (struct save_signal *);
/* Suspend the Emacs process; give terminal to its superior. */
void
-sys_suspend ()
+sys_suspend (void)
{
#if defined (SIGTSTP) && !defined (MSDOS)
}
#else /* No SIGTSTP */
-#ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
- ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
- kill (getpid (), SIGQUIT);
-
-#else /* No SIGTSTP or USG_JOBCTRL */
-
/* On a system where suspending is not implemented,
instead fork a subshell and let it talk directly to the terminal
while we wait. */
sys_subshell ();
-#endif /* no USG_JOBCTRL */
#endif /* no SIGTSTP */
}
/* Fork a subshell. */
void
-sys_subshell ()
+sys_subshell (void)
{
#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
int st;
dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
str = (unsigned char *) alloca (SCHARS (dir) + 2);
len = SCHARS (dir);
- bcopy (SDATA (dir), str, len);
+ memcpy (str, SDATA (dir), len);
if (str[len - 1] != '/') str[len++] = '/';
str[len] = 0;
xyzzy:
#ifdef DOS_NT
pid = 0;
-#if __DJGPP__ > 1
save_signal_handlers (saved_handlers);
synch_process_alive = 1;
-#endif /* __DJGPP__ > 1 */
#else
pid = vfork ();
if (pid == -1)
}
/* Do this now if we did not do it before. */
-#if !defined (MSDOS) || __DJGPP__ == 1
+#ifndef MSDOS
save_signal_handlers (saved_handlers);
synch_process_alive = 1;
#endif
}
static void
-save_signal_handlers (saved_handlers)
- struct save_signal *saved_handlers;
+save_signal_handlers (struct save_signal *saved_handlers)
{
while (saved_handlers->code)
{
saved_handlers->handler
- = (SIGTYPE (*) P_ ((int))) signal (saved_handlers->code, SIG_IGN);
+ = (SIGTYPE (*) (int)) signal (saved_handlers->code, SIG_IGN);
saved_handlers++;
}
}
static void
-restore_signal_handlers (saved_handlers)
- struct save_signal *saved_handlers;
+restore_signal_handlers (struct save_signal *saved_handlers)
{
while (saved_handlers->code)
{
int old_fcntl_flags[MAXDESC];
void
-init_sigio (fd)
- int fd;
+init_sigio (int fd)
{
#ifdef FASYNC
old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
}
void
-reset_sigio (fd)
- int fd;
+reset_sigio (int fd)
{
#ifdef FASYNC
fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
/* XXX Yeah, but you need it for SIGIO, don't you? */
void
-request_sigio ()
+request_sigio (void)
{
if (noninteractive)
return;
void
unrequest_sigio (void)
-{
+{
if (noninteractive)
return;
#ifndef MSDOS
void
-request_sigio ()
+request_sigio (void)
{
if (noninteractive || read_socket_hook)
return;
}
void
-unrequest_sigio ()
+unrequest_sigio (void)
{
if (noninteractive || read_socket_hook)
return;
#endif /* FASYNC */
#endif /* F_SETFL */
#endif /* SIGIO */
-\f
-/* Saving and restoring the process group of Emacs's terminal. */
-
-#ifdef BSD_PGRPS
-
-/* The process group of which Emacs was a member when it initially
- started.
-
- If Emacs was in its own process group (i.e. inherited_pgroup ==
- getpid ()), then we know we're running under a shell with job
- control (Emacs would never be run as part of a pipeline).
- Everything is fine.
-
- If Emacs was not in its own process group, then we know we're
- running under a shell (or a caller) that doesn't know how to
- separate itself from Emacs (like sh). Emacs must be in its own
- process group in order to receive SIGIO correctly. In this
- situation, we put ourselves in our own pgroup, forcibly set the
- tty's pgroup to our pgroup, and make sure to restore and reinstate
- 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.
-
- 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 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 (fd, &me); /* XXX This only works on the controlling tty. */
- setpgrp (0, me);
-}
-
-/* Set the tty to our original foreground group. */
-static void
-widen_foreground_group (int fd)
-{
- if (inherited_pgroup != getpid ())
- EMACS_SET_TTY_PGRP (fd, &inherited_pgroup);
- setpgrp (0, inherited_pgroup);
-}
-
-#endif /* BSD_PGRPS */
\f
/* Getting and setting emacs_tty structures. */
Return zero if all's well, or -1 if we ran into an error we
couldn't deal with. */
int
-emacs_get_tty (fd, settings)
- int fd;
- struct emacs_tty *settings;
+emacs_get_tty (int fd, struct emacs_tty *settings)
{
/* Retrieve the primary parameters - baud rate, character size, etcetera. */
#ifdef HAVE_TCATTR
/* We have those nifty POSIX tcmumbleattr functions. */
- bzero (&settings->main, sizeof (settings->main));
+ memset (&settings->main, 0, sizeof (settings->main));
if (tcgetattr (fd, &settings->main) < 0)
return -1;
Return 0 if all went well, and -1 if anything failed. */
int
-emacs_set_tty (fd, settings, flushp)
- int fd;
- struct emacs_tty *settings;
- int flushp;
+emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
{
/* Set the primary parameters - baud rate, character size, etcetera. */
#ifdef HAVE_TCATTR
{
struct termios new;
- bzero (&new, sizeof (new));
+ memset (&new, 0, sizeof (new));
/* Get the current settings, and see if they're what we asked for. */
tcgetattr (fd, &new);
/* We cannot use memcmp on the whole structure here because under
/* Initialize the terminal mode on the given tty device. */
void
-init_sys_modes (tty_out)
- struct tty_display_info *tty_out;
+init_sys_modes (struct tty_display_info *tty_out)
{
struct emacs_tty tty;
if (!tty_out->output)
return; /* The tty is suspended. */
-
-#ifdef BSD_PGRPS
-#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
- narrow_foreground_group (fileno (tty_out->input));
-#endif
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 = *tty_out->old_tty;
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
tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
of C-z */
#endif /* VSWTCH */
-
+
#if defined (__mips__) || defined (HAVE_TCATTR)
#ifdef VSUSP
tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
#endif /* mips or HAVE_TCATTR */
#ifdef AIX
-#ifndef IBMR2AIX
- /* 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;
-#endif /* IBMR2AIX */
if (tty_out->flow_control)
{
#ifdef VSTART
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 */
if (tty_out->term_initted && no_redraw_on_reenter)
{
- /* XXX This seems wrong on multi-tty. */
- if (display_completed)
- direct_output_forward_char (0);
+ /* We used to call "direct_output_forward_char(0)" here,
+ but it's not clear why, since it may not do anything anyway. */
}
else
{
to HEIGHT and WIDTH. This is used mainly with ptys. */
int
-set_window_size (fd, height, width)
- int fd, height, width;
+set_window_size (int fd, int height, int width)
{
#ifdef TIOCSWINSZ
bottom of the frame, turn off interrupt-driven I/O, etc. */
void
-reset_sys_modes (tty_out)
- struct tty_display_info *tty_out;
+reset_sys_modes (struct tty_display_info *tty_out)
{
if (noninteractive)
{
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)
{
{ /* 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);
dos_ttcooked ();
#endif
-#ifdef BSD_PGRPS
- widen_foreground_group (fileno (tty_out->input));
-#endif
}
\f
#ifdef HAVE_PTYS
/* Set up the proper status flags for use of a pty. */
void
-setup_pty (fd)
- int fd;
+setup_pty (int fd)
{
/* I'm told that TOICREMOTE does not mean control chars
"can't be sent" but rather that they don't have
#if !(defined (__NetBSD__) && defined (__ELF__))
#ifndef HAVE_TEXT_START
char *
-start_of_text ()
+start_of_text (void)
{
#ifdef TEXT_START
return ((char *) TEXT_START);
#ifndef start_of_data
char *
-start_of_data ()
+start_of_data (void)
{
#ifdef DATA_START
return ((char *) DATA_START);
#endif /* TRY_AGAIN */
void
-init_system_name ()
+init_system_name (void)
{
#ifndef HAVE_GETHOSTNAME
struct utsname uts;
struct addrinfo hints;
int ret;
- memset (&hints, 0, sizeof(hints));
+ memset (&hints, 0, sizeof (hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
int read_alarm_should_throw;
-SIGTYPE
-select_alarm ()
+void
+select_alarm (int ignore)
{
select_alarmed = 1;
signal (SIGALRM, SIG_IGN);
#ifndef WINDOWSNT
/* Only rfds are checked. */
int
-sys_select (nfds, rfds, wfds, efds, timeout)
- int nfds;
- SELECT_TYPE *rfds, *wfds, *efds;
- EMACS_TIME *timeout;
+sys_select (int nfds,
+ SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
+ EMACS_TIME *timeout)
{
/* XXX This needs to be updated for multi-tty support. Is there
- anybody who needs to emulate select these days? */
+ anybody who needs to emulate select these days? */
int ravail = 0;
SELECT_TYPE orfds;
int timeoutval;
waiting for at least one character. */
void
-read_input_waiting ()
+read_input_waiting (void)
{
/* XXX This needs to be updated for multi-tty support. Is there
anybody who needs to emulate select these days? */
/* POSIX signals support - DJB */
/* Anyone with POSIX signals should have ANSI C declarations */
-#ifdef POSIX_SIGNALS
-
sigset_t empty_mask, full_mask;
+#ifndef WINDOWSNT
+
signal_handler_t
sys_signal (int signal_number, signal_handler_t action)
{
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)
# endif
return (old_action.sa_handler);
}
+#endif /* WINDOWSNT */
+
#ifndef __GNUC__
/* If we're compiling with GCC, we don't need this function, since it
can be written as a macro. */
return (old_mask);
}
-#endif /* POSIX_SIGNALS */
\f
#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
static char *my_sys_siglist[NSIG];
#endif
void
-init_signals ()
+init_signals (void)
{
-#ifdef POSIX_SIGNALS
sigemptyset (&empty_mask);
sigfillset (&full_mask);
-#endif
#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
if (! initialized)
#endif /* !RAND_BITS */
void
-seed_random (arg)
- long arg;
+seed_random (long int arg)
{
#ifdef HAVE_RANDOM
srandom ((unsigned int)arg);
* This suffices even for a 64-bit architecture with a 15-bit rand.
*/
long
-get_random ()
+get_random (void)
{
long val = random ();
#if VALBITS > RAND_BITS
#endif /* ! HAVE_STRERROR */
\f
int
-emacs_open (path, oflag, mode)
- const char *path;
- int oflag, mode;
+emacs_open (const char *path, int oflag, int mode)
{
register int rtnval;
}
int
-emacs_close (fd)
- int fd;
+emacs_close (int fd)
{
int did_retry = 0;
register int rtnval;
}
int
-emacs_read (fildes, buf, nbyte)
- int fildes;
- char *buf;
- unsigned int nbyte;
+emacs_read (int fildes, char *buf, unsigned int nbyte)
{
register int rtnval;
}
int
-emacs_write (fildes, buf, nbyte)
- int fildes;
- const char *buf;
- unsigned int nbyte;
+emacs_write (int fildes, const char *buf, unsigned int nbyte)
{
register int rtnval, bytes_written;
#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 ();
- if (pending_atimers)
- do_pending_atimers ();
+ process_pending_signals ();
#endif
continue;
}
#ifndef HAVE_GETWD
char *
-getwd (pathname)
- char *pathname;
+getwd (char *pathname)
{
char *npath, *spath;
- extern char *getcwd ();
+ extern char *getcwd (char *, size_t);
BLOCK_INPUT; /* getcwd uses malloc */
spath = npath = getcwd ((char *) 0, MAXPATHLEN);
#ifndef HAVE_RENAME
-rename (from, to)
- const char *from;
- const char *to;
+int
+rename (const char *from, const char *to)
{
if (access (from, 0) == 0)
{
/* HPUX curses library references perror, but as far as we know
it won't be called. Anyway this definition will do for now. */
-perror ()
+void
+perror (void)
{
}
#endif /* HPUX and not HAVE_PERROR */
* until we are, then close the unsuccessful ones.
*/
-dup2 (oldd, newd)
- int oldd;
- int newd;
+int
+dup2 (int oldd, int newd)
{
register int fd, ret;
/* ARGSUSED */
int
-gettimeofday (tp, tzp)
- struct timeval *tp;
- struct timezone *tzp;
+gettimeofday (struct timeval *tp, struct timezone *tzp)
{
- extern long time ();
+ extern long time (long);
tp->tv_sec = time ((long *)0);
tp->tv_usec = 0;
*/
void
-croak (badfunc)
- char *badfunc;
+croak (char *badfunc)
{
printf ("%s not yet implemented\r\n", badfunc);
reset_all_sys_modes ();
int rtnval;
rtnval = emacs_close (dirp->dd_fd);
-
- /* 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 (SOLARIS2)
- xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
-#endif
xfree ((char *) dirp);
return rtnval;
\f
int
-set_file_times (filename, atime, mtime)
- const char *filename;
- EMACS_TIME atime, mtime;
+set_file_times (const char *filename, EMACS_TIME atime, EMACS_TIME mtime)
{
#ifdef HAVE_UTIMES
struct timeval tv[2];
/*
* Make a directory.
*/
-#ifdef MKDIR_PROTOTYPE
-MKDIR_PROTOTYPE
-#else
int
-mkdir (dpath, dmode)
- char *dpath;
- int dmode;
-#endif
+mkdir (char *dpath, int dmode)
{
int cpid, status, fd;
struct stat statbuf;
#ifndef HAVE_RMDIR
int
-rmdir (dpath)
- char *dpath;
+rmdir (char *dpath)
{
int cpid, status, fd;
struct stat statbuf;
#endif /* !HAVE_RMDIR */
\f
-#ifndef BSTRING
-
-#ifndef bzero
-
-void
-bzero (b, length)
- register char *b;
- register int length;
+#ifndef HAVE_MEMSET
+void *
+memset (void *b, int n, size_t length)
{
+ unsigned char *p = b;
while (length-- > 0)
- *b++ = 0;
+ *p++ = n;
+ return b;
}
+#endif /* !HAVE_MEMSET */
-#endif /* no bzero */
-#endif /* BSTRING */
-
-#if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
-#undef bcopy
-
-/* 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;
+#ifndef HAVE_MEMCPY
+void *
+memcpy (void *b1, void *b2, size_t length)
{
+ unsigned char *p1 = b1, *p2 = b2;
while (length-- > 0)
- *b2++ = *b1++;
+ *p1++ = *p2++;
+ return b1;
+}
+#endif /* !HAVE_MEMCPY */
+
+#ifndef HAVE_MEMMOVE
+void *
+memmove (void *b1, void *b2, size_t length)
+{
+ unsigned char *p1 = b1, *p2 = b2;
+ if (p1 < p2 || p1 >= p2 + length)
+ while (length-- > 0)
+ *p1++ = *p2++;
+ else
+ {
+ p1 += length;
+ p2 += length;
+ while (length-- > 0)
+ *--p1 = *--p2;
+ }
+ return b1;
}
-#endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
+#endif /* !HAVE_MEMCPY */
-#ifndef BSTRING
-#ifndef bcmp
+#ifndef HAVE_MEMCMP
int
-bcmp (b1, b2, length) /* This could be a macro! */
- register char *b1;
- register char *b2;
- register int length;
+memcmp (void *b1, void *b2, size_t length)
{
+ unsigned char *p1 = b1, *p2 = b2;
while (length-- > 0)
- if (*b1++ != *b2++)
- return 1;
-
+ if (*p1++ != *p2++)
+ return p1[-1] < p2[-1] ? -1 : 1;
return 0;
}
-#endif /* no bcmp */
-#endif /* not BSTRING */
+#endif /* !HAVE_MEMCMP */
\f
#ifndef HAVE_STRSIGNAL
char *
-strsignal (code)
- int code;
+strsignal (int code)
{
char *signame = 0;
\f
#ifdef HAVE_TERMIOS
/* For make-serial-process */
-int serial_open (char *port)
+int
+serial_open (char *port)
{
int fd = -1;
#if !defined (HAVE_CFMAKERAW)
/* Workaround for targets which are missing cfmakeraw. */
/* Pasted from man page. */
-static void cfmakeraw (struct termios *termios_p)
+static void
+cfmakeraw (struct termios *termios_p)
{
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
#if !defined (HAVE_CFSETSPEED)
/* Workaround for targets which are missing cfsetspeed. */
-static int cfsetspeed (struct termios *termios_p, speed_t vitesse)
+static int
+cfsetspeed (struct termios *termios_p, speed_t vitesse)
{
return (cfsetispeed (termios_p, vitesse)
+ cfsetospeed (termios_p, vitesse));
/* For serial-process-configure */
void
serial_configure (struct Lisp_Process *p,
- Lisp_Object contact)
+ Lisp_Object contact)
{
Lisp_Object childp2 = Qnil;
Lisp_Object tem = Qnil;
attr.c_cflag |= CLOCAL;
#endif
#if defined (CREAD)
- attr.c_cflag | CREAD;
+ attr.c_cflag |= CREAD;
#endif
/* Configure speed. */
CHECK_NUMBER (tem);
if (XINT (tem) != 7 && XINT (tem) != 8)
error (":bytesize must be nil (8), 7, or 8");
- summary[0] = XINT(tem) + '0';
+ summary[0] = XINT (tem) + '0';
#if defined (CSIZE) && defined (CS7) && defined (CS8)
attr.c_cflag &= ~CSIZE;
attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
}
#endif /* TERMIOS */
+\f
+/* System depended enumeration of and access to system processes a-la ps(1). */
+
+#ifdef HAVE_PROCFS
+
+/* Process enumeration and access via /proc. */
+
+Lisp_Object
+list_system_processes (void)
+{
+ Lisp_Object procdir, match, proclist, next;
+ struct gcpro gcpro1, gcpro2;
+ register Lisp_Object tail;
+
+ 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)
+ {
+ next = XCDR (tail);
+ XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
+ }
+ UNGCPRO;
+
+ /* directory_files_internal returns the files in reverse order; undo
+ that. */
+ proclist = Fnreverse (proclist);
+ return proclist;
+}
+
+/* The WINDOWSNT implementation is in w32.c.
+ The MSDOS implementation is in dosfns.c. */
+#elif !defined (WINDOWSNT) && !defined (MSDOS)
+
+Lisp_Object
+list_system_processes (void)
+{
+ return Qnil;
+}
+
+#endif /* !defined (WINDOWSNT) */
+
+#ifdef GNU_LINUX
+static void
+time_from_jiffies (unsigned long long tval, long hz,
+ time_t *sec, unsigned *usec)
+{
+ unsigned long long ullsec;
+
+ *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
+ *usec = tval / (hz / 1000000);
+}
+
+static Lisp_Object
+ltime_from_jiffies (unsigned long long tval, long hz)
+{
+ time_t sec;
+ unsigned usec;
+
+ time_from_jiffies (tval, hz, &sec, &usec);
+
+ return list3 (make_number ((sec >> 16) & 0xffff),
+ make_number (sec & 0xffff),
+ make_number (usec));
+}
+
+static void
+get_up_time (time_t *sec, unsigned *usec)
+{
+ FILE *fup;
+
+ *sec = *usec = 0;
+
+ BLOCK_INPUT;
+ fup = fopen ("/proc/uptime", "r");
+
+ if (fup)
+ {
+ double uptime, idletime;
+
+ /* 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;
+}
+
+#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
+#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
+
+static Lisp_Object
+procfs_ttyname (int rdev)
+{
+ FILE *fdev = NULL;
+ char name[PATH_MAX];
+
+ BLOCK_INPUT;
+ fdev = fopen ("/proc/tty/drivers", "r");
+
+ if (fdev)
+ {
+ unsigned major;
+ unsigned long minor_beg, minor_end;
+ char minor[25]; /* 2 32-bit numbers + dash */
+ char *endp;
+
+ 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 (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
+ {
+ sprintf (name + strlen (name), "%u", MINOR (rdev));
+ break;
+ }
+ }
+ }
+ fclose (fdev);
+ }
+ UNBLOCK_INPUT;
+ return build_string (name);
+}
+
+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");
+
+ if (fmem)
+ {
+ unsigned long entry_value;
+ char entry_name[20]; /* the longest I saw is 13+1 */
+
+ 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;
+}
+
+Lisp_Object
+system_process_attributes (Lisp_Object pid)
+{
+ 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;
+ 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/%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);
+
+ 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);
+
+ 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)
+ {
+ procbuf[nread] = '\0';
+ p = procbuf;
+
+ 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);
+
+ 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);
+
+ /* args */
+ strcpy (procfn_end, "/cmdline");
+ fd = emacs_open (fn, O_RDONLY, 0);
+ if (fd >= 0)
+ {
+ 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);
+ }
+
+ UNGCPRO;
+ return attrs;
+}
+
+#elif defined (SOLARIS2) && defined (HAVE_PROCFS)
+
+/* The <procfs.h> 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
+
+#include <procfs.h>
+
+#if PROCFS_FILE_OFFSET_BITS_HACK == 1
+#define _FILE_OFFSET_BITS 64
+#endif /* PROCFS_FILE_OFFSET_BITS_HACK == 1 */
+
+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);
+
+ 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);
+
+ 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);
+
+ {
+ 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);
+ }
+
+ /* FIXME: missing Qttyname. psinfo.pr_ttydev is a dev_t,
+ need to get a string from it. */
+
+ /* FIXME: missing: Qtpgid */
+
+ /* FIXME: missing:
+ Qminflt
+ Qmajflt
+ Qcminflt
+ Qcmajflt
+
+ Qutime
+ Qcutime
+ Qstime
+ Qcstime
+ Are they available? */
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ /* 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);
+
+ 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 (fd >= 0)
+ emacs_close (fd);
+
+ UNGCPRO;
+ return attrs;
+}
+
+/* The WINDOWSNT implementation is in w32.c.
+ The MSDOS implementation is in dosfns.c. */
+#elif !defined (WINDOWSNT) && !defined (MSDOS)
+
+Lisp_Object
+system_process_attributes (Lisp_Object pid)
+{
+ return Qnil;
+}
+
+#endif /* !defined (WINDOWSNT) */
+
/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
(do not change this comment) */