/* 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, 2009, 2010, 2011, 2012
+ Copyright (C) 1985-1988, 1993-1995, 1999-2012
Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
-
#include <ctype.h>
#include <signal.h>
#include <stdio.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
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#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. */
+#include <allocator.h>
+#include <careadlinkat.h>
+#include <ignore-value.h>
+#include <utimens.h>
-/* The w32 build defines select stuff in w32.h, which is included by
- sys/select.h (included below). */
-#ifndef WINDOWSNT
+#include "lisp.h"
#include "sysselect.h"
+#include "blockinput.h"
+
+#ifdef BSD_SYSTEM
+#include <sys/param.h>
+#include <sys/sysctl.h>
#endif
-#include "blockinput.h"
+#ifdef __FreeBSD__
+#include <sys/user.h>
+#include <sys/resource.h>
+#include <math.h>
+#endif
#ifdef WINDOWSNT
#define read sys_read
#define write sys_write
#include <windows.h>
-#ifndef NULL
-#define NULL 0
-#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)
-#undef setpgrp
-#define setpgrp setpgid
-#endif
-#endif
-
/* Get SI_SRPC_DOMAIN, if it is available. */
#ifdef HAVE_SYS_SYSTEMINFO_H
#include <sys/systeminfo.h>
#endif
#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
-#include <dos.h>
-#include "dosfns.h"
#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>
-
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
-#ifndef MSDOS
-#include <sys/ioctl.h>
-#endif
#include "systty.h"
#include "syswait.h"
-#if defined (USG)
+#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
#include <memory.h>
-#endif /* USG */
-
-extern int quit_char;
+#endif /* HAVE_SYS_UTSNAME_H */
#include "keyboard.h"
#include "frame.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 <direct.h>
/* In process.h which conflicts with the local copy. */
#include "syssignal.h"
#include "systime.h"
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-#ifndef HAVE_UTIMES
-#ifndef HAVE_STRUCT_UTIMBUF
-/* We want to use utime rather than utimes, but we couldn't find the
- structure declaration. We'll use the traditional one. */
-struct utimbuf {
- long actime;
- long modtime;
-};
-#endif
+static int emacs_get_tty (int, struct emacs_tty *);
+static int emacs_set_tty (int, struct emacs_tty *, int);
+#if defined TIOCNOTTY || defined USG5 || defined CYGWIN
+static _Noreturn void croak (char *);
#endif
-/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
-#ifndef LPASS8
-#define LPASS8 0
+/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */
+#ifndef ULLONG_MAX
+#define ULLONG_MAX TYPE_MAXIMUM (unsigned long long int)
#endif
+/* Declare here, including term.h is problematic on some systems. */
+extern void tputs (const char *, int, int (*)(int));
+
static const int baud_convert[] =
{
0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
1800, 2400, 4800, 9600, 19200, 38400
};
-#ifdef HAVE_SPEED_T
-#include <termios.h>
-#else
-#if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
-#else
-#if defined (HAVE_TERMIOS_H) && defined (GNU_LINUX)
-#include <termios.h>
-#endif
-#endif
-#endif
-
-int emacs_ospeed;
-
-void croak P_ ((char *)) NO_RETURN;
-
-/* Temporary used by `sigblock' when defined in terms of signprocmask. */
-
-SIGMASKTYPE sigprocmask_set;
-
#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
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;
#endif
)
{
- buf = (char *) malloc (strlen (pwd) + 1);
+ buf = malloc (strlen (pwd) + 1);
if (!buf)
return NULL;
strcpy (buf, pwd);
else
{
size_t buf_size = 1024;
- buf = (char *) malloc (buf_size);
+ buf = malloc (buf_size);
if (!buf)
return NULL;
for (;;)
return NULL;
}
buf_size *= 2;
- buf = (char *) realloc (buf, buf_size);
+ buf = realloc (buf, buf_size);
if (!buf)
return NULL;
}
else
{
/* We need MAXPATHLEN here. */
- buf = (char *) malloc (MAXPATHLEN + 1);
+ buf = malloc (MAXPATHLEN + 1);
if (!buf)
return NULL;
if (getwd (buf) == NULL)
/* Discard pending input on all input descriptors. */
void
-discard_tty_input ()
+discard_tty_input (void)
{
#ifndef WINDOWSNT
struct emacs_tty buf;
{
if (tty->input) /* Is the device suspended? */
{
- EMACS_GET_TTY (fileno (tty->input), &buf);
- EMACS_SET_TTY (fileno (tty->input), &buf, 0);
+ emacs_get_tty (fileno (tty->input), &buf);
+ emacs_set_tty (fileno (tty->input), &buf, 0);
}
}
}
void
init_baud_rate (int fd)
{
+ int emacs_ospeed;
+
if (noninteractive)
emacs_ospeed = 0;
else
#ifdef DOS_NT
emacs_ospeed = 15;
#else /* not DOS_NT */
-#ifdef HAVE_TERMIOS
struct termios sg;
sg.c_cflag = B9600;
tcgetattr (fd, &sg);
emacs_ospeed = cfgetospeed (&sg);
-#else /* not TERMIOS */
-#ifdef HAVE_TERMIO
- struct termio sg;
-
- sg.c_cflag = B9600;
-#ifdef HAVE_TCATTR
- tcgetattr (fd, &sg);
-#else
- ioctl (fd, TCGETA, &sg);
-#endif
- emacs_ospeed = sg.c_cflag & CBAUD;
-#else /* neither TERMIOS nor TERMIO */
- struct sgttyb sg;
-
- sg.sg_ospeed = B9600;
- if (ioctl (fd, TIOCGETP, &sg) < 0)
- abort ();
- emacs_ospeed = sg.sg_ospeed;
-#endif /* not HAVE_TERMIO */
-#endif /* not HAVE_TERMIOS */
#endif /* not DOS_NT */
}
}
\f
-/*ARGSUSED*/
-void
-set_exclusive_use (fd)
- int fd;
-{
-#ifdef FIOCLEX
- ioctl (fd, FIOCLEX, 0);
-#endif
- /* Ok to do nothing if this feature does not exist */
-}
-\f
-#ifndef subprocesses
-
-wait_without_blocking ()
-{
-#ifdef BSD_SYSTEM
- wait3 (0, WNOHANG | WUNTRACED, 0);
-#else
- croak ("wait_without_blocking");
-#endif
- synch_process_alive = 0;
-}
-
-#endif /* not subprocesses */
-int wait_debugging; /* Set nonzero to make following function work under dbx
- (at least for bsd). */
+/* Set nonzero to make following function work under dbx
+ (at least for bsd). */
+int wait_debugging EXTERNALLY_VISIBLE;
-SIGTYPE
-wait_for_termination_signal ()
-{}
-
-/* Wait for subprocess with process id `pid' to terminate and
- make sure it will get eliminated (not remain forever as a zombie) */
+#ifndef MSDOS
-void
-wait_for_termination (pid)
- int pid;
+static void
+wait_for_termination_1 (pid_t pid, int interruptible)
{
while (1)
{
-#ifdef subprocesses
-#if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined(__GNU__)
+#if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined (__GNU__)
/* 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. */
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 */
+ if (interruptible)
+ QUIT;
}
}
-#ifdef subprocesses
+/* 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_t pid)
+{
+ wait_for_termination_1 (pid, 0);
+}
+
+/* Like the above, but allow keyboard interruption. */
+void
+interruptible_wait_for_termination (pid_t pid)
+{
+ wait_for_termination_1 (pid, 1);
+}
/*
* flush any pending output
*/
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
- the child's tty belongs to the child's pgrp. */
-#else
-#ifdef TCFLSH
- ioctl (channel, TCFLSH, 1);
-#else
-#ifdef TIOCFLUSH
- int zero = 0;
- /* 3rd arg should be ignored
- but some 4.2 kernels actually want the address of an int
- and nonzero means something different. */
- ioctl (channel, TIOCFLUSH, &zero);
-#endif
-#endif
-#endif
+ /* FIXME: maybe this function should be removed */
}
\f
/* Set up the terminal at the other end of a pseudo-terminal that
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
+#ifndef WINDOWSNT
struct emacs_tty s;
- EMACS_GET_TTY (out, &s);
-
-#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
+ emacs_get_tty (out, &s);
s.main.c_oflag |= OPOST; /* Enable output postprocessing */
s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
#ifdef NLDLY
#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. */
- s.main.c_cc[VEOL] = CDISABLE;
s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
#endif /* AIX */
-#else /* not HAVE_TERMIO */
-
- s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
- | CBREAK | TANDEM);
- s.main.sg_flags |= LPASS8;
- s.main.sg_erase = 0377;
- s.main.sg_kill = 0377;
- s.lmode = LLITOUT | s.lmode; /* Don't strip 8th bit */
-
-#endif /* not HAVE_TERMIO */
-
- EMACS_SET_TTY (out, &s, 0);
-
-#endif /* not DOS_NT */
+ /* We originally enabled ICANON (and set VEOF to 04), and then had
+ process.c send additional EOF chars to flush the output when faced
+ with long lines, but this 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. First we tried to 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. But this disables some features, such as the ability
+ to send EOF signals. So we re-enabled ICANON but there is no
+ more "send eof to flush" going on (which is wrong and unportable
+ in itself). The correct way to handle too much output is to
+ buffer what could not be written and then write it again when
+ select returns ok for writing. This has it own set of
+ problems. Write is now asynchronous, is that a problem? How much
+ do we buffer, and what do we do when that limit is reached? */
+
+ s.main.c_lflag |= ICANON; /* Enable line editing and eof processing */
+ s.main.c_cc[VEOF] = 'D'&037; /* Control-D */
+#if 0 /* These settings only apply to non-ICANON mode. */
+ s.main.c_cc[VMIN] = 1;
+ s.main.c_cc[VTIME] = 0;
+#endif
+
+ emacs_set_tty (out, &s, 0);
+#endif /* not WINDOWSNT */
}
+#endif /* not MSDOS */
-#endif /* subprocesses */
\f
/* Record a signal code and the handler for it. */
struct save_signal
{
int code;
- SIGTYPE (*handler) P_ ((int));
+ void (*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)
/* Fork a subshell. */
void
-sys_subshell ()
+sys_subshell (void)
{
#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
int st;
int pid;
struct save_signal saved_handlers[5];
Lisp_Object dir;
- unsigned char *str = 0;
+ unsigned char *volatile str_volatile = 0;
+ unsigned char *str;
int len;
saved_handlers[0].code = SIGINT;
goto xyzzy;
dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
- str = (unsigned char *) alloca (SCHARS (dir) + 2);
+ str_volatile = str = 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)
if (pid == 0)
{
- char *sh = 0;
+ const char *sh = 0;
#ifdef DOS_NT /* MW, Aug 1993 */
getwd (oldwd);
sh = "sh";
/* Use our buffer's default directory for the subshell. */
- if (str)
- chdir ((char *) str);
-
-#ifdef subprocesses
- close_process_descs (); /* Close Emacs's pipes/ptys */
+ str = str_volatile;
+ if (str && chdir ((char *) str) != 0)
+ {
+#ifndef DOS_NT
+ ignore_value (write (1, "Can't chdir\n", 12));
+ _exit (1);
#endif
+ }
-#ifdef SET_EMACS_PRIORITY
- {
- extern EMACS_INT emacs_priority;
-
- if (emacs_priority < 0)
- nice (-emacs_priority);
- }
-#endif
+ close_process_descs (); /* Close Emacs's pipes/ptys */
#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
{
setenv ("PWD", str, 1);
}
st = system (sh);
- chdir (oldwd);
+ chdir (oldwd); /* FIXME: Do the right thing on chdir failure. */
if (epwd)
putenv (old_pwd); /* restore previous value */
}
#ifdef WINDOWSNT
/* Waits for process completion */
pid = _spawnlp (_P_WAIT, sh, sh, NULL);
- chdir (oldwd);
+ chdir (oldwd); /* FIXME: Do the right thing on chdir failure. */
if (pid == -1)
write (1, "Can't execute subshell", 22);
#else /* not WINDOWSNT */
execlp (sh, sh, (char *) 0);
- write (1, "Can't execute subshell", 22);
+ ignore_value (write (1, "Can't execute subshell", 22));
_exit (1);
#endif /* not WINDOWSNT */
#endif /* not MSDOS */
}
/* 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);
+ = (void (*) (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)
{
{
}
-void
+static void
reset_sigio (int fd)
{
}
#else
#ifdef F_SETFL
-int old_fcntl_flags[MAXDESC];
+static 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;
interrupts_deferred = 0;
}
-void
-reset_sigio (fd)
- int fd;
+static void
+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
+#ifndef DOS_NT
/* 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;
-
-#else
-#ifdef HAVE_TERMIO
- /* The SYSV-style interface? */
- if (ioctl (fd, TCGETA, &settings->main) < 0)
- return -1;
-
-#else
-#ifndef DOS_NT
- /* I give up - I hope you have the BSD ioctls. */
- if (ioctl (fd, TIOCGETP, &settings->main) < 0)
- return -1;
-#endif /* not DOS_NT */
-#endif
-#endif
-
- /* Suivant - Do we have to get struct ltchars data? */
-#ifdef HAVE_LTCHARS
- if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
- return -1;
-#endif
-
- /* How about a struct tchars and a wordful of lmode bits? */
-#ifdef HAVE_TCHARS
- if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
- || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
- return -1;
#endif
/* We have survived the tempest. */
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
+#ifndef DOS_NT
int i;
/* We have those nifty POSIX tcmumbleattr functions.
William J. Smith <wjs@wiis.wang.com> writes:
{
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
else
continue;
}
-
-#else
-#ifdef HAVE_TERMIO
- /* The SYSV-style interface? */
- if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
- return -1;
-
-#else
-#ifndef DOS_NT
- /* I give up - I hope you have the BSD ioctls. */
- if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
- return -1;
-#endif /* not DOS_NT */
-
-#endif
-#endif
-
- /* Suivant - Do we have to get struct ltchars data? */
-#ifdef HAVE_LTCHARS
- if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
- return -1;
-#endif
-
- /* How about a struct tchars and a wordful of lmode bits? */
-#ifdef HAVE_TCHARS
- if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
- || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
- return -1;
#endif
/* We have survived the tempest. */
\f
#ifdef F_SETOWN
-int old_fcntl_owner[MAXDESC];
+static int old_fcntl_owner[MAXDESC];
#endif /* F_SETOWN */
/* This may also be defined in stdio,
char _sobuf[BUFSIZ];
#endif
-#ifdef HAVE_LTCHARS
-static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
-#endif
-#ifdef HAVE_TCHARS
-static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
-#endif
-
/* Initialize the terminal mode on all tty devices that are currently
open. */
/* 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;
+ Lisp_Object terminal;
Vtty_erase_char = Qnil;
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_out->old_tty = xmalloc (sizeof *tty_out->old_tty);
+
+ emacs_get_tty (fileno (tty_out->input), tty_out->old_tty);
tty = *tty_out->old_tty;
-#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
+#if !defined (DOS_NT)
XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
tty.main.c_cflag &= ~PARENB;/* Don't check parity */
}
#endif
- if (tty_out->input == stdin)
+
+ XSETTERMINAL(terminal, tty_out->terminal);
+ if (!NILP (Fcontrolling_tty_p (terminal)))
{
tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
/* Set up C-g for both SIGQUIT and SIGINT.
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. */
+ tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off 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 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[VSTOP] = CDISABLE;
#endif /* VSTOP */
}
-#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.main.c_iflag &= ~IGNBRK;
tty.main.c_iflag &= ~BRKINT;
#endif
-#else /* if not HAVE_TERMIO */
-#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;
#endif /* not DOS_NT */
-#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. */
-#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 (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;
-#endif /* HAVE_LTCHARS */
+
#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
if (!tty_out->term_initted)
internal_terminal_init ();
dos_ttraw (tty_out);
#endif
- EMACS_SET_TTY (fileno (tty_out->input), &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. */
if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
#endif
-#if defined (HAVE_TERMIOS) || defined (HPUX)
+#if !defined (DOS_NT)
#ifdef TCOON
if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
#endif
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
{
{
struct emacs_tty etty;
- EMACS_GET_TTY (fd, &etty);
- return EMACS_TTY_TABS_OK (&etty);
+ emacs_get_tty (fd, &etty);
+#ifndef DOS_NT
+#ifdef TABDLY
+ return ((etty.main.c_oflag & TABDLY) != TAB3);
+#else /* not TABDLY */
+ return 1;
+#endif /* not TABDLY */
+#else /* DOS_NT */
+ return 0;
+#endif /* DOS_NT */
}
\f
/* Get terminal size from system.
void
get_tty_size (int fd, int *widthp, int *heightp)
{
-
-#ifdef TIOCGWINSZ
+#if defined TIOCGWINSZ
/* BSD-style. */
struct winsize size;
*heightp = size.ws_row;
}
-#else
-#ifdef TIOCGSIZE
+#elif defined TIOCGSIZE
/* SunOS - style. */
struct ttysize size;
*heightp = size.ts_lines;
}
-#else
-#ifdef MSDOS
+#elif defined WINDOWSNT
+
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ if (GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info))
+ {
+ *widthp = info.srWindow.Right - info.srWindow.Left + 1;
+ *heightp = info.srWindow.Bottom - info.srWindow.Top + 1;
+ }
+ else
+ *widthp = *heightp = 0;
+
+#elif defined MSDOS
+
*widthp = ScreenCols ();
*heightp = ScreenRows ();
+
#else /* system doesn't know size */
+
*widthp = 0;
*heightp = 0;
+
#endif
-#endif /* not SunOS-style */
-#endif /* not BSD-style */
}
/* Set the logical window size associated with descriptor FD
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);
#endif /* F_SETFL */
if (tty_out->old_tty)
- while (EMACS_SET_TTY (fileno (tty_out->input),
+ while (emacs_set_tty (fileno (tty_out->input),
tty_out->old_tty, 0) < 0 && errno == EINTR)
;
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
Since the latter lossage is more benign, we may as well
lose that way. -- cph */
#ifdef FIONBIO
-#if defined(UNIX98_PTYS)
+#if defined (UNIX98_PTYS)
{
int on = 1;
ioctl (fd, FIONBIO, &on);
}
#endif /* HAVE_PTYS */
\f
-#if !defined(CANNOT_DUMP) || !defined(SYSTEM_MALLOC)
-/* Some systems that cannot dump also cannot implement these. */
-
-/*
- * Return the address of the start of the text segment prior to
- * doing an unexec. After unexec the return value is undefined.
- * See crt0.c for further explanation and _start.
- *
- */
-
-#if !(defined (__NetBSD__) && defined (__ELF__))
-#ifndef HAVE_TEXT_START
-char *
-start_of_text ()
-{
-#ifdef TEXT_START
- return ((char *) TEXT_START);
-#else
- extern int _start ();
- return ((char *) _start);
-#endif /* TEXT_START */
-}
-#endif /* not HAVE_TEXT_START */
-#endif
-
-/*
- * Return the address of the start of the data segment prior to
- * doing an unexec. After unexec the return value is undefined.
- * See crt0.c for further information and definition of data_start.
- *
- * Apparently, on BSD systems this is etext at startup. On
- * USG systems (swapping) this is highly mmu dependent and
- * is also dependent on whether or not the program is running
- * with shared text. Generally there is a (possibly large)
- * gap between end of text and start of data with shared text.
- *
- * On Uniplus+ systems with shared text, data starts at a
- * fixed address. Each port (from a given oem) is generally
- * different, and the specific value of the start of data can
- * be obtained via the UniPlus+ specific "uvar" system call,
- * however the method outlined in crt0.c seems to be more portable.
- *
- * Probably what will have to happen when a USG unexec is available,
- * at least on UniPlus, is temacs will have to be made unshared so
- * that text and data are contiguous. Then once loadup is complete,
- * unexec will produce a shared executable where the data can be
- * at the normal shared text boundary and the startofdata variable
- * will be patched by unexec to the correct value.
- *
- */
-
-#ifndef start_of_data
-char *
-start_of_data ()
-{
-#ifdef DATA_START
- return ((char *) DATA_START);
-#else
-#ifdef ORDINARY_LINK
- /*
- * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
- * data_start isn't defined. We take the address of environ, which
- * is known to live at or near the start of the system crt0.c, and
- * we don't sweat the handful of bytes that might lose.
- */
- extern char **environ;
-
- return ((char *) &environ);
-#else
- extern int data_start;
- return ((char *) &data_start);
-#endif /* ORDINARY_LINK */
-#endif /* DATA_START */
-}
-#endif /* start_of_data */
-#endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
-\f
-/* init_system_name sets up the string for the Lisp function
- system-name to return. */
-
-extern Lisp_Object Vsystem_name;
-
#ifdef HAVE_SOCKETS
#include <sys/socket.h>
#include <netdb.h>
#endif /* TRY_AGAIN */
void
-init_system_name ()
+init_system_name (void)
{
#ifndef HAVE_GETHOSTNAME
struct utsname uts;
Vsystem_name = build_string (uts.nodename);
#else /* HAVE_GETHOSTNAME */
unsigned int hostname_size = 256;
- char *hostname = (char *) alloca (hostname_size);
+ char *hostname = alloca (hostname_size);
/* Try to get the host name; if the buffer is too short, try
again. Apparently, the only indication gethostname gives of
break;
hostname_size <<= 1;
- hostname = (char *) alloca (hostname_size);
+ hostname = alloca (hostname_size);
}
#ifdef HAVE_SOCKETS
/* Turn the hostname into the official, fully-qualified hostname.
#ifndef CANNOT_DUMP
if (initialized)
#endif /* not CANNOT_DUMP */
- if (! index (hostname, '.'))
+ if (! strchr (hostname, '.'))
{
int count;
#ifdef HAVE_GETADDRINFO
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;
while (it)
{
char *fqdn = it->ai_canonname;
- if (fqdn && index (fqdn, '.')
+ if (fqdn && strchr (fqdn, '.')
&& strcmp (fqdn, "localhost.localdomain") != 0)
break;
it = it->ai_next;
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 (!index (fqdn, '.'))
- {
- /* We still don't have a fully qualified domain name.
- Try to find one in the list of alternate names */
- char **alias = hp->h_aliases;
- while (*alias
- && (!index (*alias, '.')
- || !strcmp (*alias, "localhost.localdomain")))
- alias++;
- if (*alias)
- fqdn = *alias;
- }
- hostname = fqdn;
- }
-#endif /* !HAVE_GETADDRINFO */
- }
-#endif /* HAVE_SOCKETS */
- Vsystem_name = build_string (hostname);
-#endif /* HAVE_GETHOSTNAME */
- {
- unsigned char *p;
- for (p = SDATA (Vsystem_name); *p; p++)
- if (*p == ' ' || *p == '\t')
- *p = '-';
- }
-}
-\f
-#ifndef MSDOS
-#if !defined (HAVE_SELECT)
-
-#include "sysselect.h"
-#undef select
-
-#if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
-/* Cause explanatory error message at compile time,
- since the select emulation is not good enough for X. */
-int *x = &x_windows_lose_if_no_select_system_call;
-#endif
-
-/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
- * Only checks read descriptors.
- */
-/* How long to wait between checking fds in select */
-#define SELECT_PAUSE 1
-int select_alarmed;
-
-/* For longjmp'ing back to read_input_waiting. */
-
-jmp_buf read_alarm_throw;
-
-/* Nonzero if the alarm signal should throw back to read_input_waiting.
- The read_socket_hook function sets this to 1 while it is waiting. */
-
-int read_alarm_should_throw;
-
-SIGTYPE
-select_alarm ()
-{
- select_alarmed = 1;
- signal (SIGALRM, SIG_IGN);
- SIGNAL_THREAD_CHECK (SIGALRM);
- if (read_alarm_should_throw)
- longjmp (read_alarm_throw, 1);
-}
-
-#ifndef WINDOWSNT
-/* Only rfds are checked. */
-int
-sys_select (nfds, rfds, wfds, efds, timeout)
- int nfds;
- SELECT_TYPE *rfds, *wfds, *efds;
- EMACS_TIME *timeout;
-{
- /* 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;
- extern int proc_buffered_char[];
-#ifndef subprocesses
- int process_tick = 0, update_tick = 0;
-#else
- extern int process_tick, update_tick;
-#endif
- unsigned char buf;
-
-#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 (Vinitial_window_system))
- return select (nfds, rfds, wfds, efds, timeout);
-#endif
- timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
- local_timeout = &timeoutval;
- FD_ZERO (&orfds);
- if (rfds)
- {
- orfds = *rfds;
- FD_ZERO (rfds);
- }
- if (wfds)
- FD_ZERO (wfds);
- if (efds)
- FD_ZERO (efds);
-
- /* If we are looking only for the terminal, with no timeout,
- just read it and wait -- that's more efficient. */
- if (*local_timeout == 100000 && process_tick == update_tick
- && FD_ISSET (0, &orfds))
- {
- int fd;
- for (fd = 1; fd < nfds; ++fd)
- if (FD_ISSET (fd, &orfds))
- goto hardway;
- if (! detect_input_pending ())
- read_input_waiting ();
- FD_SET (0, rfds);
- return 1;
- }
-
- hardway:
- /* Once a second, till the timer expires, check all the flagged read
- * descriptors to see if any input is available. If there is some then
- * set the corresponding bit in the return copy of rfds.
- */
- while (1)
- {
- register int to_check, fd;
-
- if (rfds)
- {
- for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
- {
- if (FD_ISSET (fd, &orfds))
- {
- int avail = 0, status = 0;
-
- if (fd == 0)
- avail = detect_input_pending (); /* Special keyboard handler */
- else
- {
-#ifdef FIONREAD
- status = ioctl (fd, FIONREAD, &avail);
-#else /* no FIONREAD */
- /* Hoping it will return -1 if nothing available
- or 0 if all 0 chars requested are read. */
- if (proc_buffered_char[fd] >= 0)
- avail = 1;
- else
- {
- avail = read (fd, &buf, 1);
- if (avail > 0)
- proc_buffered_char[fd] = buf;
- }
-#endif /* no FIONREAD */
- }
- if (status >= 0 && avail > 0)
- {
- FD_SET (fd, rfds);
- ravail++;
- }
- }
- }
- }
- if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
- break;
-
- turn_on_atimers (0);
- signal (SIGALRM, select_alarm);
- select_alarmed = 0;
- alarm (SELECT_PAUSE);
-
- /* Wait for a SIGALRM (or maybe a SIGTINT) */
- while (select_alarmed == 0 && *local_timeout != 0
- && process_tick == update_tick)
- {
- /* If we are interested in terminal input,
- wait by reading the terminal.
- That makes instant wakeup for terminal input at least. */
- if (FD_ISSET (0, &orfds))
- {
- read_input_waiting ();
- if (detect_input_pending ())
- select_alarmed = 1;
- }
- else
- pause ();
- }
- (*local_timeout) -= SELECT_PAUSE;
-
- /* Reset the old alarm if there was one. */
- turn_on_atimers (1);
-
- if (*local_timeout == 0) /* Stop on timer being cleared */
- break;
- }
- return ravail;
-}
-#endif /* not WINDOWSNT */
-
-/* Read keyboard input into the standard buffer,
- waiting for at least one character. */
-
-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;
-
- if (read_socket_hook)
- {
- struct input_event hold_quit;
-
- EVENT_INIT (hold_quit);
- hold_quit.kind = NO_EVENT;
-
- read_alarm_should_throw = 0;
- if (! setjmp (read_alarm_throw))
- nread = (*read_socket_hook) (0, 1, &hold_quit);
- else
- nread = -1;
-
- if (hold_quit.kind != NO_EVENT)
- kbd_buffer_store_event (&hold_quit);
- }
- else
- {
- struct input_event e;
- char buf[3];
- nread = read (fileno (stdin), buf, 1);
- EVENT_INIT (e);
-
- /* Scan the chars for C-g and store them in kbd_buffer. */
- e.kind = ASCII_KEYSTROKE_EVENT;
- e.frame_or_window = selected_frame;
- e.modifiers = 0;
- for (i = 0; i < nread; i++)
- {
- /* Convert chars > 0177 to meta events if desired.
- We do this under the same conditions that read_avail_input does. */
- if (read_socket_hook == 0)
- {
- /* If the user says she has a meta key, then believe her. */
- if (meta_key == 1 && (buf[i] & 0x80))
- e.modifiers = meta_modifier;
- if (meta_key != 2)
- buf[i] &= ~0x80;
- }
+ break;
- XSETINT (e.code, buf[i]);
- kbd_buffer_store_event (&e);
- /* Don't look at input that follows a C-g too closely.
- This reduces lossage due to autorepeat on C-g. */
- if (buf[i] == quit_char)
- break;
- }
- }
-}
+ if (count >= 5)
+ break;
+ Fsleep_for (make_number (1), Qnil);
+ }
-#if !defined (HAVE_SELECT)
-#define select sys_select
-#endif
+ if (hp)
+ {
+ char *fqdn = (char *) hp->h_name;
-#endif /* not HAVE_SELECT */
-#endif /* not MSDOS */
+ if (!strchr (fqdn, '.'))
+ {
+ /* We still don't have a fully qualified domain name.
+ Try to find one in the list of alternate names */
+ char **alias = hp->h_aliases;
+ while (*alias
+ && (!strchr (*alias, '.')
+ || !strcmp (*alias, "localhost.localdomain")))
+ alias++;
+ if (*alias)
+ fqdn = *alias;
+ }
+ hostname = fqdn;
+ }
+#endif /* !HAVE_GETADDRINFO */
+ }
+#endif /* HAVE_SOCKETS */
+ Vsystem_name = build_string (hostname);
+#endif /* HAVE_GETHOSTNAME */
+ {
+ unsigned char *p;
+ for (p = SDATA (Vsystem_name); *p; p++)
+ if (*p == ' ' || *p == '\t')
+ *p = '-';
+ }
+}
\f
/* POSIX signals support - DJB */
/* Anyone with POSIX signals should have ANSI C declarations */
-#ifdef POSIX_SIGNALS
+sigset_t empty_mask;
-sigset_t empty_mask, full_mask;
+#ifndef WINDOWSNT
signal_handler_t
sys_signal (int signal_number, signal_handler_t action)
#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. */
+ However, on some systems (only hpux11 at present) this resets the
+ timeout of `select' which means that `select' never finishes if
+ it keeps getting signals.
+ We define BROKEN_SA_RESTART 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 defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT)
if (noninteractive)
# endif
new_action.sa_flags = SA_RESTART;
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. */
sys_sigblock (sigset_t new_mask)
{
sigset_t old_mask;
- sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
+ pthread_sigmask (SIG_BLOCK, &new_mask, &old_mask);
return (old_mask);
}
sys_sigunblock (sigset_t new_mask)
{
sigset_t old_mask;
- sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
+ pthread_sigmask (SIG_UNBLOCK, &new_mask, &old_mask);
return (old_mask);
}
sys_sigsetmask (sigset_t new_mask)
{
sigset_t old_mask;
- sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
+ pthread_sigmask (SIG_SETMASK, &new_mask, &old_mask);
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)
sys_siglist[SIGQUIT] = "Quit";
# endif
# ifdef SIGRETRACT
- sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
+ sys_siglist[SIGRETRACT] = "Need to relinquish monitor mode";
# endif
# ifdef SIGSAK
sys_siglist[SIGSAK] = "Secure attention";
#endif /* !RAND_BITS */
void
-seed_random (arg)
- long arg;
+seed_random (long int arg)
{
#ifdef HAVE_RANDOM
srandom ((unsigned int)arg);
}
/*
- * Build a full Emacs-sized word out of whatever we've got.
+ * Return a nonnegative random integer out of whatever we've got.
+ * It contains enough bits to make a random (signed) Emacs fixnum.
* This suffices even for a 64-bit architecture with a 15-bit rand.
*/
-long
-get_random ()
-{
- long val = random ();
-#if VALBITS > RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 2*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 3*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 4*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#endif /* need at least 5 */
-#endif /* need at least 4 */
-#endif /* need at least 3 */
-#endif /* need at least 2 */
- return val & ((1L << VALBITS) - 1);
+EMACS_INT
+get_random (void)
+{
+ EMACS_UINT val = 0;
+ int i;
+ for (i = 0; i < (FIXNUM_BITS + RAND_BITS - 1) / RAND_BITS; i++)
+ val = (random () ^ (val << RAND_BITS)
+ ^ (val >> (BITS_PER_EMACS_INT - RAND_BITS)));
+ val ^= val >> (BITS_PER_EMACS_INT - FIXNUM_BITS);
+ return val & INTMASK;
}
#ifndef HAVE_STRERROR
#ifndef WINDOWSNT
char *
-strerror (errnum)
- int errnum;
+strerror (int errnum)
{
extern char *sys_errlist[];
extern int sys_nerr;
}
#endif /* not WINDOWSNT */
#endif /* ! HAVE_STRERROR */
+
+#ifndef HAVE_SNPRINTF
+/* Approximate snprintf as best we can on ancient hosts that lack it. */
+int
+snprintf (char *buf, size_t bufsize, char const *format, ...)
+{
+ ptrdiff_t size = min (bufsize, PTRDIFF_MAX);
+ ptrdiff_t nbytes = size - 1;
+ va_list ap;
+
+ if (size)
+ {
+ va_start (ap, format);
+ nbytes = doprnt (buf, size, format, 0, ap);
+ va_end (ap);
+ }
+
+ if (nbytes == size - 1)
+ {
+ /* Calculate the length of the string that would have been created
+ had the buffer been large enough. */
+ char stackbuf[4000];
+ char *b = stackbuf;
+ ptrdiff_t bsize = sizeof stackbuf;
+ va_start (ap, format);
+ nbytes = evxprintf (&b, &bsize, stackbuf, -1, format, ap);
+ va_end (ap);
+ if (b != stackbuf)
+ xfree (b);
+ }
+
+ if (INT_MAX < nbytes)
+ {
+#ifdef EOVERFLOW
+ errno = EOVERFLOW;
+#else
+ errno = EDOM;
+#endif
+ return -1;
+ }
+ return nbytes;
+}
+#endif
\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;
return rtnval;
}
-int
-emacs_read (fildes, buf, nbyte)
- int fildes;
- char *buf;
- unsigned int nbyte;
+/* Maximum number of bytes to read or write in a single system call.
+ This works around a serious bug in Linux kernels before 2.6.16; see
+ <https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=612839>.
+ It's likely to work around similar bugs in other operating systems, so do it
+ on all platforms. Round INT_MAX down to a page size, with the conservative
+ assumption that page sizes are at most 2**18 bytes (any kernel with a
+ page size larger than that shouldn't have the bug). */
+#ifndef MAX_RW_COUNT
+#define MAX_RW_COUNT (INT_MAX >> 18 << 18)
+#endif
+
+/* Read from FILEDESC to a buffer BUF with size NBYTE, retrying if interrupted.
+ Return the number of bytes read, which might be less than NBYTE.
+ On error, set errno and return -1. */
+ptrdiff_t
+emacs_read (int fildes, char *buf, ptrdiff_t nbyte)
{
- register int rtnval;
+ register ssize_t rtnval;
+
+ /* There is no need to check against MAX_RW_COUNT, since no caller ever
+ passes a size that large to emacs_read. */
while ((rtnval = read (fildes, buf, nbyte)) == -1
&& (errno == EINTR))
return (rtnval);
}
-int
-emacs_write (fildes, buf, nbyte)
- int fildes;
- const char *buf;
- unsigned int nbyte;
+/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted
+ or if a partial write occurs. Return the number of bytes written, setting
+ errno if this is less than NBYTE. */
+ptrdiff_t
+emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
{
- register int rtnval, bytes_written;
+ ssize_t rtnval;
+ ptrdiff_t bytes_written;
bytes_written = 0;
while (nbyte > 0)
{
- rtnval = write (fildes, buf, nbyte);
+ rtnval = write (fildes, buf, min (nbyte, MAX_RW_COUNT));
- if (rtnval == -1)
+ if (rtnval < 0)
{
if (errno == EINTR)
{
continue;
}
else
- return (bytes_written ? bytes_written : -1);
+ break;
}
buf += rtnval;
nbyte -= rtnval;
bytes_written += rtnval;
}
+
return (bytes_written);
}
+
+static struct allocator const emacs_norealloc_allocator =
+ { xmalloc, NULL, xfree, memory_full };
+
+/* Get the symbolic link value of FILENAME. Return a pointer to a
+ NUL-terminated string. If readlink fails, return NULL and set
+ errno. If the value fits in INITIAL_BUF, return INITIAL_BUF.
+ Otherwise, allocate memory and return a pointer to that memory. If
+ memory allocation fails, diagnose and fail without returning. If
+ successful, store the length of the symbolic link into *LINKLEN. */
+char *
+emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
+{
+ return careadlinkat (AT_FDCWD, filename, initial_buf, READLINK_BUFSIZE,
+ &emacs_norealloc_allocator, careadlinkatcwd);
+}
\f
#ifdef USG
/*
* under error conditions.
*/
+#ifndef HAVE_GETWD
+
#ifndef MAXPATHLEN
/* In 4.1, param.h fails to define this. */
#define MAXPATHLEN 1024
#endif
-#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)
{
#endif
-#if defined(HPUX) && !defined(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. */
-perror ()
+void
+perror (void)
{
}
#endif /* HPUX and not HAVE_PERROR */
-#ifndef HAVE_DUP2
-
-/*
- * Emulate BSD dup2. First close newd if it already exists.
- * Then, attempt to dup oldd. If not successful, call dup2 recursively
- * until we are, then close the unsuccessful ones.
- */
-
-dup2 (oldd, newd)
- int oldd;
- int newd;
-{
- register int fd, ret;
-
- emacs_close (newd);
-
-#ifdef F_DUPFD
- return fcntl (oldd, F_DUPFD, newd);
-#else
- fd = dup (old);
- if (fd == -1)
- return -1;
- if (fd == new)
- return new;
- ret = dup2 (old,new);
- emacs_close (fd);
- return ret;
-#endif
-}
-
-#endif /* not HAVE_DUP2 */
-
-/*
- * Gettimeofday. Simulate as much as possible. Only accurate
- * to nearest second. Emacs doesn't use tzp so ignore it for now.
- * Only needed when subprocesses are defined.
- */
-
-#ifdef subprocesses
-#ifndef HAVE_GETTIMEOFDAY
-#ifdef HAVE_TIMEVAL
-
-/* ARGSUSED */
-int
-gettimeofday (tp, tzp)
- struct timeval *tp;
- struct timezone *tzp;
-{
- extern long time ();
-
- tp->tv_sec = time ((long *)0);
- tp->tv_usec = 0;
- if (tzp != 0)
- tzp->tz_minuteswest = -1;
- return 0;
-}
-
-#endif
-#endif
-#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
-
/*
* This function will go away as soon as all the stubs fixed. (fnf)
*/
void
-croak (badfunc)
- char *badfunc;
+croak (char *badfunc)
{
printf ("%s not yet implemented\r\n", badfunc);
reset_all_sys_modes ();
\f
/* Directory routines for systems that don't have them. */
-#ifdef SYSV_SYSTEM_DIR
+#ifdef HAVE_DIRENT_H
#include <dirent.h>
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;
}
#endif /* not HAVE_CLOSEDIR */
-#endif /* SYSV_SYSTEM_DIR */
+#endif /* HAVE_DIRENT_H */
\f
+/* Return a struct timeval that is roughly equivalent to T.
+ Use the least timeval not less than T.
+ Return an extremal value if the result would overflow. */
+struct timeval
+make_timeval (EMACS_TIME t)
+{
+ struct timeval tv;
+ tv.tv_sec = t.tv_sec;
+ tv.tv_usec = t.tv_nsec / 1000;
+
+ if (t.tv_nsec % 1000 != 0)
+ {
+ if (tv.tv_usec < 999999)
+ tv.tv_usec++;
+ else if (tv.tv_sec < TYPE_MAXIMUM (time_t))
+ {
+ tv.tv_sec++;
+ tv.tv_usec = 0;
+ }
+ }
+
+ return tv;
+}
+
+/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
+ ATIME and MTIME, respectively.
+ FD must be either negative -- in which case it is ignored --
+ or a file descriptor that is open on FILE.
+ If FD is nonnegative, then FILE can be NULL. */
int
-set_file_times (filename, atime, mtime)
- const char *filename;
- EMACS_TIME atime, mtime;
-{
-#ifdef HAVE_UTIMES
- struct timeval tv[2];
- tv[0] = atime;
- tv[1] = mtime;
- return utimes (filename, tv);
-#else /* not HAVE_UTIMES */
- struct utimbuf utb;
- utb.actime = EMACS_SECS (atime);
- utb.modtime = EMACS_SECS (mtime);
- return utime (filename, &utb);
-#endif /* not HAVE_UTIMES */
+set_file_times (int fd, const char *filename,
+ EMACS_TIME atime, EMACS_TIME mtime)
+{
+ struct timespec timespec[2];
+ timespec[0] = atime;
+ timespec[1] = mtime;
+ return fdutimens (fd, filename, timespec);
}
\f
/* mkdir and rmdir functions, for systems which don't have them. */
* Make a directory.
*/
int
-mkdir (dpath, dmode)
- char *dpath;
- int dmode;
+mkdir (char *dpath, int dmode)
{
- int cpid, status, fd;
+ pid_t cpid;
+ int status, fd;
struct stat statbuf;
if (stat (dpath, &statbuf) == 0)
#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;
-{
- while (length-- > 0)
- *b++ = 0;
-}
-
-#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;
-{
- while (length-- > 0)
- *b2++ = *b1++;
-}
-#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;
-{
- while (length-- > 0)
- if (*b1++ != *b2++)
- return 1;
-
- return 0;
-}
-#endif /* no bcmp */
-#endif /* not BSTRING */
-\f
#ifndef HAVE_STRSIGNAL
char *
-strsignal (code)
- int code;
+strsignal (int code)
{
char *signame = 0;
}
#endif /* HAVE_STRSIGNAL */
\f
-#ifdef HAVE_TERMIOS
+#ifndef DOS_NT
/* For make-serial-process */
-int serial_open (char *port)
+int
+serial_open (char *port)
{
int fd = -1;
return fd;
}
-#endif /* TERMIOS */
-
-#ifdef HAVE_TERMIOS
#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;
CHECK_NUMBER (tem);
err = cfsetspeed (&attr, XINT (tem));
if (err != 0)
- error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
+ error ("cfsetspeed(%"pI"d) failed: %s", XINT (tem),
+ emacs_strerror (errno));
childp2 = Fplist_put (childp2, QCspeed, tem);
/* Configure bytesize. */
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);
p->childp = childp2;
}
-#endif /* TERMIOS */
+#endif /* not DOS_NT */
\f
/* System depended enumeration of and access to system processes a-la ps(1). */
/* Process enumeration and access via /proc. */
Lisp_Object
-list_system_processes ()
+list_system_processes (void)
{
Lisp_Object procdir, match, proclist, next;
struct gcpro gcpro1, gcpro2;
return proclist;
}
+#elif defined BSD_SYSTEM
+
+Lisp_Object
+list_system_processes (void)
+{
+#if defined DARWIN_OS || defined __NetBSD__ || defined __OpenBSD__
+ int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
+#else
+ int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC};
+#endif
+ size_t len;
+ struct kinfo_proc *procs;
+ size_t i;
+
+ struct gcpro gcpro1;
+ Lisp_Object proclist = Qnil;
+
+ if (sysctl (mib, 3, NULL, &len, NULL, 0) != 0)
+ return proclist;
+
+ procs = xmalloc (len);
+ if (sysctl (mib, 3, procs, &len, NULL, 0) != 0)
+ {
+ xfree (procs);
+ return proclist;
+ }
+
+ GCPRO1 (proclist);
+ len /= sizeof (struct kinfo_proc);
+ for (i = 0; i < len; i++)
+ {
+#if defined DARWIN_OS || defined __NetBSD__
+ proclist = Fcons (make_fixnum_or_float (procs[i].kp_proc.p_pid), proclist);
+#elif defined __OpenBSD__
+ proclist = Fcons (make_fixnum_or_float (procs[i].p_pid), proclist);
+#else
+ proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist);
+#endif
+ }
+ UNGCPRO;
+
+ xfree (procs);
+
+ 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 ()
+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;
+static EMACS_TIME
+time_from_jiffies (unsigned long long tval, long hz)
+{
+ unsigned long long s = tval / hz;
+ unsigned long long frac = tval % hz;
+ int ns;
+ EMACS_TIME t;
+
+ if (TYPE_MAXIMUM (time_t) < s)
+ time_overflow ();
+ if (LONG_MAX - 1 <= ULLONG_MAX / EMACS_TIME_RESOLUTION
+ || frac <= ULLONG_MAX / EMACS_TIME_RESOLUTION)
+ ns = frac * EMACS_TIME_RESOLUTION / hz;
else
- *usec = tval / (hz / 1000000);
+ {
+ /* This is reachable only in the unlikely case that HZ * HZ
+ exceeds ULLONG_MAX. It calculates an approximation that is
+ guaranteed to be in range. */
+ long hz_per_ns = (hz / EMACS_TIME_RESOLUTION
+ + (hz % EMACS_TIME_RESOLUTION != 0));
+ ns = frac / hz_per_ns;
+ }
+
+ EMACS_SET_SECS_NSECS (t, s, ns);
+ return t;
}
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));
+ EMACS_TIME t = time_from_jiffies (tval, hz);
+ return make_lisp_time (t);
}
-static void
-get_up_time (time_t *sec, unsigned *usec)
+static EMACS_TIME
+get_up_time (void)
{
FILE *fup;
+ EMACS_TIME up;
- *sec = *usec = 0;
+ EMACS_SET_SECS_NSECS (up, 0, 0);
BLOCK_INPUT;
fup = fopen ("/proc/uptime", "r");
if (fup)
{
- double uptime, idletime;
+ unsigned long long upsec, upfrac, idlesec, idlefrac;
+ int upfrac_start, upfrac_end, idlefrac_start, idlefrac_end;
- /* 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))
+ if (fscanf (fup, "%llu.%n%llu%n %llu.%n%llu%n",
+ &upsec, &upfrac_start, &upfrac, &upfrac_end,
+ &idlesec, &idlefrac_start, &idlefrac, &idlefrac_end)
+ == 4)
{
- *sec = uptime;
- *usec = (uptime - *sec) * 1000000;
+ if (TYPE_MAXIMUM (time_t) < upsec)
+ {
+ upsec = TYPE_MAXIMUM (time_t);
+ upfrac = EMACS_TIME_RESOLUTION - 1;
+ }
+ else
+ {
+ int upfraclen = upfrac_end - upfrac_start;
+ for (; upfraclen < LOG10_EMACS_TIME_RESOLUTION; upfraclen++)
+ upfrac *= 10;
+ for (; LOG10_EMACS_TIME_RESOLUTION < upfraclen; upfraclen--)
+ upfrac /= 10;
+ upfrac = min (upfrac, EMACS_TIME_RESOLUTION - 1);
+ }
+ EMACS_SET_SECS_NSECS (up, upsec, upfrac);
}
fclose (fup);
}
UNBLOCK_INPUT;
+
+ return up;
}
#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
char procbuf[1025], *p, *q;
int fd;
ssize_t nread;
- const char *cmd = NULL;
+ static char const default_cmd[] = "???";
+ const char *cmd = default_cmd;
+ int cmdsize = sizeof default_cmd - 1;
char *cmdline = NULL;
- size_t cmdsize = 0, cmdline_size;
+ ptrdiff_t 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;
+ printmax_t proc_id;
+ int ppid, pgrp, sess, tty, tpgid, thcount;
+ uid_t uid;
+ gid_t gid;
+ unsigned long long u_time, s_time, cutime, cstime, start;
+ long priority, niceness, rss;
unsigned long minflt, majflt, cminflt, cmajflt, vsize;
- time_t sec;
- unsigned usec;
- EMACS_TIME tnow, tstart, tboot, telapsed,ttotal;
+ EMACS_TIME tnow, tstart, tboot, telapsed, us_time;
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);
+ CONS_TO_INTEGER (pid, pid_t, proc_id);
+ sprintf (procfn, "/proc/%"pMd, proc_id);
if (stat (procfn, &st) < 0)
return attrs;
/* 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);
+ attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
BLOCK_INPUT;
pw = getpwuid (uid);
UNBLOCK_INPUT;
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);
+ attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
BLOCK_INPUT;
gr = getgrgid (gid);
UNBLOCK_INPUT;
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)
+ if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof (procbuf) - 1)) > 0)
{
procbuf[nread] = '\0';
p = procbuf;
}
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,
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);
+ &u_time, &s_time, &cutime, &cstime,
+ &priority, &niceness, &thcount, &start, &vsize, &rss);
{
char state_str[2];
if (clocks_per_sec < 0)
clocks_per_sec = 100;
attrs = Fcons (Fcons (Qutime,
- ltime_from_jiffies (utime, clocks_per_sec)),
+ ltime_from_jiffies (u_time, clocks_per_sec)),
attrs);
attrs = Fcons (Fcons (Qstime,
- ltime_from_jiffies (stime, clocks_per_sec)),
+ ltime_from_jiffies (s_time, clocks_per_sec)),
attrs);
attrs = Fcons (Fcons (Qtime,
- ltime_from_jiffies (stime+utime, clocks_per_sec)),
+ ltime_from_jiffies (s_time + u_time,
+ clocks_per_sec)),
attrs);
attrs = Fcons (Fcons (Qcutime,
ltime_from_jiffies (cutime, clocks_per_sec)),
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 (Qnice, make_number (niceness)), 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);
+ telapsed = get_up_time ();
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);
+ tstart = time_from_jiffies (start, clocks_per_sec);
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 (Qstart, make_lisp_time (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);
+ attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
+ us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
+ pcpu = (EMACS_TIME_TO_DOUBLE (us_time)
+ / EMACS_TIME_TO_DOUBLE (telapsed));
if (pcpu > 1.0)
pcpu = 1.0;
attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
fd = emacs_open (fn, O_RDONLY, 0);
if (fd >= 0)
{
- for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++)
+ char ch;
+ for (cmdline_size = 0; cmdline_size < STRING_BYTES_BOUND; cmdline_size++)
{
+ if (emacs_read (fd, &ch, 1) != 1)
+ break;
+ c = ch;
if (isspace (c) || c == '\\')
cmdline_size++; /* for later quoting, see below */
}
nread = 0;
}
/* We don't want trailing null characters. */
- for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
+ for (p = cmdline + nread; p > cmdline + 1 && !p[-1]; p--)
nread--;
for (p = cmdline; p < cmdline + nread; p++)
{
}
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), "]");
+ sprintf (cmdline, "[%.*s]", cmdsize, cmd);
}
emacs_close (fd);
/* Command line is encoded in locale-coding-system; decode it. */
#if PROCFS_FILE_OFFSET_BITS_HACK == 1
#define _FILE_OFFSET_BITS 64
+#ifdef _FILE_OFFSET_BITS /* Avoid unused-macro warnings. */
+#endif
#endif /* PROCFS_FILE_OFFSET_BITS_HACK == 1 */
Lisp_Object
struct psinfo pinfo;
int fd;
ssize_t nread;
- int proc_id, uid, gid;
+ printmax_t proc_id;
+ uid_t uid;
+ gid_t 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);
+ CONS_TO_INTEGER (pid, pid_t, proc_id);
+ sprintf (procfn, "/proc/%"pMd, proc_id);
if (stat (procfn, &st) < 0)
return attrs;
/* 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);
+ attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
BLOCK_INPUT;
pw = getpwuid (uid);
UNBLOCK_INPUT;
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);
+ attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
BLOCK_INPUT;
gr = getgrgid (gid);
UNBLOCK_INPUT;
strcpy (procfn_end, "/psinfo");
fd = emacs_open (fn, O_RDONLY, 0);
if (fd >= 0
- && (nread = read (fd, (char*)&pinfo, sizeof(struct psinfo)) > 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);
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 (Qtime, make_lisp_time (pinfo.pr_time)), attrs);
+ attrs = Fcons (Fcons (Qctime, make_lisp_time (pinfo.pr_ctime)), 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 (Qstart, make_lisp_time (pinfo.pr_start)), 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);
+ /* pr_pctcpu and pr_pctmem are unsigned integers in the
+ range 0 .. 2**15, representing 0.0 .. 1.0. */
+ attrs = Fcons (Fcons (Qpcpu, make_float (100.0 / 0x8000 * pinfo.pr_pctcpu)), attrs);
+ attrs = Fcons (Fcons (Qpmem, make_float (100.0 / 0x8000 * pinfo.pr_pctmem)), attrs);
decoded_cmd
= code_convert_string_norecord (make_unibyte_string (pinfo.pr_fname,
return attrs;
}
+#elif defined __FreeBSD__
+
+static EMACS_TIME
+timeval_to_EMACS_TIME (struct timeval t)
+{
+ EMACS_TIME e;
+ EMACS_SET_SECS_NSECS (e, t.tv_sec, t.tv_usec * 1000);
+ return e;
+}
+
+static Lisp_Object
+make_lisp_timeval (struct timeval t)
+{
+ return make_lisp_time (timeval_to_EMACS_TIME (t));
+}
+
+Lisp_Object
+system_process_attributes (Lisp_Object pid)
+{
+ int proc_id;
+ int pagesize = getpagesize ();
+ int npages;
+ int fscale;
+ struct passwd *pw;
+ struct group *gr;
+ char *ttyname;
+ size_t len;
+ char args[MAXPATHLEN];
+ EMACS_TIME t, now;
+
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
+ struct kinfo_proc proc;
+ size_t proclen = sizeof proc;
+
+ struct gcpro gcpro1, gcpro2;
+ Lisp_Object attrs = Qnil;
+ Lisp_Object decoded_comm;
+
+ CHECK_NUMBER_OR_FLOAT (pid);
+ CONS_TO_INTEGER (pid, int, proc_id);
+ mib[3] = proc_id;
+
+ if (sysctl (mib, 4, &proc, &proclen, NULL, 0) != 0)
+ return attrs;
+
+ GCPRO2 (attrs, decoded_comm);
+
+ attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs);
+
+ BLOCK_INPUT;
+ pw = getpwuid (proc.ki_uid);
+ UNBLOCK_INPUT;
+ if (pw)
+ attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
+
+ attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (proc.ki_svgid)), attrs);
+
+ BLOCK_INPUT;
+ gr = getgrgid (proc.ki_svgid);
+ UNBLOCK_INPUT;
+ if (gr)
+ attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
+
+ decoded_comm = code_convert_string_norecord
+ (make_unibyte_string (proc.ki_comm, strlen (proc.ki_comm)),
+ Vlocale_coding_system, 0);
+
+ attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
+ {
+ char state[2] = {'\0', '\0'};
+ switch (proc.ki_stat)
+ {
+ case SRUN:
+ state[0] = 'R';
+ break;
+
+ case SSLEEP:
+ state[0] = 'S';
+ break;
+
+ case SLOCK:
+ state[0] = 'D';
+ break;
+
+ case SZOMB:
+ state[0] = 'Z';
+ break;
+
+ case SSTOP:
+ state[0] = 'T';
+ break;
+ }
+ attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
+ }
+
+ attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (proc.ki_ppid)), attrs);
+ attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (proc.ki_pgid)), attrs);
+ attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (proc.ki_sid)), attrs);
+
+ BLOCK_INPUT;
+ ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR);
+ UNBLOCK_INPUT;
+ if (ttyname)
+ attrs = Fcons (Fcons (Qtty, build_string (ttyname)), attrs);
+
+ attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (proc.ki_tpgid)), attrs);
+ attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (proc.ki_rusage.ru_minflt)), attrs);
+ attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (proc.ki_rusage.ru_majflt)), attrs);
+ attrs = Fcons (Fcons (Qcminflt, make_number (proc.ki_rusage_ch.ru_minflt)), attrs);
+ attrs = Fcons (Fcons (Qcmajflt, make_number (proc.ki_rusage_ch.ru_majflt)), attrs);
+
+ attrs = Fcons (Fcons (Qutime, make_lisp_timeval (proc.ki_rusage.ru_utime)),
+ attrs);
+ attrs = Fcons (Fcons (Qstime, make_lisp_timeval (proc.ki_rusage.ru_stime)),
+ attrs);
+ EMACS_ADD_TIME (t,
+ timeval_to_EMACS_TIME (proc.ki_rusage.ru_utime),
+ timeval_to_EMACS_TIME (proc.ki_rusage.ru_stime));
+ attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs);
+
+ attrs = Fcons (Fcons (Qcutime,
+ make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
+ attrs);
+ attrs = Fcons (Fcons (Qcstime,
+ make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
+ attrs);
+ EMACS_ADD_TIME (t,
+ timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_utime),
+ timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_stime));
+ attrs = Fcons (Fcons (Qctime, make_lisp_time (t)), attrs);
+
+ attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (proc.ki_numthreads)),
+ attrs);
+ attrs = Fcons (Fcons (Qpri, make_number (proc.ki_pri.pri_native)), attrs);
+ attrs = Fcons (Fcons (Qnice, make_number (proc.ki_nice)), attrs);
+ attrs = Fcons (Fcons (Qstart, make_lisp_timeval (proc.ki_start)), attrs);
+ attrs = Fcons (Fcons (Qvsize, make_number (proc.ki_size >> 10)), attrs);
+ attrs = Fcons (Fcons (Qrss, make_number (proc.ki_rssize * pagesize >> 10)),
+ attrs);
+
+ EMACS_GET_TIME (now);
+ EMACS_SUB_TIME (t, now, timeval_to_EMACS_TIME (proc.ki_start));
+ attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
+
+ len = sizeof fscale;
+ if (sysctlbyname ("kern.fscale", &fscale, &len, NULL, 0) == 0)
+ {
+ double pcpu;
+ fixpt_t ccpu;
+ len = sizeof ccpu;
+ if (sysctlbyname ("kern.ccpu", &ccpu, &len, NULL, 0) == 0)
+ {
+ pcpu = (100.0 * proc.ki_pctcpu / fscale
+ / (1 - exp (proc.ki_swtime * log ((double) ccpu / fscale))));
+ attrs = Fcons (Fcons (Qpcpu, make_fixnum_or_float (pcpu)), attrs);
+ }
+ }
+
+ len = sizeof npages;
+ if (sysctlbyname ("hw.availpages", &npages, &len, NULL, 0) == 0)
+ {
+ double pmem = (proc.ki_flag & P_INMEM
+ ? 100.0 * proc.ki_rssize / npages
+ : 0);
+ attrs = Fcons (Fcons (Qpmem, make_fixnum_or_float (pmem)), attrs);
+ }
+
+ mib[2] = KERN_PROC_ARGS;
+ len = MAXPATHLEN;
+ if (sysctl (mib, 4, args, &len, NULL, 0) == 0)
+ {
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ if (! args[i] && i < len - 1)
+ args[i] = ' ';
+ }
+
+ decoded_comm =
+ (code_convert_string_norecord
+ (make_unibyte_string (args, strlen (args)),
+ Vlocale_coding_system, 0));
+
+ attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
+ }
+
+ UNGCPRO;
+ return attrs;
+}
+
/* The WINDOWSNT implementation is in w32.c.
The MSDOS implementation is in dosfns.c. */
#elif !defined (WINDOWSNT) && !defined (MSDOS)
}
#endif /* !defined (WINDOWSNT) */
-
-
-/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
- (do not change this comment) */