diff options
Diffstat (limited to 'src/sysdep.c')
-rw-r--r-- | src/sysdep.c | 312 |
1 files changed, 87 insertions, 225 deletions
diff --git a/src/sysdep.c b/src/sysdep.c index addaf4dc28a..29c88f5308e 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #endif /* HAVE_PWD_H */ #include <limits.h> #include <stdlib.h> +#include <sys/random.h> #include <unistd.h> #include <c-ctype.h> @@ -48,10 +49,14 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ # include <cygwin/fs.h> #endif -#if defined DARWIN_OS || defined __FreeBSD__ +#if defined DARWIN_OS || defined __FreeBSD__ || defined __OpenBSD__ # include <sys/sysctl.h> #endif +#ifdef DARWIN_OS +# include <libproc.h> +#endif + #ifdef __FreeBSD__ /* Sparc/ARM machine/frame.h has 'struct frame' which conflicts with Emacs's 'struct frame', so rename it. */ @@ -115,16 +120,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include "process.h" #include "cm.h" -#include "gnutls.h" -/* MS-Windows loads GnuTLS at run time, if available; we don't want to - do that during startup just to call gnutls_rnd. */ -#if defined HAVE_GNUTLS && !defined WINDOWSNT -# include <gnutls/crypto.h> -#else -# define emacs_gnutls_global_init() Qnil -# define gnutls_rnd(level, data, len) (-1) -#endif - #ifdef WINDOWSNT # include <direct.h> /* In process.h which conflicts with the local copy. */ @@ -135,11 +130,6 @@ int _cdecl _spawnlp (int, const char *, const char *, ...); # include <sys/socket.h> #endif -/* 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)); @@ -204,6 +194,7 @@ maybe_disable_address_randomization (int argc, char **argv) } #endif +#ifndef WINDOWSNT /* Execute the program in FILE, with argument vector ARGV and environ ENVP. Return an error number if unsuccessful. This is like execve except it reenables ASLR in the executed program if necessary, and @@ -220,6 +211,8 @@ emacs_exec_file (char const *file, char *const *argv, char *const *envp) return errno; } +#endif /* !WINDOWSNT */ + /* If FD is not already open, arrange for it to be open with FLAGS. */ static void force_open (int fd, int flags) @@ -274,12 +267,12 @@ get_current_dir_name_or_unreachable (void) char *pwd; - /* The maximum size of a directory name, including the terminating NUL. + /* The maximum size of a directory name, including the terminating null. Leave room so that the caller can append a trailing slash. */ ptrdiff_t dirsize_max = min (PTRDIFF_MAX, SIZE_MAX) - 1; /* The maximum size of a buffer for a file name, including the - terminating NUL. This is bounded by PATH_MAX, if available. */ + terminating null. This is bounded by PATH_MAX, if available. */ ptrdiff_t bufsize_max = dirsize_max; #ifdef PATH_MAX bufsize_max = min (bufsize_max, PATH_MAX); @@ -317,8 +310,8 @@ get_current_dir_name_or_unreachable (void) if (pwd && (pwdlen = strnlen (pwd, bufsize_max)) < bufsize_max && IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0]) - && stat (pwd, &pwdstat) == 0 - && stat (".", &dotstat) == 0 + && emacs_fstatat (AT_FDCWD, pwd, &pwdstat, 0) == 0 + && emacs_fstatat (AT_FDCWD, ".", &dotstat, 0) == 0 && dotstat.st_ino == pwdstat.st_ino && dotstat.st_dev == pwdstat.st_dev) { @@ -1770,24 +1763,6 @@ deliver_thread_signal (int sig, signal_handler_t handler) errno = old_errno; } -#if !HAVE_DECL_SYS_SIGLIST -# undef sys_siglist -# ifdef _sys_siglist -# define sys_siglist _sys_siglist -# elif HAVE_DECL___SYS_SIGLIST -# define sys_siglist __sys_siglist -# else -# define sys_siglist my_sys_siglist -static char const *sys_siglist[NSIG]; -# endif -#endif - -#ifdef _sys_nsig -# define sys_siglist_entries _sys_nsig -#else -# define sys_siglist_entries NSIG -#endif - /* Handle bus errors, invalid instruction, etc. */ static void handle_fatal_signal (int sig) @@ -1979,143 +1954,6 @@ init_signals (void) main_thread_id = pthread_self (); #endif -#if !HAVE_DECL_SYS_SIGLIST && !defined _sys_siglist - if (! initialized) - { - sys_siglist[SIGABRT] = "Aborted"; -# ifdef SIGAIO - sys_siglist[SIGAIO] = "LAN I/O interrupt"; -# endif - sys_siglist[SIGALRM] = "Alarm clock"; -# ifdef SIGBUS - sys_siglist[SIGBUS] = "Bus error"; -# endif -# ifdef SIGCHLD - sys_siglist[SIGCHLD] = "Child status changed"; -# endif -# ifdef SIGCONT - sys_siglist[SIGCONT] = "Continued"; -# endif -# ifdef SIGDANGER - sys_siglist[SIGDANGER] = "Swap space dangerously low"; -# endif -# ifdef SIGDGNOTIFY - sys_siglist[SIGDGNOTIFY] = "Notification message in queue"; -# endif -# ifdef SIGEMT - sys_siglist[SIGEMT] = "Emulation trap"; -# endif - sys_siglist[SIGFPE] = "Arithmetic exception"; -# ifdef SIGFREEZE - sys_siglist[SIGFREEZE] = "SIGFREEZE"; -# endif -# ifdef SIGGRANT - sys_siglist[SIGGRANT] = "Monitor mode granted"; -# endif - sys_siglist[SIGHUP] = "Hangup"; - sys_siglist[SIGILL] = "Illegal instruction"; - sys_siglist[SIGINT] = "Interrupt"; -# ifdef SIGIO - sys_siglist[SIGIO] = "I/O possible"; -# endif -# ifdef SIGIOINT - sys_siglist[SIGIOINT] = "I/O intervention required"; -# endif -# ifdef SIGIOT - sys_siglist[SIGIOT] = "IOT trap"; -# endif - sys_siglist[SIGKILL] = "Killed"; -# ifdef SIGLOST - sys_siglist[SIGLOST] = "Resource lost"; -# endif -# ifdef SIGLWP - sys_siglist[SIGLWP] = "SIGLWP"; -# endif -# ifdef SIGMSG - sys_siglist[SIGMSG] = "Monitor mode data available"; -# endif -# ifdef SIGPHONE - sys_siglist[SIGWIND] = "SIGPHONE"; -# endif - sys_siglist[SIGPIPE] = "Broken pipe"; -# ifdef SIGPOLL - sys_siglist[SIGPOLL] = "Pollable event occurred"; -# endif -# ifdef SIGPROF - sys_siglist[SIGPROF] = "Profiling timer expired"; -# endif -# ifdef SIGPTY - sys_siglist[SIGPTY] = "PTY I/O interrupt"; -# endif -# ifdef SIGPWR - sys_siglist[SIGPWR] = "Power-fail restart"; -# endif - sys_siglist[SIGQUIT] = "Quit"; -# ifdef SIGRETRACT - sys_siglist[SIGRETRACT] = "Need to relinquish monitor mode"; -# endif -# ifdef SIGSAK - sys_siglist[SIGSAK] = "Secure attention"; -# endif - sys_siglist[SIGSEGV] = "Segmentation violation"; -# ifdef SIGSOUND - sys_siglist[SIGSOUND] = "Sound completed"; -# endif -# ifdef SIGSTOP - sys_siglist[SIGSTOP] = "Stopped (signal)"; -# endif -# ifdef SIGSTP - sys_siglist[SIGSTP] = "Stopped (user)"; -# endif -# ifdef SIGSYS - sys_siglist[SIGSYS] = "Bad argument to system call"; -# endif - sys_siglist[SIGTERM] = "Terminated"; -# ifdef SIGTHAW - sys_siglist[SIGTHAW] = "SIGTHAW"; -# endif -# ifdef SIGTRAP - sys_siglist[SIGTRAP] = "Trace/breakpoint trap"; -# endif -# ifdef SIGTSTP - sys_siglist[SIGTSTP] = "Stopped (user)"; -# endif -# ifdef SIGTTIN - sys_siglist[SIGTTIN] = "Stopped (tty input)"; -# endif -# ifdef SIGTTOU - sys_siglist[SIGTTOU] = "Stopped (tty output)"; -# endif -# ifdef SIGURG - sys_siglist[SIGURG] = "Urgent I/O condition"; -# endif -# ifdef SIGUSR1 - sys_siglist[SIGUSR1] = "User defined signal 1"; -# endif -# ifdef SIGUSR2 - sys_siglist[SIGUSR2] = "User defined signal 2"; -# endif -# ifdef SIGVTALRM - sys_siglist[SIGVTALRM] = "Virtual timer expired"; -# endif -# ifdef SIGWAITING - sys_siglist[SIGWAITING] = "Process's LWPs are blocked"; -# endif -# ifdef SIGWINCH - sys_siglist[SIGWINCH] = "Window size changed"; -# endif -# ifdef SIGWIND - sys_siglist[SIGWIND] = "SIGWIND"; -# endif -# ifdef SIGXCPU - sys_siglist[SIGXCPU] = "CPU time limit exceeded"; -# endif -# ifdef SIGXFSZ - sys_siglist[SIGXFSZ] = "File size limit exceeded"; -# endif - } -#endif /* !HAVE_DECL_SYS_SIGLIST && !_sys_siglist */ - /* Don't alter signal handlers if dumping. On some machines, changing signal handlers sets static data that would make signals fail to work right when the dumped Emacs is run. */ @@ -2282,9 +2120,7 @@ init_signals (void) typedef unsigned int random_seed; static void set_random_seed (random_seed arg) { srandom (arg); } #elif defined HAVE_LRAND48 -/* Although srand48 uses a long seed, this is unsigned long to avoid - undefined behavior on signed integer overflow in init_random. */ -typedef unsigned long int random_seed; +typedef long int random_seed; static void set_random_seed (random_seed arg) { srand48 (arg); } #else typedef unsigned int random_seed; @@ -2311,23 +2147,14 @@ init_random (void) /* First, try seeding the PRNG from the operating system's entropy source. This approach is both fast and secure. */ #ifdef WINDOWSNT + /* FIXME: Perhaps getrandom can be used here too? */ success = w32_init_random (&v, sizeof v) == 0; #else - int fd = emacs_open ("/dev/urandom", O_RDONLY, 0); - if (0 <= fd) - { - success = emacs_read (fd, &v, sizeof v) == sizeof v; - close (fd); - } + verify (sizeof v <= 256); + success = getrandom (&v, sizeof v, 0) == sizeof v; #endif - /* If that didn't work, try using GnuTLS, which is secure, but on - some systems, can be somewhat slow. */ - if (!success) - success = EQ (emacs_gnutls_global_init (), Qt) - && gnutls_rnd (GNUTLS_RND_NONCE, &v, sizeof v) == 0; - - /* If _that_ didn't work, just use the current time value and PID. + /* If that didn't work, just use the current time value and PID. It's at least better than XKCD 221. */ if (!success) { @@ -2456,7 +2283,27 @@ emacs_abort (void) } #endif -/* Open FILE for Emacs use, using open flags OFLAG and mode MODE. +/* Assuming the directory DIRFD, store information about FILENAME into *ST, + using FLAGS to control how the status is obtained. + Do not fail merely because fetching info was interrupted by a signal. + Allow the user to quit. + + The type of ST is void * instead of struct stat * because the + latter type would be problematic in lisp.h. Some platforms may + play tricks like "#define stat stat64" in <sys/stat.h>, and lisp.h + does not include <sys/stat.h>. */ + +int +emacs_fstatat (int dirfd, char const *filename, void *st, int flags) +{ + int r; + while ((r = fstatat (dirfd, filename, st, flags)) != 0 && errno == EINTR) + maybe_quit (); + return r; +} + +/* Assuming the directory DIRFD, open FILE for Emacs use, + using open flags OFLAGS and mode MODE. Use binary I/O on systems that care about text vs binary I/O. Arrange for subprograms to not inherit the file descriptor. Prefer a method that is multithread-safe, if available. @@ -2464,17 +2311,23 @@ emacs_abort (void) Allow the user to quit. */ int -emacs_open (const char *file, int oflags, int mode) +emacs_openat (int dirfd, char const *file, int oflags, int mode) { int fd; if (! (oflags & O_TEXT)) oflags |= O_BINARY; oflags |= O_CLOEXEC; - while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR) + while ((fd = openat (dirfd, file, oflags, mode)) < 0 && errno == EINTR) maybe_quit (); return fd; } +int +emacs_open (char const *file, int oflags, int mode) +{ + return emacs_openat (AT_FDCWD, file, oflags, mode); +} + /* Open FILE as a stream for Emacs use, with mode MODE. Act like emacs_open with respect to threads, signals, and quits. */ @@ -2733,21 +2586,6 @@ emacs_perror (char const *message) errno = err; } -/* 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 (int fd, const char *filename, - struct timespec atime, struct timespec mtime) -{ - struct timespec timespec[2]; - timespec[0] = atime; - timespec[1] = mtime; - return fdutimens (fd, filename, timespec); -} - /* Rename directory SRCFD's entry SRC to directory DSTFD's entry DST. This is like renameat except that it fails if DST already exists, or if this operation is not supported atomically. Return 0 if @@ -2771,15 +2609,13 @@ renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst) #endif } -/* Like strsignal, except async-signal-safe, and this function typically +/* Like strsignal, except async-signal-safe, and this function returns a string in the C locale rather than the current locale. */ char const * safe_strsignal (int code) { - char const *signame = 0; + char const *signame = sigdescr_np (code); - if (0 <= code && code < sys_siglist_entries) - signame = sys_siglist[code]; if (! signame) signame = "Unknown signal"; @@ -3058,7 +2894,8 @@ list_system_processes (void) process. */ procdir = build_string ("/proc"); match = build_string ("[0-9]+"); - proclist = directory_files_internal (procdir, Qnil, match, Qt, false, Qnil); + proclist = directory_files_internal (procdir, Qnil, match, Qt, + false, Qnil, Qnil); /* `proclist' gives process IDs as strings. Destructively convert each string into a number. */ @@ -3074,37 +2911,43 @@ list_system_processes (void) return proclist; } -#elif defined DARWIN_OS || defined __FreeBSD__ +#elif defined DARWIN_OS || defined __FreeBSD__ || defined __OpenBSD__ Lisp_Object list_system_processes (void) { #ifdef DARWIN_OS int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; +#elif defined __OpenBSD__ + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, + sizeof (struct kinfo_proc), 4096}; #else int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC}; #endif size_t len; + size_t mibsize = sizeof mib / sizeof mib[0]; struct kinfo_proc *procs; size_t i; Lisp_Object proclist = Qnil; - if (sysctl (mib, 3, NULL, &len, NULL, 0) != 0 || len == 0) + if (sysctl (mib, mibsize, NULL, &len, NULL, 0) != 0 || len == 0) return proclist; procs = xmalloc (len); - if (sysctl (mib, 3, procs, &len, NULL, 0) != 0 || len == 0) + if (sysctl (mib, mibsize, procs, &len, NULL, 0) != 0 || len == 0) { xfree (procs); return proclist; } - len /= sizeof (struct kinfo_proc); + len /= sizeof procs[0]; for (i = 0; i < len; i++) { #ifdef DARWIN_OS proclist = Fcons (INT_TO_INTEGER (procs[i].kp_proc.p_pid), proclist); +#elif defined __OpenBSD__ + proclist = Fcons (INT_TO_INTEGER (procs[i].p_pid), proclist); #else proclist = Fcons (INT_TO_INTEGER (procs[i].ki_pid), proclist); #endif @@ -3143,7 +2986,7 @@ make_lisp_timeval (struct timeval t) #endif -#if defined GNU_LINUX && defined HAVE_LONG_LONG_INT +#ifdef GNU_LINUX static struct timespec time_from_jiffies (unsigned long long tval, long hz) { @@ -3491,7 +3334,7 @@ system_process_attributes (Lisp_Object pid) if (nread) { - /* We don't want trailing NUL characters. */ + /* We don't want trailing null characters. */ for (p = cmdline + nread; cmdline < p && !p[-1]; p--) continue; @@ -3878,8 +3721,21 @@ system_process_attributes (Lisp_Object pid) if (gr) attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + char *comm; + + if (proc_pidpath (proc_id, pathbuf, sizeof(pathbuf)) > 0) + { + if ((comm = strrchr (pathbuf, '/'))) + comm++; + else + comm = pathbuf; + } + else + comm = proc.kp_proc.p_comm; + decoded_comm = (code_convert_string_norecord - (build_unibyte_string (proc.kp_proc.p_comm), + (build_unibyte_string (comm), Vlocale_coding_system, 0)); attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs); @@ -4129,14 +3985,20 @@ str_collate (Lisp_Object s1, Lisp_Object s2, len = SCHARS (s1); i = i_byte = 0; SAFE_NALLOCA (p1, 1, len + 1); while (i < len) - FETCH_STRING_CHAR_ADVANCE (*(p1+i-1), s1, i, i_byte); - *(p1+len) = 0; + { + wchar_t *p = &p1[i]; + *p = fetch_string_char_advance (s1, &i, &i_byte); + } + p1[len] = 0; len = SCHARS (s2); i = i_byte = 0; SAFE_NALLOCA (p2, 1, len + 1); while (i < len) - FETCH_STRING_CHAR_ADVANCE (*(p2+i-1), s2, i, i_byte); - *(p2+len) = 0; + { + wchar_t *p = &p2[i]; + *p = fetch_string_char_advance (s2, &i, &i_byte); + } + p2[len] = 0; if (STRINGP (locale)) { |