/* Interfaces to system-dependent kernel and library entries.
- Copyright (C) 1985-1988, 1993-1995, 1999-2011
+ Copyright (C) 1985-1988, 1993-1995, 1999-2012
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "sysselect.h"
#include "blockinput.h"
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/resource.h> */
+#include <math.h>
+#endif
+
+#ifdef DARWIN_OS
+#include <sys/sysctl.h>
+#endif
+
#ifdef WINDOWSNT
#define read sys_read
#define write sys_write
#include <windows.h>
-#ifndef NULL
-#define NULL 0
-#endif
#endif /* not WINDOWSNT */
#include <sys/types.h>
{
while (1)
{
-#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. */
#endif /* AIX */
/* We originally enabled ICANON (and set VEOF to 04), and then had
- proces.c send additional EOF chars to flush the output when faced
+ 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
init_sys_modes (struct tty_display_info *tty_out)
{
struct emacs_tty tty;
+ Lisp_Object terminal;
Vtty_erase_char = Qnil;
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.
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);
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;
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 /* 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 (const char *path, int oflag, int mode)
#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. */
return proclist;
}
+#elif defined BSD_SYSTEM
+
+Lisp_Object
+list_system_processes (void)
+{
+#ifdef DARWIN_OS
+ 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++)
+ {
+#ifdef DARWIN_OS
+ proclist = Fcons (make_fixnum_or_float (procs[i].kp_proc.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)
ssize_t nread;
const char *cmd = NULL;
char *cmdline = NULL;
- size_t cmdsize = 0, cmdline_size;
+ ptrdiff_t cmdsize = 0, cmdline_size;
unsigned char c;
int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
unsigned long long u_time, s_time, cutime, cstime, start;
if (fd >= 0)
{
char ch;
- for (cmdline_size = 0; emacs_read (fd, &ch, 1) == 1; cmdline_size++)
+ 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++)
{
return attrs;
}
+#elif defined __FreeBSD__
+
+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);
+ proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
+ 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);
+
+#define TIMELIST(ts) \
+ list3 (make_number (EMACS_SECS (ts) >> 16 & 0xffff), \
+ make_number (EMACS_SECS (ts) & 0xffff), \
+ make_number (EMACS_USECS (ts)))
+
+ attrs = Fcons (Fcons (Qutime, TIMELIST (proc.ki_rusage.ru_utime)), attrs);
+ attrs = Fcons (Fcons (Qstime, TIMELIST (proc.ki_rusage.ru_stime)), attrs);
+ EMACS_ADD_TIME (t, proc.ki_rusage.ru_utime, proc.ki_rusage.ru_stime);
+ attrs = Fcons (Fcons (Qtime, TIMELIST (t)), attrs);
+
+ attrs = Fcons (Fcons (Qcutime, TIMELIST (proc.ki_rusage_ch.ru_utime)), attrs);
+ attrs = Fcons (Fcons (Qcstime, TIMELIST (proc.ki_rusage_ch.ru_utime)), attrs);
+ EMACS_ADD_TIME (t, proc.ki_rusage_ch.ru_utime, proc.ki_rusage_ch.ru_stime);
+ attrs = Fcons (Fcons (Qctime, TIMELIST (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, TIMELIST (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, proc.ki_start);
+ attrs = Fcons (Fcons (Qetime, TIMELIST (t)), attrs);
+
+#undef TIMELIST
+
+ 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)