]> code.delx.au - gnu-emacs/blobdiff - src/sysdep.c
Fix port to glibc 2.24 (pre-release) + ppc64
[gnu-emacs] / src / sysdep.c
index a01bf1d7c100d1066257cf458f1c2492b5ca5b6c..16541735f036ec31a466411727d5eea3aa856742 100644 (file)
@@ -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 <http://www.gnu.org/licenses/>.  */
 /* 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 <sys/socket.h>
@@ -130,6 +129,77 @@ static const int baud_convert[] =
     1800, 2400, 4800, 9600, 19200, 38400
   };
 
+#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
+# include <sys/personality.h>
+
+/* 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));