X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/c69aef14ddc150da07dcd3527b5a9fb99d6cef34..63750fd4ed4ff8bb9b3ff8868d4e36e3422adb21:/src/sysdep.c diff --git a/src/sysdep.c b/src/sysdep.c index a01bf1d7c1..16541735f0 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -6,8 +6,8 @@ This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -107,7 +107,6 @@ along with GNU Emacs. If not, see . */ /* In process.h which conflicts with the local copy. */ #define _P_WAIT 0 int _cdecl _spawnlp (int, const char *, const char *, ...); -int _cdecl _getpid (void); /* The following is needed for O_CLOEXEC, F_SETFD, FD_CLOEXEC, and several prototypes of functions called below. */ #include @@ -130,6 +129,77 @@ static const int baud_convert[] = 1800, 2400, 4800, 9600, 19200, 38400 }; +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE +# include + +/* Disable address randomization in the current process. Return true + if addresses were randomized but this has been disabled, false + otherwise. */ +bool +disable_address_randomization (void) +{ + bool disabled = false; + int pers = personality (0xffffffff); + disabled = (! (pers & ADDR_NO_RANDOMIZE) + && 0 <= personality (pers | ADDR_NO_RANDOMIZE)); + return disabled; +} +#endif + +/* 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 + on error it returns an error number rather than -1. */ +int +emacs_exec_file (char const *file, char *const *argv, char *const *envp) +{ +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE + int pers = getenv ("EMACS_HEAP_EXEC") ? personality (0xffffffff) : -1; + bool change_personality = 0 <= pers && pers & ADDR_NO_RANDOMIZE; + if (change_personality) + personality (pers & ~ADDR_NO_RANDOMIZE); +#endif + + execve (file, argv, envp); + int err = errno; + +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE + if (change_personality) + personality (pers); +#endif + + return err; +} + +/* If FD is not already open, arrange for it to be open with FLAGS. */ +static void +force_open (int fd, int flags) +{ + if (dup2 (fd, fd) < 0 && errno == EBADF) + { + int n = open (NULL_DEVICE, flags); + if (n < 0 || (fd != n && (dup2 (n, fd) < 0 || emacs_close (n) != 0))) + { + emacs_perror (NULL_DEVICE); + exit (EXIT_FAILURE); + } + } +} + +/* Make sure stdin, stdout, and stderr are open to something, so that + their file descriptors are not hijacked by later system calls. */ +void +init_standard_fds (void) +{ + /* Open stdin for *writing*, and stdout and stderr for *reading*. + That way, any attempt to do normal I/O will result in an error, + just as if the files were closed, and the file descriptors will + not be reused by later opens. */ + force_open (STDIN_FILENO, O_WRONLY); + force_open (STDOUT_FILENO, O_RDONLY); + force_open (STDERR_FILENO, O_RDONLY); +} + /* Return the current working directory. The result should be freed with 'free'. Return NULL on errors. */ char * @@ -478,15 +548,16 @@ void sys_subshell (void) { #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */ - int st; #ifdef MSDOS + int st; char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */ #else char oldwd[MAX_UTF8_PATH]; -#endif +#endif /* MSDOS */ +#else /* !DOS_NT */ + int status; #endif pid_t pid; - int status; struct save_signal saved_handlers[5]; char *str = SSDATA (encode_current_directory ()); @@ -909,7 +980,9 @@ void init_sys_modes (struct tty_display_info *tty_out) { struct emacs_tty tty; +#ifndef DOS_NT Lisp_Object terminal; +#endif Vtty_erase_char = Qnil; @@ -2119,7 +2192,7 @@ init_random (void) { bool success = false; #ifndef WINDOWSNT - int fd = emacs_open ("/dev/urandom", O_RDONLY | O_BINARY, 0); + int fd = emacs_open ("/dev/urandom", O_RDONLY, 0); if (0 <= fd) { success = emacs_read (fd, &v, sizeof v) == sizeof v; @@ -2299,7 +2372,6 @@ emacs_fopen (char const *file, char const *mode) switch (*m++) { case '+': omode = O_RDWR; break; - case 'b': bflag = O_BINARY; break; case 't': bflag = O_TEXT; break; default: /* Ignore. */ break; } @@ -2468,7 +2540,7 @@ void emacs_perror (char const *message) { int err = errno; - char const *error_string = strerror (err); + char const *error_string = emacs_strerror (err); char const *command = (initial_argv && initial_argv[0] ? initial_argv[0] : "emacs"); /* Write it out all at once, if it's short; this is less likely to @@ -3021,7 +3093,7 @@ system_process_attributes (Lisp_Object pid) struct timespec tnow, tstart, tboot, telapsed, us_time; double pcpu, pmem; Lisp_Object attrs = Qnil; - Lisp_Object cmd_str, decoded_cmd; + Lisp_Object decoded_cmd; ptrdiff_t count; CHECK_NUMBER_OR_FLOAT (pid); @@ -3078,7 +3150,7 @@ system_process_attributes (Lisp_Object pid) else q = NULL; /* Command name is encoded in locale-coding-system; decode it. */ - cmd_str = make_unibyte_string (cmd, cmdsize); + AUTO_STRING_WITH_LEN (cmd_str, cmd, cmdsize); decoded_cmd = code_convert_string_norecord (cmd_str, Vlocale_coding_system, 0); attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs); @@ -3211,7 +3283,7 @@ system_process_attributes (Lisp_Object pid) sprintf (cmdline, "[%.*s]", cmdsize, cmd); } /* Command line is encoded in locale-coding-system; decode it. */ - cmd_str = make_unibyte_string (q, nread); + AUTO_STRING_WITH_LEN (cmd_str, q, nread); decoded_cmd = code_convert_string_norecord (cmd_str, Vlocale_coding_system, 0); unbind_to (count, Qnil); @@ -3346,13 +3418,13 @@ system_process_attributes (Lisp_Object pid) make_float (100.0 / 0x8000 * pinfo.pr_pctmem)), attrs); - decoded_cmd = (code_convert_string_norecord - (build_unibyte_string (pinfo.pr_fname), - Vlocale_coding_system, 0)); + AUTO_STRING (fname, pinfo.pr_fname); + decoded_cmd = code_convert_string_norecord (fname, + Vlocale_coding_system, 0); attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs); - decoded_cmd = (code_convert_string_norecord - (build_unibyte_string (pinfo.pr_psargs), - Vlocale_coding_system, 0)); + AUTO_STRING (psargs, pinfo.pr_psargs); + decoded_cmd = code_convert_string_norecord (psargs, + Vlocale_coding_system, 0); attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs); } unbind_to (count, Qnil); @@ -3417,9 +3489,8 @@ system_process_attributes (Lisp_Object pid) if (gr) attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); - decoded_comm = (code_convert_string_norecord - (build_unibyte_string (proc.ki_comm), - Vlocale_coding_system, 0)); + AUTO_STRING (comm, proc.ki_comm); + decoded_comm = code_convert_string_norecord (comm, Vlocale_coding_system, 0); attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs); { @@ -3530,10 +3601,9 @@ system_process_attributes (Lisp_Object pid) args[i] = ' '; } - decoded_comm = - (code_convert_string_norecord - (build_unibyte_string (args), - Vlocale_coding_system, 0)); + AUTO_STRING (comm, args); + decoded_comm = code_convert_string_norecord (comm, + Vlocale_coding_system, 0); attrs = Fcons (Fcons (Qargs, decoded_comm), attrs); } @@ -3541,6 +3611,146 @@ system_process_attributes (Lisp_Object pid) return attrs; } +#elif defined DARWIN_OS + +static struct timespec +timeval_to_timespec (struct timeval t) +{ + return make_timespec (t.tv_sec, t.tv_usec * 1000); +} + +static Lisp_Object +make_lisp_timeval (struct timeval t) +{ + return make_lisp_time (timeval_to_timespec (t)); +} + +Lisp_Object +system_process_attributes (Lisp_Object pid) +{ + int proc_id; + int pagesize = getpagesize (); + unsigned long npages; + int fscale; + struct passwd *pw; + struct group *gr; + char *ttyname; + size_t len; + char args[MAXPATHLEN]; + struct timeval starttime; + struct timespec t, now; + struct rusage *rusage; + dev_t tdev; + uid_t uid; + gid_t gid; + + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID}; + struct kinfo_proc proc; + size_t proclen = sizeof proc; + + 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; + + uid = proc.kp_eproc.e_ucred.cr_uid; + attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs); + + block_input (); + pw = getpwuid (uid); + unblock_input (); + if (pw) + attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs); + + gid = proc.kp_eproc.e_pcred.p_svgid; + attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs); + + block_input (); + gr = getgrgid (gid); + unblock_input (); + if (gr) + attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs); + + decoded_comm = (code_convert_string_norecord + (build_unibyte_string (proc.kp_proc.p_comm), + Vlocale_coding_system, 0)); + + attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs); + { + char state[2] = {'\0', '\0'}; + switch (proc.kp_proc.p_stat) + { + case SRUN: + state[0] = 'R'; + break; + + case SSLEEP: + state[0] = 'S'; + break; + + case SZOMB: + state[0] = 'Z'; + break; + + case SSTOP: + state[0] = 'T'; + break; + + case SIDL: + state[0] = 'I'; + break; + } + attrs = Fcons (Fcons (Qstate, build_string (state)), attrs); + } + + attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (proc.kp_eproc.e_ppid)), + attrs); + attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (proc.kp_eproc.e_pgid)), + attrs); + + tdev = proc.kp_eproc.e_tdev; + block_input (); + ttyname = tdev == NODEV ? NULL : devname (tdev, S_IFCHR); + unblock_input (); + if (ttyname) + attrs = Fcons (Fcons (Qtty, build_string (ttyname)), attrs); + + attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (proc.kp_eproc.e_tpgid)), + attrs); + + rusage = proc.kp_proc.p_ru; + if (rusage) + { + attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (rusage->ru_minflt)), + attrs); + attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (rusage->ru_majflt)), + attrs); + + attrs = Fcons (Fcons (Qutime, make_lisp_timeval (rusage->ru_utime)), + attrs); + attrs = Fcons (Fcons (Qstime, make_lisp_timeval (rusage->ru_stime)), + attrs); + t = timespec_add (timeval_to_timespec (rusage->ru_utime), + timeval_to_timespec (rusage->ru_stime)); + attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs); + } + + starttime = proc.kp_proc.p_starttime; + attrs = Fcons (Fcons (Qnice, make_number (proc.kp_proc.p_nice)), attrs); + attrs = Fcons (Fcons (Qstart, make_lisp_timeval (starttime)), attrs); + + now = current_timespec (); + t = timespec_sub (now, timeval_to_timespec (starttime)); + attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs); + + return attrs; +} + /* The WINDOWSNT implementation is in w32.c. The MSDOS implementation is in dosfns.c. */ #elif !defined (WINDOWSNT) && !defined (MSDOS) @@ -3697,7 +3907,7 @@ str_collate (Lisp_Object s1, Lisp_Object s2, locale_t loc = newlocale (LC_COLLATE_MASK | LC_CTYPE_MASK, SSDATA (locale), 0); if (!loc) - error ("Invalid locale %s: %s", SSDATA (locale), strerror (errno)); + error ("Invalid locale %s: %s", SSDATA (locale), emacs_strerror (errno)); if (! NILP (ignore_case)) for (int i = 1; i < 3; i++) @@ -3728,10 +3938,10 @@ str_collate (Lisp_Object s1, Lisp_Object s2, } # ifndef HAVE_NEWLOCALE if (err) - error ("Invalid locale or string for collation: %s", strerror (err)); + error ("Invalid locale or string for collation: %s", emacs_strerror (err)); # else if (err) - error ("Invalid string for collation: %s", strerror (err)); + error ("Invalid string for collation: %s", emacs_strerror (err)); # endif SAFE_FREE (); @@ -3749,7 +3959,7 @@ str_collate (Lisp_Object s1, Lisp_Object s2, int res, err = errno; errno = 0; - res = w32_compare_strings (SDATA (s1), SDATA (s2), loc, !NILP (ignore_case)); + res = w32_compare_strings (SSDATA (s1), SSDATA (s2), loc, !NILP (ignore_case)); if (errno) error ("Invalid string for collation: %s", strerror (errno));