Ruby  2.5.0dev(2017-10-22revision60238)
process.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  process.c -
4 
5  $Author$
6  created at: Tue Aug 10 14:30:50 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9  Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10  Copyright (C) 2000 Information-technology Promotion Agency, Japan
11 
12 **********************************************************************/
13 
14 #include "internal.h"
15 #include "ruby/io.h"
16 #include "ruby/thread.h"
17 #include "ruby/util.h"
18 #include "vm_core.h"
19 
20 #include <stdio.h>
21 #include <errno.h>
22 #include <signal.h>
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #ifdef HAVE_FCNTL_H
30 #include <fcntl.h>
31 #endif
32 #ifdef HAVE_PROCESS_H
33 #include <process.h>
34 #endif
35 
36 #include <time.h>
37 #include <ctype.h>
38 
39 #ifndef EXIT_SUCCESS
40 #define EXIT_SUCCESS 0
41 #endif
42 #ifndef EXIT_FAILURE
43 #define EXIT_FAILURE 1
44 #endif
45 
46 #ifdef HAVE_SYS_WAIT_H
47 # include <sys/wait.h>
48 #endif
49 #ifdef HAVE_SYS_RESOURCE_H
50 # include <sys/resource.h>
51 #endif
52 #ifdef HAVE_VFORK_H
53 # include <vfork.h>
54 #endif
55 #ifdef HAVE_SYS_PARAM_H
56 # include <sys/param.h>
57 #endif
58 #ifndef MAXPATHLEN
59 # define MAXPATHLEN 1024
60 #endif
61 #include "ruby/st.h"
62 
63 #include <sys/stat.h>
64 #if defined(__native_client__) && defined(NACL_NEWLIB)
65 # include <sys/unistd.h>
66 # include "nacl/stat.h"
67 # include "nacl/unistd.h"
68 # include "nacl/resource.h"
69 # undef HAVE_ISSETUGID
70 #endif
71 
72 #ifdef HAVE_SYS_TIME_H
73 #include <sys/time.h>
74 #endif
75 #ifdef HAVE_SYS_TIMES_H
76 #include <sys/times.h>
77 #endif
78 
79 #ifdef HAVE_PWD_H
80 #include <pwd.h>
81 #endif
82 #ifdef HAVE_GRP_H
83 #include <grp.h>
84 # ifdef __CYGWIN__
85 int initgroups(const char *, rb_gid_t);
86 # endif
87 #endif
88 #ifdef HAVE_SYS_ID_H
89 #include <sys/id.h>
90 #endif
91 
92 #ifdef __APPLE__
93 # include <mach/mach_time.h>
94 #endif
95 
96 /* define system APIs */
97 #ifdef _WIN32
98 #undef open
99 #define open rb_w32_uopen
100 #endif
101 
102 #if defined(HAVE_TIMES) || defined(_WIN32)
103 static VALUE rb_cProcessTms;
104 #endif
105 
106 #ifndef WIFEXITED
107 #define WIFEXITED(w) (((w) & 0xff) == 0)
108 #endif
109 #ifndef WIFSIGNALED
110 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
111 #endif
112 #ifndef WIFSTOPPED
113 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
114 #endif
115 #ifndef WEXITSTATUS
116 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
117 #endif
118 #ifndef WTERMSIG
119 #define WTERMSIG(w) ((w) & 0x7f)
120 #endif
121 #ifndef WSTOPSIG
122 #define WSTOPSIG WEXITSTATUS
123 #endif
124 
125 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
126 #define HAVE_44BSD_SETUID 1
127 #define HAVE_44BSD_SETGID 1
128 #endif
129 
130 #ifdef __NetBSD__
131 #undef HAVE_SETRUID
132 #undef HAVE_SETRGID
133 #endif
134 
135 #ifdef BROKEN_SETREUID
136 #define setreuid ruby_setreuid
137 int setreuid(rb_uid_t ruid, rb_uid_t euid);
138 #endif
139 #ifdef BROKEN_SETREGID
140 #define setregid ruby_setregid
141 int setregid(rb_gid_t rgid, rb_gid_t egid);
142 #endif
143 
144 #if defined(HAVE_44BSD_SETUID) || defined(__APPLE__)
145 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
146 #define OBSOLETE_SETREUID 1
147 #endif
148 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
149 #define OBSOLETE_SETREGID 1
150 #endif
151 #endif
152 
153 #define preserving_errno(stmts) \
154  do {int saved_errno = errno; stmts; errno = saved_errno;} while (0)
155 
156 static void check_uid_switch(void);
157 static void check_gid_switch(void);
158 
159 #if 1
160 #define p_uid_from_name p_uid_from_name
161 #define p_gid_from_name p_gid_from_name
162 #endif
163 
164 #if defined(HAVE_PWD_H)
165 # if defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
166 # define USE_GETPWNAM_R 1
167 # define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX)
168 # define GETPW_R_SIZE_DEFAULT 0x1000
169 # define GETPW_R_SIZE_LIMIT 0x10000
170 # endif
171 # ifdef USE_GETPWNAM_R
172 # define PREPARE_GETPWNAM \
173  VALUE getpw_buf = 0
174 # define FINISH_GETPWNAM \
175  (getpw_buf ? (void)rb_str_resize(getpw_buf, 0) : (void)0)
176 # define OBJ2UID1(id) obj2uid((id), &getpw_buf)
177 # define OBJ2UID(id) obj2uid0(id)
178 static rb_uid_t obj2uid(VALUE id, VALUE *getpw_buf);
179 static inline rb_uid_t
180 obj2uid0(VALUE id)
181 {
182  rb_uid_t uid;
184  uid = OBJ2UID1(id);
186  return uid;
187 }
188 # else
189 # define PREPARE_GETPWNAM /* do nothing */
190 # define FINISH_GETPWNAM /* do nothing */
191 # define OBJ2UID1(id) obj2uid((id))
192 # define OBJ2UID(id) obj2uid((id))
193 static rb_uid_t obj2uid(VALUE id);
194 # endif
195 #else
196 # define PREPARE_GETPWNAM /* do nothing */
197 # define FINISH_GETPWNAM /* do nothing */
198 # define OBJ2UID1(id) NUM2UIDT(id)
199 # define OBJ2UID(id) NUM2UIDT(id)
200 # ifdef p_uid_from_name
201 # undef p_uid_from_name
202 # define p_uid_from_name rb_f_notimplement
203 # endif
204 #endif
205 
206 #if defined(HAVE_GRP_H)
207 # if defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
208 # define USE_GETGRNAM_R
209 # define GETGR_R_SIZE_INIT sysconf(_SC_GETGR_R_SIZE_MAX)
210 # define GETGR_R_SIZE_DEFAULT 0x1000
211 # define GETGR_R_SIZE_LIMIT 0x10000
212 # endif
213 # ifdef USE_GETGRNAM_R
214 # define PREPARE_GETGRNAM \
215  VALUE getgr_buf = 0
216 # define FINISH_GETGRNAM \
217  (getgr_buf ? (void)rb_str_resize(getgr_buf, 0) : (void)0)
218 # define OBJ2GID1(id) obj2gid((id), &getgr_buf)
219 # define OBJ2GID(id) obj2gid0(id)
220 static rb_gid_t obj2gid(VALUE id, VALUE *getgr_buf);
221 static inline rb_gid_t
222 obj2gid0(VALUE id)
223 {
224  rb_gid_t gid;
226  gid = OBJ2GID1(id);
228  return gid;
229 }
230 static rb_gid_t obj2gid(VALUE id, VALUE *getgr_buf);
231 # else
232 # define PREPARE_GETGRNAM /* do nothing */
233 # define FINISH_GETGRNAM /* do nothing */
234 # define OBJ2GID1(id) obj2gid((id))
235 # define OBJ2GID(id) obj2gid((id))
236 static rb_gid_t obj2gid(VALUE id);
237 # endif
238 #else
239 # define PREPARE_GETGRNAM /* do nothing */
240 # define FINISH_GETGRNAM /* do nothing */
241 # define OBJ2GID1(id) NUM2GIDT(id)
242 # define OBJ2GID(id) NUM2GIDT(id)
243 # ifdef p_gid_from_name
244 # undef p_gid_from_name
245 # define p_gid_from_name rb_f_notimplement
246 # endif
247 #endif
248 
249 #if SIZEOF_CLOCK_T == SIZEOF_INT
250 typedef unsigned int unsigned_clock_t;
251 #elif SIZEOF_CLOCK_T == SIZEOF_LONG
252 typedef unsigned long unsigned_clock_t;
253 #elif defined(HAVE_LONG_LONG) && SIZEOF_CLOCK_T == SIZEOF_LONG_LONG
254 typedef unsigned LONG_LONG unsigned_clock_t;
255 #endif
256 #ifndef HAVE_SIG_T
257 typedef void (*sig_t) (int);
258 #endif
259 
260 static ID id_in, id_out, id_err, id_pid, id_uid, id_gid;
261 static ID id_close, id_child;
262 #ifdef HAVE_SETPGID
263 static ID id_pgroup;
264 #endif
265 #ifdef _WIN32
266 static ID id_new_pgroup;
267 #endif
268 static ID id_unsetenv_others, id_chdir, id_umask, id_close_others, id_ENV;
269 static ID id_nanosecond, id_microsecond, id_millisecond, id_second;
270 static ID id_float_microsecond, id_float_millisecond, id_float_second;
271 static ID id_GETTIMEOFDAY_BASED_CLOCK_REALTIME, id_TIME_BASED_CLOCK_REALTIME;
272 #ifdef HAVE_TIMES
273 static ID id_TIMES_BASED_CLOCK_MONOTONIC;
274 static ID id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID;
275 #endif
276 #ifdef RUSAGE_SELF
277 static ID id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID;
278 #endif
279 static ID id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID;
280 #ifdef __APPLE__
281 static ID id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC;
282 #endif
283 static ID id_hertz;
285 #define id_status ruby_static_id_status
286 
287 /* execv and execl are async-signal-safe since SUSv4 (POSIX.1-2008, XPG7) */
288 #if defined(__sun) && !defined(_XPG7) /* Solaris 10, 9, ... */
289 #define execv(path, argv) (rb_async_bug_errno("unreachable: async-signal-unsafe execv() is called", 0))
290 #define execl(path, arg0, arg1, arg2, term) do { extern char **environ; execle((path), (arg0), (arg1), (arg2), (term), (environ)); } while (0)
291 #define ALWAYS_NEED_ENVP 1
292 #else
293 #define ALWAYS_NEED_ENVP 0
294 #endif
295 
296 static inline int
297 close_unless_reserved(int fd)
298 {
299  /* We should not have reserved FDs at this point */
300  if (rb_reserved_fd_p(fd)) { /* async-signal-safe */
301  rb_async_bug_errno("BUG timer thread still running", 0 /* EDOOFUS */);
302  return 0;
303  }
304  return close(fd); /* async-signal-safe */
305 }
306 
307 /*#define DEBUG_REDIRECT*/
308 #if defined(DEBUG_REDIRECT)
309 
310 #include <stdarg.h>
311 
312 static void
313 ttyprintf(const char *fmt, ...)
314 {
315  va_list ap;
316  FILE *tty;
317  int save = errno;
318 #ifdef _WIN32
319  tty = fopen("con", "w");
320 #else
321  tty = fopen("/dev/tty", "w");
322 #endif
323  if (!tty)
324  return;
325 
326  va_start(ap, fmt);
327  vfprintf(tty, fmt, ap);
328  va_end(ap);
329  fclose(tty);
330  errno = save;
331 }
332 
333 static int
334 redirect_dup(int oldfd)
335 {
336  int ret;
337  ret = dup(oldfd);
338  ttyprintf("dup(%d) => %d\n", oldfd, ret);
339  return ret;
340 }
341 
342 static int
343 redirect_dup2(int oldfd, int newfd)
344 {
345  int ret;
346  ret = dup2(oldfd, newfd);
347  ttyprintf("dup2(%d, %d) => %d\n", oldfd, newfd, ret);
348  return ret;
349 }
350 
351 static int
352 redirect_cloexec_dup(int oldfd)
353 {
354  int ret;
355  ret = rb_cloexec_dup(oldfd);
356  ttyprintf("cloexec_dup(%d) => %d\n", oldfd, ret);
357  return ret;
358 }
359 
360 static int
361 redirect_cloexec_dup2(int oldfd, int newfd)
362 {
363  int ret;
364  ret = rb_cloexec_dup2(oldfd, newfd);
365  ttyprintf("cloexec_dup2(%d, %d) => %d\n", oldfd, newfd, ret);
366  return ret;
367 }
368 
369 static int
370 redirect_close(int fd)
371 {
372  int ret;
373  ret = close_unless_reserved(fd);
374  ttyprintf("close(%d) => %d\n", fd, ret);
375  return ret;
376 }
377 
378 static int
379 parent_redirect_open(const char *pathname, int flags, mode_t perm)
380 {
381  int ret;
382  ret = rb_cloexec_open(pathname, flags, perm);
383  ttyprintf("parent_open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
384  return ret;
385 }
386 
387 static int
388 parent_redirect_close(int fd)
389 {
390  int ret;
391  ret = close_unless_reserved(fd);
392  ttyprintf("parent_close(%d) => %d\n", fd, ret);
393  return ret;
394 }
395 
396 #else
397 #define redirect_dup(oldfd) dup(oldfd)
398 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
399 #define redirect_cloexec_dup(oldfd) rb_cloexec_dup(oldfd)
400 #define redirect_cloexec_dup2(oldfd, newfd) rb_cloexec_dup2((oldfd), (newfd))
401 #define redirect_close(fd) close_unless_reserved(fd)
402 #define parent_redirect_open(pathname, flags, perm) rb_cloexec_open((pathname), (flags), (perm))
403 #define parent_redirect_close(fd) close_unless_reserved(fd)
404 #endif
405 
406 /*
407  * call-seq:
408  * Process.pid -> integer
409  *
410  * Returns the process id of this process. Not available on all
411  * platforms.
412  *
413  * Process.pid #=> 27415
414  */
415 
416 static VALUE
417 get_pid(void)
418 {
419  return PIDT2NUM(getpid());
420 }
421 
422 
423 /*
424  * call-seq:
425  * Process.ppid -> integer
426  *
427  * Returns the process id of the parent of this process. Returns
428  * untrustworthy value on Win32/64. Not available on all platforms.
429  *
430  * puts "I am #{Process.pid}"
431  * Process.fork { puts "Dad is #{Process.ppid}" }
432  *
433  * <em>produces:</em>
434  *
435  * I am 27417
436  * Dad is 27417
437  */
438 
439 static VALUE
440 get_ppid(void)
441 {
442  return PIDT2NUM(getppid());
443 }
444 
445 
446 /*********************************************************************
447  *
448  * Document-class: Process::Status
449  *
450  * <code>Process::Status</code> encapsulates the information on the
451  * status of a running or terminated system process. The built-in
452  * variable <code>$?</code> is either +nil+ or a
453  * <code>Process::Status</code> object.
454  *
455  * fork { exit 99 } #=> 26557
456  * Process.wait #=> 26557
457  * $?.class #=> Process::Status
458  * $?.to_i #=> 25344
459  * $? >> 8 #=> 99
460  * $?.stopped? #=> false
461  * $?.exited? #=> true
462  * $?.exitstatus #=> 99
463  *
464  * Posix systems record information on processes using a 16-bit
465  * integer. The lower bits record the process status (stopped,
466  * exited, signaled) and the upper bits possibly contain additional
467  * information (for example the program's return code in the case of
468  * exited processes). Pre Ruby 1.8, these bits were exposed directly
469  * to the Ruby program. Ruby now encapsulates these in a
470  * <code>Process::Status</code> object. To maximize compatibility,
471  * however, these objects retain a bit-oriented interface. In the
472  * descriptions that follow, when we talk about the integer value of
473  * _stat_, we're referring to this 16 bit value.
474  */
475 
476 static VALUE rb_cProcessStatus;
477 
478 VALUE
480 {
481  return GET_THREAD()->last_status;
482 }
483 
484 void
485 rb_last_status_set(int status, rb_pid_t pid)
486 {
487  rb_thread_t *th = GET_THREAD();
488  th->last_status = rb_obj_alloc(rb_cProcessStatus);
489  rb_ivar_set(th->last_status, id_status, INT2FIX(status));
490  rb_ivar_set(th->last_status, id_pid, PIDT2NUM(pid));
491 }
492 
493 void
495 {
496  GET_THREAD()->last_status = Qnil;
497 }
498 
499 /*
500  * call-seq:
501  * stat.to_i -> integer
502  * stat.to_int -> integer
503  *
504  * Returns the bits in _stat_ as a <code>Integer</code>. Poking
505  * around in these bits is platform dependent.
506  *
507  * fork { exit 0xab } #=> 26566
508  * Process.wait #=> 26566
509  * sprintf('%04x', $?.to_i) #=> "ab00"
510  */
511 
512 static VALUE
513 pst_to_i(VALUE st)
514 {
515  return rb_ivar_get(st, id_status);
516 }
517 
518 #define PST2INT(st) NUM2INT(pst_to_i(st))
519 
520 /*
521  * call-seq:
522  * stat.pid -> integer
523  *
524  * Returns the process ID that this status object represents.
525  *
526  * fork { exit } #=> 26569
527  * Process.wait #=> 26569
528  * $?.pid #=> 26569
529  */
530 
531 static VALUE
532 pst_pid(VALUE st)
533 {
534  return rb_attr_get(st, id_pid);
535 }
536 
537 static void
538 pst_message(VALUE str, rb_pid_t pid, int status)
539 {
540  rb_str_catf(str, "pid %ld", (long)pid);
541  if (WIFSTOPPED(status)) {
542  int stopsig = WSTOPSIG(status);
543  const char *signame = ruby_signal_name(stopsig);
544  if (signame) {
545  rb_str_catf(str, " stopped SIG%s (signal %d)", signame, stopsig);
546  }
547  else {
548  rb_str_catf(str, " stopped signal %d", stopsig);
549  }
550  }
551  if (WIFSIGNALED(status)) {
552  int termsig = WTERMSIG(status);
553  const char *signame = ruby_signal_name(termsig);
554  if (signame) {
555  rb_str_catf(str, " SIG%s (signal %d)", signame, termsig);
556  }
557  else {
558  rb_str_catf(str, " signal %d", termsig);
559  }
560  }
561  if (WIFEXITED(status)) {
562  rb_str_catf(str, " exit %d", WEXITSTATUS(status));
563  }
564 #ifdef WCOREDUMP
565  if (WCOREDUMP(status)) {
566  rb_str_cat2(str, " (core dumped)");
567  }
568 #endif
569 }
570 
571 
572 /*
573  * call-seq:
574  * stat.to_s -> string
575  *
576  * Show pid and exit status as a string.
577  *
578  * system("false")
579  * p $?.to_s #=> "pid 12766 exit 1"
580  *
581  */
582 
583 static VALUE
584 pst_to_s(VALUE st)
585 {
586  rb_pid_t pid;
587  int status;
588  VALUE str;
589 
590  pid = NUM2PIDT(pst_pid(st));
591  status = PST2INT(st);
592 
593  str = rb_str_buf_new(0);
594  pst_message(str, pid, status);
595  return str;
596 }
597 
598 
599 /*
600  * call-seq:
601  * stat.inspect -> string
602  *
603  * Override the inspection method.
604  *
605  * system("false")
606  * p $?.inspect #=> "#<Process::Status: pid 12861 exit 1>"
607  *
608  */
609 
610 static VALUE
611 pst_inspect(VALUE st)
612 {
613  rb_pid_t pid;
614  int status;
615  VALUE vpid, str;
616 
617  vpid = pst_pid(st);
618  if (NIL_P(vpid)) {
619  return rb_sprintf("#<%s: uninitialized>", rb_class2name(CLASS_OF(st)));
620  }
621  pid = NUM2PIDT(vpid);
622  status = PST2INT(st);
623 
624  str = rb_sprintf("#<%s: ", rb_class2name(CLASS_OF(st)));
625  pst_message(str, pid, status);
626  rb_str_cat2(str, ">");
627  return str;
628 }
629 
630 
631 /*
632  * call-seq:
633  * stat == other -> true or false
634  *
635  * Returns +true+ if the integer value of _stat_
636  * equals <em>other</em>.
637  */
638 
639 static VALUE
640 pst_equal(VALUE st1, VALUE st2)
641 {
642  if (st1 == st2) return Qtrue;
643  return rb_equal(pst_to_i(st1), st2);
644 }
645 
646 
647 /*
648  * call-seq:
649  * stat & num -> integer
650  *
651  * Logical AND of the bits in _stat_ with <em>num</em>.
652  *
653  * fork { exit 0x37 }
654  * Process.wait
655  * sprintf('%04x', $?.to_i) #=> "3700"
656  * sprintf('%04x', $? & 0x1e00) #=> "1600"
657  */
658 
659 static VALUE
660 pst_bitand(VALUE st1, VALUE st2)
661 {
662  int status = PST2INT(st1) & NUM2INT(st2);
663 
664  return INT2NUM(status);
665 }
666 
667 
668 /*
669  * call-seq:
670  * stat >> num -> integer
671  *
672  * Shift the bits in _stat_ right <em>num</em> places.
673  *
674  * fork { exit 99 } #=> 26563
675  * Process.wait #=> 26563
676  * $?.to_i #=> 25344
677  * $? >> 8 #=> 99
678  */
679 
680 static VALUE
681 pst_rshift(VALUE st1, VALUE st2)
682 {
683  int status = PST2INT(st1) >> NUM2INT(st2);
684 
685  return INT2NUM(status);
686 }
687 
688 
689 /*
690  * call-seq:
691  * stat.stopped? -> true or false
692  *
693  * Returns +true+ if this process is stopped. This is only
694  * returned if the corresponding <code>wait</code> call had the
695  * <code>WUNTRACED</code> flag set.
696  */
697 
698 static VALUE
699 pst_wifstopped(VALUE st)
700 {
701  int status = PST2INT(st);
702 
703  if (WIFSTOPPED(status))
704  return Qtrue;
705  else
706  return Qfalse;
707 }
708 
709 
710 /*
711  * call-seq:
712  * stat.stopsig -> integer or nil
713  *
714  * Returns the number of the signal that caused _stat_ to stop
715  * (or +nil+ if self is not stopped).
716  */
717 
718 static VALUE
719 pst_wstopsig(VALUE st)
720 {
721  int status = PST2INT(st);
722 
723  if (WIFSTOPPED(status))
724  return INT2NUM(WSTOPSIG(status));
725  return Qnil;
726 }
727 
728 
729 /*
730  * call-seq:
731  * stat.signaled? -> true or false
732  *
733  * Returns +true+ if _stat_ terminated because of
734  * an uncaught signal.
735  */
736 
737 static VALUE
738 pst_wifsignaled(VALUE st)
739 {
740  int status = PST2INT(st);
741 
742  if (WIFSIGNALED(status))
743  return Qtrue;
744  else
745  return Qfalse;
746 }
747 
748 
749 /*
750  * call-seq:
751  * stat.termsig -> integer or nil
752  *
753  * Returns the number of the signal that caused _stat_ to
754  * terminate (or +nil+ if self was not terminated by an
755  * uncaught signal).
756  */
757 
758 static VALUE
759 pst_wtermsig(VALUE st)
760 {
761  int status = PST2INT(st);
762 
763  if (WIFSIGNALED(status))
764  return INT2NUM(WTERMSIG(status));
765  return Qnil;
766 }
767 
768 
769 /*
770  * call-seq:
771  * stat.exited? -> true or false
772  *
773  * Returns +true+ if _stat_ exited normally (for
774  * example using an <code>exit()</code> call or finishing the
775  * program).
776  */
777 
778 static VALUE
779 pst_wifexited(VALUE st)
780 {
781  int status = PST2INT(st);
782 
783  if (WIFEXITED(status))
784  return Qtrue;
785  else
786  return Qfalse;
787 }
788 
789 
790 /*
791  * call-seq:
792  * stat.exitstatus -> integer or nil
793  *
794  * Returns the least significant eight bits of the return code of
795  * _stat_. Only available if <code>exited?</code> is
796  * +true+.
797  *
798  * fork { } #=> 26572
799  * Process.wait #=> 26572
800  * $?.exited? #=> true
801  * $?.exitstatus #=> 0
802  *
803  * fork { exit 99 } #=> 26573
804  * Process.wait #=> 26573
805  * $?.exited? #=> true
806  * $?.exitstatus #=> 99
807  */
808 
809 static VALUE
810 pst_wexitstatus(VALUE st)
811 {
812  int status = PST2INT(st);
813 
814  if (WIFEXITED(status))
815  return INT2NUM(WEXITSTATUS(status));
816  return Qnil;
817 }
818 
819 
820 /*
821  * call-seq:
822  * stat.success? -> true, false or nil
823  *
824  * Returns +true+ if _stat_ is successful, +false+ if not.
825  * Returns +nil+ if <code>exited?</code> is not +true+.
826  */
827 
828 static VALUE
829 pst_success_p(VALUE st)
830 {
831  int status = PST2INT(st);
832 
833  if (!WIFEXITED(status))
834  return Qnil;
835  return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
836 }
837 
838 
839 /*
840  * call-seq:
841  * stat.coredump? -> true or false
842  *
843  * Returns +true+ if _stat_ generated a coredump
844  * when it terminated. Not available on all platforms.
845  */
846 
847 static VALUE
848 pst_wcoredump(VALUE st)
849 {
850 #ifdef WCOREDUMP
851  int status = PST2INT(st);
852 
853  if (WCOREDUMP(status))
854  return Qtrue;
855  else
856  return Qfalse;
857 #else
858  return Qfalse;
859 #endif
860 }
861 
862 struct waitpid_arg {
863  rb_pid_t pid;
864  int flags;
865  int *st;
866 };
867 
868 static rb_pid_t
869 do_waitpid(rb_pid_t pid, int *st, int flags)
870 {
871 #if defined HAVE_WAITPID
872  return waitpid(pid, st, flags);
873 #elif defined HAVE_WAIT4
874  return wait4(pid, st, flags, NULL);
875 #else
876 # error waitpid or wait4 is required.
877 #endif
878 }
879 
880 static void *
881 rb_waitpid_blocking(void *data)
882 {
883  struct waitpid_arg *arg = data;
884  rb_pid_t result = do_waitpid(arg->pid, arg->st, arg->flags);
885  return (void *)(VALUE)result;
886 }
887 
888 static rb_pid_t
889 do_waitpid_nonblocking(rb_pid_t pid, int *st, int flags)
890 {
891  void *result;
892  struct waitpid_arg arg;
893  arg.pid = pid;
894  arg.st = st;
895  arg.flags = flags;
896  result = rb_thread_call_without_gvl(rb_waitpid_blocking, &arg,
897  RUBY_UBF_PROCESS, 0);
898  return (rb_pid_t)(VALUE)result;
899 }
900 
901 rb_pid_t
902 rb_waitpid(rb_pid_t pid, int *st, int flags)
903 {
904  rb_pid_t result;
905 
906  if (flags & WNOHANG) {
907  result = do_waitpid(pid, st, flags);
908  }
909  else {
910  while ((result = do_waitpid_nonblocking(pid, st, flags)) < 0 &&
911  (errno == EINTR)) {
912  rb_thread_t *th = GET_THREAD();
913  RUBY_VM_CHECK_INTS(th);
914  }
915  }
916  if (result > 0) {
917  rb_last_status_set(*st, result);
918  }
919  return result;
920 }
921 
922 
923 /* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
924  has historically been documented as if it didn't take any arguments
925  despite the fact that it's just an alias for ::waitpid(). The way I
926  have it below is more truthful, but a little confusing.
927 
928  I also took the liberty of putting in the pid values, as they're
929  pretty useful, and it looked as if the original 'ri' output was
930  supposed to contain them after "[...]depending on the value of
931  aPid:".
932 
933  The 'ansi' and 'bs' formats of the ri output don't display the
934  definition list for some reason, but the plain text one does.
935  */
936 
937 /*
938  * call-seq:
939  * Process.wait() -> integer
940  * Process.wait(pid=-1, flags=0) -> integer
941  * Process.waitpid(pid=-1, flags=0) -> integer
942  *
943  * Waits for a child process to exit, returns its process id, and
944  * sets <code>$?</code> to a <code>Process::Status</code> object
945  * containing information on that process. Which child it waits on
946  * depends on the value of _pid_:
947  *
948  * > 0:: Waits for the child whose process ID equals _pid_.
949  *
950  * 0:: Waits for any child whose process group ID equals that of the
951  * calling process.
952  *
953  * -1:: Waits for any child process (the default if no _pid_ is
954  * given).
955  *
956  * < -1:: Waits for any child whose process group ID equals the absolute
957  * value of _pid_.
958  *
959  * The _flags_ argument may be a logical or of the flag values
960  * <code>Process::WNOHANG</code> (do not block if no child available)
961  * or <code>Process::WUNTRACED</code> (return stopped children that
962  * haven't been reported). Not all flags are available on all
963  * platforms, but a flag value of zero will work on all platforms.
964  *
965  * Calling this method raises a SystemCallError if there are no child
966  * processes. Not available on all platforms.
967  *
968  * include Process
969  * fork { exit 99 } #=> 27429
970  * wait #=> 27429
971  * $?.exitstatus #=> 99
972  *
973  * pid = fork { sleep 3 } #=> 27440
974  * Time.now #=> 2008-03-08 19:56:16 +0900
975  * waitpid(pid, Process::WNOHANG) #=> nil
976  * Time.now #=> 2008-03-08 19:56:16 +0900
977  * waitpid(pid, 0) #=> 27440
978  * Time.now #=> 2008-03-08 19:56:19 +0900
979  */
980 
981 static VALUE
982 proc_wait(int argc, VALUE *argv)
983 {
984  rb_pid_t pid;
985  int flags, status;
986 
987  flags = 0;
988  if (rb_check_arity(argc, 0, 2) == 0) {
989  pid = -1;
990  }
991  else {
992  VALUE vflags;
993  pid = NUM2PIDT(argv[0]);
994  if (argc == 2 && !NIL_P(vflags = argv[1])) {
995  flags = NUM2UINT(vflags);
996  }
997  }
998  if ((pid = rb_waitpid(pid, &status, flags)) < 0)
999  rb_sys_fail(0);
1000  if (pid == 0) {
1002  return Qnil;
1003  }
1004  return PIDT2NUM(pid);
1005 }
1006 
1007 
1008 /*
1009  * call-seq:
1010  * Process.wait2(pid=-1, flags=0) -> [pid, status]
1011  * Process.waitpid2(pid=-1, flags=0) -> [pid, status]
1012  *
1013  * Waits for a child process to exit (see Process::waitpid for exact
1014  * semantics) and returns an array containing the process id and the
1015  * exit status (a <code>Process::Status</code> object) of that
1016  * child. Raises a SystemCallError if there are no child processes.
1017  *
1018  * Process.fork { exit 99 } #=> 27437
1019  * pid, status = Process.wait2
1020  * pid #=> 27437
1021  * status.exitstatus #=> 99
1022  */
1023 
1024 static VALUE
1025 proc_wait2(int argc, VALUE *argv)
1026 {
1027  VALUE pid = proc_wait(argc, argv);
1028  if (NIL_P(pid)) return Qnil;
1029  return rb_assoc_new(pid, rb_last_status_get());
1030 }
1031 
1032 
1033 /*
1034  * call-seq:
1035  * Process.waitall -> [ [pid1,status1], ...]
1036  *
1037  * Waits for all children, returning an array of
1038  * _pid_/_status_ pairs (where _status_ is a
1039  * <code>Process::Status</code> object).
1040  *
1041  * fork { sleep 0.2; exit 2 } #=> 27432
1042  * fork { sleep 0.1; exit 1 } #=> 27433
1043  * fork { exit 0 } #=> 27434
1044  * p Process.waitall
1045  *
1046  * <em>produces</em>:
1047  *
1048  * [[30982, #<Process::Status: pid 30982 exit 0>],
1049  * [30979, #<Process::Status: pid 30979 exit 1>],
1050  * [30976, #<Process::Status: pid 30976 exit 2>]]
1051  */
1052 
1053 static VALUE
1054 proc_waitall(void)
1055 {
1056  VALUE result;
1057  rb_pid_t pid;
1058  int status;
1059 
1060  result = rb_ary_new();
1062 
1063  for (pid = -1;;) {
1064  pid = rb_waitpid(-1, &status, 0);
1065  if (pid == -1) {
1066  int e = errno;
1067  if (e == ECHILD)
1068  break;
1069  rb_syserr_fail(e, 0);
1070  }
1072  }
1073  return result;
1074 }
1075 
1076 static VALUE rb_cWaiter;
1077 
1078 static VALUE
1079 detach_process_pid(VALUE thread)
1080 {
1081  return rb_thread_local_aref(thread, id_pid);
1082 }
1083 
1084 static VALUE
1085 detach_process_watcher(void *arg)
1086 {
1087  rb_pid_t cpid, pid = (rb_pid_t)(VALUE)arg;
1088  int status;
1089 
1090  while ((cpid = rb_waitpid(pid, &status, 0)) == 0) {
1091  /* wait while alive */
1092  }
1093  return rb_last_status_get();
1094 }
1095 
1096 VALUE
1098 {
1099  VALUE watcher = rb_thread_create(detach_process_watcher, (void*)(VALUE)pid);
1100  rb_thread_local_aset(watcher, id_pid, PIDT2NUM(pid));
1101  RBASIC_SET_CLASS(watcher, rb_cWaiter);
1102  return watcher;
1103 }
1104 
1105 
1106 /*
1107  * call-seq:
1108  * Process.detach(pid) -> thread
1109  *
1110  * Some operating systems retain the status of terminated child
1111  * processes until the parent collects that status (normally using
1112  * some variant of <code>wait()</code>). If the parent never collects
1113  * this status, the child stays around as a <em>zombie</em> process.
1114  * <code>Process::detach</code> prevents this by setting up a
1115  * separate Ruby thread whose sole job is to reap the status of the
1116  * process _pid_ when it terminates. Use <code>detach</code>
1117  * only when you do not intend to explicitly wait for the child to
1118  * terminate.
1119  *
1120  * The waiting thread returns the exit status of the detached process
1121  * when it terminates, so you can use <code>Thread#join</code> to
1122  * know the result. If specified _pid_ is not a valid child process
1123  * ID, the thread returns +nil+ immediately.
1124  *
1125  * The waiting thread has <code>pid</code> method which returns the pid.
1126  *
1127  * In this first example, we don't reap the first child process, so
1128  * it appears as a zombie in the process status display.
1129  *
1130  * p1 = fork { sleep 0.1 }
1131  * p2 = fork { sleep 0.2 }
1132  * Process.waitpid(p2)
1133  * sleep 2
1134  * system("ps -ho pid,state -p #{p1}")
1135  *
1136  * <em>produces:</em>
1137  *
1138  * 27389 Z
1139  *
1140  * In the next example, <code>Process::detach</code> is used to reap
1141  * the child automatically.
1142  *
1143  * p1 = fork { sleep 0.1 }
1144  * p2 = fork { sleep 0.2 }
1145  * Process.detach(p1)
1146  * Process.waitpid(p2)
1147  * sleep 2
1148  * system("ps -ho pid,state -p #{p1}")
1149  *
1150  * <em>(produces no output)</em>
1151  */
1152 
1153 static VALUE
1154 proc_detach(VALUE obj, VALUE pid)
1155 {
1156  return rb_detach_process(NUM2PIDT(pid));
1157 }
1158 
1159 /* This function should be async-signal-safe. Actually it is. */
1160 static void
1161 before_exec_async_signal_safe(void)
1162 {
1163 }
1164 
1165 static void
1166 before_exec_non_async_signal_safe(void)
1167 {
1168  /*
1169  * On Mac OS X 10.5.x (Leopard) or earlier, exec() may return ENOTSUP
1170  * if the process have multiple threads. Therefore we have to kill
1171  * internal threads temporary. [ruby-core:10583]
1172  * This is also true on Haiku. It returns Errno::EPERM against exec()
1173  * in multiple threads.
1174  *
1175  * Nowadays, we always stop the timer thread completely to allow redirects.
1176  */
1178 }
1179 
1180 static void
1181 before_exec(void)
1182 {
1183  before_exec_non_async_signal_safe();
1184  before_exec_async_signal_safe();
1185 }
1186 
1187 /* This function should be async-signal-safe. Actually it is. */
1188 static void
1189 after_exec_async_signal_safe(void)
1190 {
1191 }
1192 
1193 static void
1194 after_exec_non_async_signal_safe(void)
1195 {
1198 }
1199 
1200 static void
1201 after_exec(void)
1202 {
1203  after_exec_async_signal_safe();
1204  after_exec_non_async_signal_safe();
1205 }
1206 
1207 #define before_fork_ruby() before_exec()
1208 #define after_fork_ruby() (rb_threadptr_pending_interrupt_clear(GET_THREAD()), after_exec())
1209 
1210 #include "dln.h"
1211 
1212 static void
1213 security(const char *str)
1214 {
1215  if (rb_env_path_tainted()) {
1216  if (rb_safe_level() > 0) {
1217  rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
1218  }
1219  }
1220 }
1221 
1222 #if defined(HAVE_WORKING_FORK) && !defined(__native_client__)
1223 
1224 /* try_with_sh and exec_with_sh should be async-signal-safe. Actually it is.*/
1225 #define try_with_sh(prog, argv, envp) ((saved_errno == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0)
1226 static void
1227 exec_with_sh(const char *prog, char **argv, char **envp)
1228 {
1229  *argv = (char *)prog;
1230  *--argv = (char *)"sh";
1231  if (envp)
1232  execve("/bin/sh", argv, envp); /* async-signal-safe */
1233  else
1234  execv("/bin/sh", argv); /* async-signal-safe (since SUSv4) */
1235 }
1236 
1237 #else
1238 #define try_with_sh(prog, argv, envp) (void)0
1239 #endif
1240 
1241 /* This function should be async-signal-safe. Actually it is. */
1242 static int
1243 proc_exec_cmd(const char *prog, VALUE argv_str, VALUE envp_str)
1244 {
1245 #ifdef __native_client__
1246  rb_notimplement();
1247  UNREACHABLE;
1248 #else
1249  char **argv;
1250 #ifndef _WIN32
1251  char **envp;
1252 #endif
1253 
1254  argv = ARGVSTR2ARGV(argv_str);
1255 
1256  if (!prog) {
1257  errno = ENOENT;
1258  return -1;
1259  }
1260 
1261 #ifdef _WIN32
1262  rb_w32_uaspawn(P_OVERLAY, prog, argv);
1263 #else
1264  envp = envp_str ? (char **)RSTRING_PTR(envp_str) : NULL;
1265  if (envp_str)
1266  execve(prog, argv, envp); /* async-signal-safe */
1267  else
1268  execv(prog, argv); /* async-signal-safe (since SUSv4) */
1269  preserving_errno(try_with_sh(prog, argv, envp)); /* try_with_sh() is async-signal-safe. */
1270 #endif
1271  return -1;
1272 #endif
1273 }
1274 
1275 /* This function should be async-signal-safe. Actually it is. */
1276 static int
1277 proc_exec_sh(const char *str, VALUE envp_str)
1278 {
1279 #ifdef __native_client__
1280  rb_notimplement();
1281  UNREACHABLE;
1282 #else
1283  const char *s;
1284 
1285  s = str;
1286  while (*s == ' ' || *s == '\t' || *s == '\n')
1287  s++;
1288 
1289  if (!*s) {
1290  errno = ENOENT;
1291  return -1;
1292  }
1293 
1294 #ifdef _WIN32
1295  rb_w32_uspawn(P_OVERLAY, (char *)str, 0);
1296  return -1;
1297 #else
1298 #if defined(__CYGWIN32__)
1299  {
1300  char fbuf[MAXPATHLEN];
1301  char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
1302  int status = -1;
1303  if (shell)
1304  execl(shell, "sh", "-c", str, (char *) NULL);
1305  else
1306  status = system(str);
1307  if (status != -1)
1308  exit(status);
1309  }
1310 #else
1311  if (envp_str)
1312  execle("/bin/sh", "sh", "-c", str, (char *)NULL, (char **)RSTRING_PTR(envp_str)); /* async-signal-safe */
1313  else
1314  execl("/bin/sh", "sh", "-c", str, (char *)NULL); /* async-signal-safe (since SUSv4) */
1315 #endif
1316  return -1;
1317 #endif /* _WIN32 */
1318 #endif
1319 }
1320 
1321 int
1322 rb_proc_exec(const char *str)
1323 {
1324  int ret;
1325  before_exec();
1326  ret = proc_exec_sh(str, Qfalse);
1327  preserving_errno(after_exec());
1328  return ret;
1329 }
1330 
1331 static void
1332 mark_exec_arg(void *ptr)
1333 {
1334  struct rb_execarg *eargp = ptr;
1335  if (eargp->use_shell)
1336  rb_gc_mark(eargp->invoke.sh.shell_script);
1337  else {
1338  rb_gc_mark(eargp->invoke.cmd.command_name);
1339  rb_gc_mark(eargp->invoke.cmd.command_abspath);
1340  rb_gc_mark(eargp->invoke.cmd.argv_str);
1341  rb_gc_mark(eargp->invoke.cmd.argv_buf);
1342  }
1343  rb_gc_mark(eargp->redirect_fds);
1344  rb_gc_mark(eargp->envp_str);
1345  rb_gc_mark(eargp->envp_buf);
1346  rb_gc_mark(eargp->dup2_tmpbuf);
1347  rb_gc_mark(eargp->rlimit_limits);
1348  rb_gc_mark(eargp->fd_dup2);
1349  rb_gc_mark(eargp->fd_close);
1350  rb_gc_mark(eargp->fd_open);
1351  rb_gc_mark(eargp->fd_dup2_child);
1352  rb_gc_mark(eargp->env_modification);
1353  rb_gc_mark(eargp->path_env);
1354  rb_gc_mark(eargp->chdir_dir);
1355 }
1356 
1357 static size_t
1358 memsize_exec_arg(const void *ptr)
1359 {
1360  return sizeof(struct rb_execarg);
1361 }
1362 
1363 static const rb_data_type_t exec_arg_data_type = {
1364  "exec_arg",
1365  {mark_exec_arg, RUBY_TYPED_DEFAULT_FREE, memsize_exec_arg},
1367 };
1368 
1369 #ifdef _WIN32
1370 # define DEFAULT_PROCESS_ENCODING rb_utf8_encoding()
1371 #endif
1372 #ifdef DEFAULT_PROCESS_ENCODING
1373 # define EXPORT_STR(str) rb_str_export_to_enc((str), DEFAULT_PROCESS_ENCODING)
1374 # define EXPORT_DUP(str) export_dup(str)
1375 static VALUE
1376 export_dup(VALUE str)
1377 {
1378  VALUE newstr = EXPORT_STR(str);
1379  if (newstr == str) newstr = rb_str_dup(str);
1380  return newstr;
1381 }
1382 #else
1383 # define EXPORT_STR(str) (str)
1384 # define EXPORT_DUP(str) rb_str_dup(str)
1385 #endif
1386 
1387 #if !defined(HAVE_WORKING_FORK) && defined(HAVE_SPAWNV)
1388 # define USE_SPAWNV 1
1389 #else
1390 # define USE_SPAWNV 0
1391 #endif
1392 #ifndef P_NOWAIT
1393 # define P_NOWAIT _P_NOWAIT
1394 #endif
1395 
1396 #if USE_SPAWNV
1397 #if defined(_WIN32)
1398 #define proc_spawn_cmd_internal(argv, prog) rb_w32_uaspawn(P_NOWAIT, (prog), (argv))
1399 #else
1400 static rb_pid_t
1401 proc_spawn_cmd_internal(char **argv, char *prog)
1402 {
1403  char fbuf[MAXPATHLEN];
1404  rb_pid_t status;
1405 
1406  if (!prog)
1407  prog = argv[0];
1408  security(prog);
1409  prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
1410  if (!prog)
1411  return -1;
1412 
1413  before_exec();
1414  status = spawnv(P_NOWAIT, prog, (const char **)argv);
1415  if (status == -1 && errno == ENOEXEC) {
1416  *argv = (char *)prog;
1417  *--argv = (char *)"sh";
1418  status = spawnv(P_NOWAIT, "/bin/sh", (const char **)argv);
1419  after_exec();
1420  if (status == -1) errno = ENOEXEC;
1421  }
1422  return status;
1423 }
1424 #endif
1425 
1426 static rb_pid_t
1427 proc_spawn_cmd(char **argv, VALUE prog, struct rb_execarg *eargp)
1428 {
1429  rb_pid_t pid = -1;
1430 
1431  if (argv[0]) {
1432 #if defined(_WIN32)
1433  DWORD flags = 0;
1434  if (eargp->new_pgroup_given && eargp->new_pgroup_flag) {
1435  flags = CREATE_NEW_PROCESS_GROUP;
1436  }
1437  pid = rb_w32_uaspawn_flags(P_NOWAIT, prog ? RSTRING_PTR(prog) : 0, argv, flags);
1438 #else
1439  pid = proc_spawn_cmd_internal(argv, prog ? RSTRING_PTR(prog) : 0);
1440 #endif
1441  }
1442  return pid;
1443 }
1444 
1445 #if defined(_WIN32)
1446 #define proc_spawn_sh(str) rb_w32_uspawn(P_NOWAIT, (str), 0)
1447 #else
1448 static rb_pid_t
1449 proc_spawn_sh(char *str)
1450 {
1451  char fbuf[MAXPATHLEN];
1452  rb_pid_t status;
1453 
1454  char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
1455  before_exec();
1456  status = spawnl(P_NOWAIT, (shell ? shell : "/bin/sh"), "sh", "-c", str, (char*)NULL);
1457  after_exec();
1458  return status;
1459 }
1460 #endif
1461 #endif
1462 
1463 static VALUE
1464 hide_obj(VALUE obj)
1465 {
1466  RBASIC_CLEAR_CLASS(obj);
1467  return obj;
1468 }
1469 
1470 static VALUE
1471 check_exec_redirect_fd(VALUE v, int iskey)
1472 {
1473  VALUE tmp;
1474  int fd;
1475  if (FIXNUM_P(v)) {
1476  fd = FIX2INT(v);
1477  }
1478  else if (SYMBOL_P(v)) {
1479  ID id = rb_check_id(&v);
1480  if (id == id_in)
1481  fd = 0;
1482  else if (id == id_out)
1483  fd = 1;
1484  else if (id == id_err)
1485  fd = 2;
1486  else
1487  goto wrong;
1488  }
1489  else if (!NIL_P(tmp = rb_check_convert_type_with_id(v, T_FILE, "IO", idTo_io))) {
1490  rb_io_t *fptr;
1491  GetOpenFile(tmp, fptr);
1492  if (fptr->tied_io_for_writing)
1493  rb_raise(rb_eArgError, "duplex IO redirection");
1494  fd = fptr->fd;
1495  }
1496  else {
1497  wrong:
1498  rb_raise(rb_eArgError, "wrong exec redirect");
1499  }
1500  if (fd < 0) {
1501  rb_raise(rb_eArgError, "negative file descriptor");
1502  }
1503 #ifdef _WIN32
1504  else if (fd >= 3 && iskey) {
1505  rb_raise(rb_eArgError, "wrong file descriptor (%d)", fd);
1506  }
1507 #endif
1508  return INT2FIX(fd);
1509 }
1510 
1511 static VALUE
1512 check_exec_redirect1(VALUE ary, VALUE key, VALUE param)
1513 {
1514  if (ary == Qfalse) {
1515  ary = hide_obj(rb_ary_new());
1516  }
1517  if (!RB_TYPE_P(key, T_ARRAY)) {
1518  VALUE fd = check_exec_redirect_fd(key, !NIL_P(param));
1519  rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
1520  }
1521  else {
1522  int i, n=0;
1523  for (i = 0 ; i < RARRAY_LEN(key); i++) {
1524  VALUE v = RARRAY_AREF(key, i);
1525  VALUE fd = check_exec_redirect_fd(v, !NIL_P(param));
1526  rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
1527  n++;
1528  }
1529  }
1530  return ary;
1531 }
1532 
1533 static void
1534 check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
1535 {
1536  VALUE param;
1537  VALUE path, flags, perm;
1538  VALUE tmp;
1539  ID id;
1540 
1541  switch (TYPE(val)) {
1542  case T_SYMBOL:
1543  if (!(id = rb_check_id(&val))) goto wrong_symbol;
1544  if (id == id_close) {
1545  param = Qnil;
1546  eargp->fd_close = check_exec_redirect1(eargp->fd_close, key, param);
1547  }
1548  else if (id == id_in) {
1549  param = INT2FIX(0);
1550  eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
1551  }
1552  else if (id == id_out) {
1553  param = INT2FIX(1);
1554  eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
1555  }
1556  else if (id == id_err) {
1557  param = INT2FIX(2);
1558  eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
1559  }
1560  else {
1561  wrong_symbol:
1562  rb_raise(rb_eArgError, "wrong exec redirect symbol: %"PRIsVALUE,
1563  val);
1564  }
1565  break;
1566 
1567  case T_FILE:
1568  io:
1569  val = check_exec_redirect_fd(val, 0);
1570  /* fall through */
1571  case T_FIXNUM:
1572  param = val;
1573  eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
1574  break;
1575 
1576  case T_ARRAY:
1577  path = rb_ary_entry(val, 0);
1578  if (RARRAY_LEN(val) == 2 && SYMBOL_P(path) &&
1579  path == ID2SYM(id_child)) {
1580  param = check_exec_redirect_fd(rb_ary_entry(val, 1), 0);
1581  eargp->fd_dup2_child = check_exec_redirect1(eargp->fd_dup2_child, key, param);
1582  }
1583  else {
1584  FilePathValue(path);
1585  flags = rb_ary_entry(val, 1);
1586  if (NIL_P(flags))
1587  flags = INT2NUM(O_RDONLY);
1588  else if (RB_TYPE_P(flags, T_STRING))
1589  flags = INT2NUM(rb_io_modestr_oflags(StringValueCStr(flags)));
1590  else
1591  flags = rb_to_int(flags);
1592  perm = rb_ary_entry(val, 2);
1593  perm = NIL_P(perm) ? INT2FIX(0644) : rb_to_int(perm);
1594  param = hide_obj(rb_ary_new3(4, hide_obj(EXPORT_DUP(path)),
1595  flags, perm, Qnil));
1596  eargp->fd_open = check_exec_redirect1(eargp->fd_open, key, param);
1597  }
1598  break;
1599 
1600  case T_STRING:
1601  path = val;
1602  FilePathValue(path);
1603  if (RB_TYPE_P(key, T_FILE))
1604  key = check_exec_redirect_fd(key, 1);
1605  if (FIXNUM_P(key) && (FIX2INT(key) == 1 || FIX2INT(key) == 2))
1606  flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
1607  else if (RB_TYPE_P(key, T_ARRAY)) {
1608  int i;
1609  for (i = 0; i < RARRAY_LEN(key); i++) {
1610  VALUE v = RARRAY_PTR(key)[i];
1611  VALUE fd = check_exec_redirect_fd(v, 1);
1612  if (FIX2INT(fd) != 1 && FIX2INT(fd) != 2) break;
1613  }
1614  if (i == RARRAY_LEN(key))
1615  flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
1616  else
1617  flags = INT2NUM(O_RDONLY);
1618  }
1619  else
1620  flags = INT2NUM(O_RDONLY);
1621  perm = INT2FIX(0644);
1622  param = hide_obj(rb_ary_new3(4, hide_obj(EXPORT_DUP(path)),
1623  flags, perm, Qnil));
1624  eargp->fd_open = check_exec_redirect1(eargp->fd_open, key, param);
1625  break;
1626 
1627  default:
1628  tmp = val;
1629  val = rb_io_check_io(tmp);
1630  if (!NIL_P(val)) goto io;
1631  rb_raise(rb_eArgError, "wrong exec redirect action");
1632  }
1633 
1634 }
1635 
1636 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1637 static int rlimit_type_by_sym(VALUE key);
1638 
1639 static void
1640 rb_execarg_addopt_rlimit(struct rb_execarg *eargp, int rtype, VALUE val)
1641 {
1642  VALUE ary = eargp->rlimit_limits;
1643  VALUE tmp, softlim, hardlim;
1644  if (eargp->rlimit_limits == Qfalse)
1645  ary = eargp->rlimit_limits = hide_obj(rb_ary_new());
1646  else
1647  ary = eargp->rlimit_limits;
1648  tmp = rb_check_array_type(val);
1649  if (!NIL_P(tmp)) {
1650  if (RARRAY_LEN(tmp) == 1)
1651  softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0));
1652  else if (RARRAY_LEN(tmp) == 2) {
1653  softlim = rb_to_int(rb_ary_entry(tmp, 0));
1654  hardlim = rb_to_int(rb_ary_entry(tmp, 1));
1655  }
1656  else {
1657  rb_raise(rb_eArgError, "wrong exec rlimit option");
1658  }
1659  }
1660  else {
1661  softlim = hardlim = rb_to_int(val);
1662  }
1663  tmp = hide_obj(rb_ary_new3(3, INT2NUM(rtype), softlim, hardlim));
1664  rb_ary_push(ary, tmp);
1665 }
1666 #endif
1667 
1668 int
1670 {
1671  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
1672 
1673  ID id;
1674 
1675  switch (TYPE(key)) {
1676  case T_SYMBOL:
1677 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1678  {
1679  int rtype = rlimit_type_by_sym(key);
1680  if (rtype != -1) {
1681  rb_execarg_addopt_rlimit(eargp, rtype, val);
1682  RB_GC_GUARD(execarg_obj);
1683  return ST_CONTINUE;
1684  }
1685  }
1686 #endif
1687  if (!(id = rb_check_id(&key))) return ST_STOP;
1688 #ifdef HAVE_SETPGID
1689  if (id == id_pgroup) {
1690  rb_pid_t pgroup;
1691  if (eargp->pgroup_given) {
1692  rb_raise(rb_eArgError, "pgroup option specified twice");
1693  }
1694  if (!RTEST(val))
1695  pgroup = -1; /* asis(-1) means "don't call setpgid()". */
1696  else if (val == Qtrue)
1697  pgroup = 0; /* new process group. */
1698  else {
1699  pgroup = NUM2PIDT(val);
1700  if (pgroup < 0) {
1701  rb_raise(rb_eArgError, "negative process group ID : %ld", (long)pgroup);
1702  }
1703  }
1704  eargp->pgroup_given = 1;
1705  eargp->pgroup_pgid = pgroup;
1706  }
1707  else
1708 #endif
1709 #ifdef _WIN32
1710  if (id == id_new_pgroup) {
1711  if (eargp->new_pgroup_given) {
1712  rb_raise(rb_eArgError, "new_pgroup option specified twice");
1713  }
1714  eargp->new_pgroup_given = 1;
1715  eargp->new_pgroup_flag = RTEST(val) ? 1 : 0;
1716  }
1717  else
1718 #endif
1719  if (id == id_unsetenv_others) {
1720  if (eargp->unsetenv_others_given) {
1721  rb_raise(rb_eArgError, "unsetenv_others option specified twice");
1722  }
1723  eargp->unsetenv_others_given = 1;
1724  eargp->unsetenv_others_do = RTEST(val) ? 1 : 0;
1725  }
1726  else if (id == id_chdir) {
1727  if (eargp->chdir_given) {
1728  rb_raise(rb_eArgError, "chdir option specified twice");
1729  }
1730  FilePathValue(val);
1731  val = rb_str_encode_ospath(val);
1732  eargp->chdir_given = 1;
1733  eargp->chdir_dir = hide_obj(EXPORT_DUP(val));
1734  }
1735  else if (id == id_umask) {
1736  mode_t cmask = NUM2MODET(val);
1737  if (eargp->umask_given) {
1738  rb_raise(rb_eArgError, "umask option specified twice");
1739  }
1740  eargp->umask_given = 1;
1741  eargp->umask_mask = cmask;
1742  }
1743  else if (id == id_close_others) {
1744  if (eargp->close_others_given) {
1745  rb_raise(rb_eArgError, "close_others option specified twice");
1746  }
1747  eargp->close_others_given = 1;
1748  eargp->close_others_do = RTEST(val) ? 1 : 0;
1749  }
1750  else if (id == id_in) {
1751  key = INT2FIX(0);
1752  goto redirect;
1753  }
1754  else if (id == id_out) {
1755  key = INT2FIX(1);
1756  goto redirect;
1757  }
1758  else if (id == id_err) {
1759  key = INT2FIX(2);
1760  goto redirect;
1761  }
1762  else if (id == id_uid) {
1763 #ifdef HAVE_SETUID
1764  if (eargp->uid_given) {
1765  rb_raise(rb_eArgError, "uid option specified twice");
1766  }
1767  check_uid_switch();
1768  {
1769  eargp->uid = OBJ2UID(val);
1770  eargp->uid_given = 1;
1771  }
1772 #else
1774  "uid option is unimplemented on this machine");
1775 #endif
1776  }
1777  else if (id == id_gid) {
1778 #ifdef HAVE_SETGID
1779  if (eargp->gid_given) {
1780  rb_raise(rb_eArgError, "gid option specified twice");
1781  }
1782  check_gid_switch();
1783  {
1784  eargp->gid = OBJ2GID(val);
1785  eargp->gid_given = 1;
1786  }
1787 #else
1789  "gid option is unimplemented on this machine");
1790 #endif
1791  }
1792  else {
1793  return ST_STOP;
1794  }
1795  break;
1796 
1797  case T_FIXNUM:
1798  case T_FILE:
1799  case T_ARRAY:
1800 redirect:
1801  check_exec_redirect(key, val, eargp);
1802  break;
1803 
1804  default:
1805  return ST_STOP;
1806  }
1807 
1808  RB_GC_GUARD(execarg_obj);
1809  return ST_CONTINUE;
1810 }
1811 
1812 static int
1813 check_exec_options_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
1814 {
1815  VALUE key = (VALUE)st_key;
1816  VALUE val = (VALUE)st_val;
1817  VALUE execarg_obj = (VALUE)arg;
1818  if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) {
1819  if (SYMBOL_P(key))
1820  rb_raise(rb_eArgError, "wrong exec option symbol: % "PRIsVALUE,
1821  key);
1822  rb_raise(rb_eArgError, "wrong exec option");
1823  }
1824  return ST_CONTINUE;
1825 }
1826 
1827 static int
1828 check_exec_options_i_extract(st_data_t st_key, st_data_t st_val, st_data_t arg)
1829 {
1830  VALUE key = (VALUE)st_key;
1831  VALUE val = (VALUE)st_val;
1832  VALUE *args = (VALUE *)arg;
1833  VALUE execarg_obj = args[0];
1834  if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) {
1835  VALUE nonopts = args[1];
1836  if (NIL_P(nonopts)) args[1] = nonopts = rb_hash_new();
1837  rb_hash_aset(nonopts, key, val);
1838  }
1839  return ST_CONTINUE;
1840 }
1841 
1842 static int
1843 check_exec_fds_1(struct rb_execarg *eargp, VALUE h, int maxhint, VALUE ary)
1844 {
1845  long i;
1846 
1847  if (ary != Qfalse) {
1848  for (i = 0; i < RARRAY_LEN(ary); i++) {
1849  VALUE elt = RARRAY_AREF(ary, i);
1850  int fd = FIX2INT(RARRAY_AREF(elt, 0));
1851  if (RTEST(rb_hash_lookup(h, INT2FIX(fd)))) {
1852  rb_raise(rb_eArgError, "fd %d specified twice", fd);
1853  }
1854  if (ary == eargp->fd_dup2)
1855  rb_hash_aset(h, INT2FIX(fd), Qtrue);
1856  else if (ary == eargp->fd_dup2_child)
1857  rb_hash_aset(h, INT2FIX(fd), RARRAY_AREF(elt, 1));
1858  else /* ary == eargp->fd_close */
1859  rb_hash_aset(h, INT2FIX(fd), INT2FIX(-1));
1860  if (maxhint < fd)
1861  maxhint = fd;
1862  if (ary == eargp->fd_dup2 || ary == eargp->fd_dup2_child) {
1863  fd = FIX2INT(RARRAY_AREF(elt, 1));
1864  if (maxhint < fd)
1865  maxhint = fd;
1866  }
1867  }
1868  }
1869  return maxhint;
1870 }
1871 
1872 static VALUE
1873 check_exec_fds(struct rb_execarg *eargp)
1874 {
1875  VALUE h = rb_hash_new();
1876  VALUE ary;
1877  int maxhint = -1;
1878  long i;
1879 
1880  maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_dup2);
1881  maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_close);
1882  maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_dup2_child);
1883 
1884  if (eargp->fd_dup2_child) {
1885  ary = eargp->fd_dup2_child;
1886  for (i = 0; i < RARRAY_LEN(ary); i++) {
1887  VALUE elt = RARRAY_AREF(ary, i);
1888  int newfd = FIX2INT(RARRAY_AREF(elt, 0));
1889  int oldfd = FIX2INT(RARRAY_AREF(elt, 1));
1890  int lastfd = oldfd;
1891  VALUE val = rb_hash_lookup(h, INT2FIX(lastfd));
1892  long depth = 0;
1893  while (FIXNUM_P(val) && 0 <= FIX2INT(val)) {
1894  lastfd = FIX2INT(val);
1895  val = rb_hash_lookup(h, val);
1896  if (RARRAY_LEN(ary) < depth)
1897  rb_raise(rb_eArgError, "cyclic child fd redirection from %d", oldfd);
1898  depth++;
1899  }
1900  if (val != Qtrue)
1901  rb_raise(rb_eArgError, "child fd %d is not redirected", oldfd);
1902  if (oldfd != lastfd) {
1903  VALUE val2;
1904  rb_ary_store(elt, 1, INT2FIX(lastfd));
1905  rb_hash_aset(h, INT2FIX(newfd), INT2FIX(lastfd));
1906  val = INT2FIX(oldfd);
1907  while (FIXNUM_P(val2 = rb_hash_lookup(h, val))) {
1908  rb_hash_aset(h, val, INT2FIX(lastfd));
1909  val = val2;
1910  }
1911  }
1912  }
1913  }
1914 
1915  eargp->close_others_maxhint = maxhint;
1916  return h;
1917 }
1918 
1919 static void
1920 rb_check_exec_options(VALUE opthash, VALUE execarg_obj)
1921 {
1922  if (RHASH_EMPTY_P(opthash))
1923  return;
1924  st_foreach(rb_hash_tbl_raw(opthash), check_exec_options_i, (st_data_t)execarg_obj);
1925 }
1926 
1927 VALUE
1929 {
1930  VALUE args[2];
1931  if (RHASH_EMPTY_P(opthash))
1932  return Qnil;
1933  args[0] = execarg_obj;
1934  args[1] = Qnil;
1935  st_foreach(rb_hash_tbl_raw(opthash), check_exec_options_i_extract, (st_data_t)args);
1936  return args[1];
1937 }
1938 
1939 #ifdef ENV_IGNORECASE
1940 #define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
1941 #else
1942 #define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
1943 #endif
1944 
1945 static int
1946 check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
1947 {
1948  VALUE key = (VALUE)st_key;
1949  VALUE val = (VALUE)st_val;
1950  VALUE env = ((VALUE *)arg)[0];
1951  VALUE *path = &((VALUE *)arg)[1];
1952  char *k;
1953 
1954  k = StringValueCStr(key);
1955  if (strchr(k, '='))
1956  rb_raise(rb_eArgError, "environment name contains a equal : %s", k);
1957 
1958  if (!NIL_P(val))
1959  StringValueCStr(val);
1960 
1961  key = EXPORT_STR(key);
1962  if (!NIL_P(val)) val = EXPORT_STR(val);
1963 
1964  if (ENVMATCH(k, PATH_ENV)) {
1965  *path = val;
1966  }
1967  rb_ary_push(env, hide_obj(rb_assoc_new(key, val)));
1968 
1969  return ST_CONTINUE;
1970 }
1971 
1972 static VALUE
1973 rb_check_exec_env(VALUE hash, VALUE *path)
1974 {
1975  VALUE env[2];
1976 
1977  env[0] = hide_obj(rb_ary_new());
1978  env[1] = Qfalse;
1979  st_foreach(rb_hash_tbl_raw(hash), check_exec_env_i, (st_data_t)env);
1980  *path = env[1];
1981 
1982  return env[0];
1983 }
1984 
1985 static VALUE
1986 rb_check_argv(int argc, VALUE *argv)
1987 {
1988  VALUE tmp, prog;
1989  int i;
1990  const char *name = 0;
1991 
1993 
1994  prog = 0;
1995  tmp = rb_check_array_type(argv[0]);
1996  if (!NIL_P(tmp)) {
1997  if (RARRAY_LEN(tmp) != 2) {
1998  rb_raise(rb_eArgError, "wrong first argument");
1999  }
2000  prog = RARRAY_AREF(tmp, 0);
2001  argv[0] = RARRAY_AREF(tmp, 1);
2002  SafeStringValue(prog);
2003  StringValueCStr(prog);
2004  prog = rb_str_new_frozen(prog);
2005  name = RSTRING_PTR(prog);
2006  }
2007  for (i = 0; i < argc; i++) {
2008  SafeStringValue(argv[i]);
2009  argv[i] = rb_str_new_frozen(argv[i]);
2010  StringValueCStr(argv[i]);
2011  }
2012  security(name ? name : RSTRING_PTR(argv[0]));
2013  return prog;
2014 }
2015 
2016 static VALUE
2017 check_hash(VALUE obj)
2018 {
2019  if (RB_SPECIAL_CONST_P(obj)) return Qnil;
2020  switch (RB_BUILTIN_TYPE(obj)) {
2021  case T_STRING:
2022  case T_ARRAY:
2023  return Qnil;
2024  }
2025  return rb_check_hash_type(obj);
2026 }
2027 
2028 static VALUE
2029 rb_exec_getargs(int *argc_p, VALUE **argv_p, int accept_shell, VALUE *env_ret, VALUE *opthash_ret)
2030 {
2031  VALUE hash, prog;
2032 
2033  if (0 < *argc_p) {
2034  hash = check_hash((*argv_p)[*argc_p-1]);
2035  if (!NIL_P(hash)) {
2036  *opthash_ret = hash;
2037  (*argc_p)--;
2038  }
2039  }
2040 
2041  if (0 < *argc_p) {
2042  hash = check_hash((*argv_p)[0]);
2043  if (!NIL_P(hash)) {
2044  *env_ret = hash;
2045  (*argc_p)--;
2046  (*argv_p)++;
2047  }
2048  }
2049  prog = rb_check_argv(*argc_p, *argv_p);
2050  if (!prog) {
2051  prog = (*argv_p)[0];
2052  if (accept_shell && *argc_p == 1) {
2053  *argc_p = 0;
2054  *argv_p = 0;
2055  }
2056  }
2057  return prog;
2058 }
2059 
2060 #ifndef _WIN32
2061 struct string_part {
2062  const char *ptr;
2063  size_t len;
2064 };
2065 
2066 static int
2067 compare_posix_sh(const void *key, const void *el)
2068 {
2069  const struct string_part *word = key;
2070  int ret = strncmp(word->ptr, el, word->len);
2071  if (!ret && ((const char *)el)[word->len]) ret = -1;
2072  return ret;
2073 }
2074 #endif
2075 
2076 static void
2077 rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VALUE execarg_obj)
2078 {
2079  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2080  char fbuf[MAXPATHLEN];
2081 
2082  MEMZERO(eargp, struct rb_execarg, 1);
2083 
2084  if (!NIL_P(opthash)) {
2085  rb_check_exec_options(opthash, execarg_obj);
2086  }
2087  if (!NIL_P(env)) {
2088  env = rb_check_exec_env(env, &eargp->path_env);
2089  eargp->env_modification = env;
2090  }
2091 
2092  prog = EXPORT_STR(prog);
2093  eargp->use_shell = argc == 0;
2094  if (eargp->use_shell)
2095  eargp->invoke.sh.shell_script = prog;
2096  else
2097  eargp->invoke.cmd.command_name = prog;
2098 
2099 #ifndef _WIN32
2100  if (eargp->use_shell) {
2101  static const char posix_sh_cmds[][9] = {
2102  "!", /* reserved */
2103  ".", /* special built-in */
2104  ":", /* special built-in */
2105  "break", /* special built-in */
2106  "case", /* reserved */
2107  "continue", /* special built-in */
2108  "do", /* reserved */
2109  "done", /* reserved */
2110  "elif", /* reserved */
2111  "else", /* reserved */
2112  "esac", /* reserved */
2113  "eval", /* special built-in */
2114  "exec", /* special built-in */
2115  "exit", /* special built-in */
2116  "export", /* special built-in */
2117  "fi", /* reserved */
2118  "for", /* reserved */
2119  "if", /* reserved */
2120  "in", /* reserved */
2121  "readonly", /* special built-in */
2122  "return", /* special built-in */
2123  "set", /* special built-in */
2124  "shift", /* special built-in */
2125  "then", /* reserved */
2126  "times", /* special built-in */
2127  "trap", /* special built-in */
2128  "unset", /* special built-in */
2129  "until", /* reserved */
2130  "while", /* reserved */
2131  };
2132  const char *p;
2133  struct string_part first = {0, 0};
2134  int has_meta = 0;
2135  /*
2136  * meta characters:
2137  *
2138  * * Pathname Expansion
2139  * ? Pathname Expansion
2140  * {} Grouping Commands
2141  * [] Pathname Expansion
2142  * <> Redirection
2143  * () Grouping Commands
2144  * ~ Tilde Expansion
2145  * & AND Lists, Asynchronous Lists
2146  * | OR Lists, Pipelines
2147  * \ Escape Character
2148  * $ Parameter Expansion
2149  * ; Sequential Lists
2150  * ' Single-Quotes
2151  * ` Command Substitution
2152  * " Double-Quotes
2153  * \n Lists
2154  *
2155  * # Comment
2156  * = Assignment preceding command name
2157  * % (used in Parameter Expansion)
2158  */
2159  for (p = RSTRING_PTR(prog); *p; p++) {
2160  if (*p == ' ' || *p == '\t') {
2161  if (first.ptr && !first.len) first.len = p - first.ptr;
2162  }
2163  else {
2164  if (!first.ptr) first.ptr = p;
2165  }
2166  if (!has_meta && strchr("*?{}[]<>()~&|\\$;'`\"\n#", *p))
2167  has_meta = 1;
2168  if (!first.len) {
2169  if (*p == '=') {
2170  has_meta = 1;
2171  }
2172  else if (*p == '/') {
2173  first.len = 0x100; /* longer than any posix_sh_cmds */
2174  }
2175  }
2176  if (has_meta)
2177  break;
2178  }
2179  if (!has_meta && first.ptr) {
2180  if (!first.len) first.len = p - first.ptr;
2181  if (first.len > 0 && first.len <= sizeof(posix_sh_cmds[0]) &&
2182  bsearch(&first, posix_sh_cmds, numberof(posix_sh_cmds), sizeof(posix_sh_cmds[0]), compare_posix_sh))
2183  has_meta = 1;
2184  }
2185  if (!has_meta) {
2186  /* avoid shell since no shell meta character found. */
2187  eargp->use_shell = 0;
2188  }
2189  if (!eargp->use_shell) {
2190  VALUE argv_buf;
2191  argv_buf = hide_obj(rb_str_buf_new(0));
2192  p = RSTRING_PTR(prog);
2193  while (*p) {
2194  while (*p == ' ' || *p == '\t')
2195  p++;
2196  if (*p) {
2197  const char *w = p;
2198  while (*p && *p != ' ' && *p != '\t')
2199  p++;
2200  rb_str_buf_cat(argv_buf, w, p-w);
2201  rb_str_buf_cat(argv_buf, "", 1); /* append '\0' */
2202  }
2203  }
2204  eargp->invoke.cmd.argv_buf = argv_buf;
2205  eargp->invoke.cmd.command_name = hide_obj(rb_str_new_cstr(RSTRING_PTR(argv_buf)));
2206  }
2207  }
2208 #endif
2209 
2210  if (!eargp->use_shell) {
2211  const char *abspath;
2212  const char *path_env = 0;
2213  if (RTEST(eargp->path_env)) path_env = RSTRING_PTR(eargp->path_env);
2214  abspath = dln_find_exe_r(RSTRING_PTR(eargp->invoke.cmd.command_name),
2215  path_env, fbuf, sizeof(fbuf));
2216  if (abspath)
2217  eargp->invoke.cmd.command_abspath = rb_str_new_cstr(abspath);
2218  else
2219  eargp->invoke.cmd.command_abspath = Qnil;
2220  }
2221 
2222  if (!eargp->use_shell && !eargp->invoke.cmd.argv_buf) {
2223  int i;
2224  VALUE argv_buf;
2225  argv_buf = rb_str_buf_new(0);
2226  hide_obj(argv_buf);
2227  for (i = 0; i < argc; i++) {
2228  VALUE arg = argv[i];
2229  const char *s = StringValueCStr(arg);
2230 #ifdef DEFAULT_PROCESS_ENCODING
2231  arg = EXPORT_STR(arg);
2232  s = RSTRING_PTR(arg);
2233 #endif
2234  rb_str_buf_cat(argv_buf, s, RSTRING_LEN(arg) + 1); /* include '\0' */
2235  }
2236  eargp->invoke.cmd.argv_buf = argv_buf;
2237  }
2238 
2239  if (!eargp->use_shell) {
2240  const char *p, *ep, *null=NULL;
2241  VALUE argv_str;
2242  argv_str = hide_obj(rb_str_buf_new(sizeof(char*) * (argc + 2)));
2243  rb_str_buf_cat(argv_str, (char *)&null, sizeof(null)); /* place holder for /bin/sh of try_with_sh. */
2244  p = RSTRING_PTR(eargp->invoke.cmd.argv_buf);
2245  ep = p + RSTRING_LEN(eargp->invoke.cmd.argv_buf);
2246  while (p < ep) {
2247  rb_str_buf_cat(argv_str, (char *)&p, sizeof(p));
2248  p += strlen(p) + 1;
2249  }
2250  rb_str_buf_cat(argv_str, (char *)&null, sizeof(null)); /* terminator for execve. */
2251  eargp->invoke.cmd.argv_str = argv_str;
2252  }
2253  RB_GC_GUARD(execarg_obj);
2254 }
2255 
2256 VALUE
2257 rb_execarg_new(int argc, const VALUE *argv, int accept_shell)
2258 {
2259  VALUE execarg_obj;
2260  struct rb_execarg *eargp;
2261  execarg_obj = TypedData_Make_Struct(rb_cData, struct rb_execarg, &exec_arg_data_type, eargp);
2262  hide_obj(execarg_obj);
2263  rb_execarg_init(argc, argv, accept_shell, execarg_obj);
2264  return execarg_obj;
2265 }
2266 
2267 struct rb_execarg *
2268 rb_execarg_get(VALUE execarg_obj)
2269 {
2270  struct rb_execarg *eargp;
2271  TypedData_Get_Struct(execarg_obj, struct rb_execarg, &exec_arg_data_type, eargp);
2272  return eargp;
2273 }
2274 
2275 VALUE
2276 rb_execarg_init(int argc, const VALUE *orig_argv, int accept_shell, VALUE execarg_obj)
2277 {
2278  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2279  VALUE prog, ret;
2280  VALUE env = Qnil, opthash = Qnil;
2281  VALUE argv_buf;
2282  VALUE *argv = ALLOCV_N(VALUE, argv_buf, argc);
2283  MEMCPY(argv, orig_argv, VALUE, argc);
2284  prog = rb_exec_getargs(&argc, &argv, accept_shell, &env, &opthash);
2285  rb_exec_fillarg(prog, argc, argv, env, opthash, execarg_obj);
2286  ALLOCV_END(argv_buf);
2287  ret = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
2288  RB_GC_GUARD(execarg_obj);
2289  return ret;
2290 }
2291 
2292 void
2294 {
2295  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2296  env = !NIL_P(env) ? rb_check_exec_env(env, &eargp->path_env) : Qfalse;
2297  eargp->env_modification = env;
2298 }
2299 
2300 static int
2301 fill_envp_buf_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
2302 {
2303  VALUE key = (VALUE)st_key;
2304  VALUE val = (VALUE)st_val;
2305  VALUE envp_buf = (VALUE)arg;
2306 
2307  rb_str_buf_cat2(envp_buf, StringValueCStr(key));
2308  rb_str_buf_cat2(envp_buf, "=");
2309  rb_str_buf_cat2(envp_buf, StringValueCStr(val));
2310  rb_str_buf_cat(envp_buf, "", 1); /* append '\0' */
2311 
2312  return ST_CONTINUE;
2313 }
2314 
2315 
2316 static long run_exec_dup2_tmpbuf_size(long n);
2317 
2318 struct open_struct {
2320  int oflags;
2322  int ret;
2323  int err;
2324 };
2325 
2326 static void *
2327 open_func(void *ptr)
2328 {
2329  struct open_struct *data = ptr;
2330  const char *fname = RSTRING_PTR(data->fname);
2331  data->ret = parent_redirect_open(fname, data->oflags, data->perm);
2332  data->err = errno;
2333  return NULL;
2334 }
2335 
2336 static VALUE
2337 rb_execarg_parent_start1(VALUE execarg_obj)
2338 {
2339  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2340  int unsetenv_others;
2341  VALUE envopts;
2342  VALUE ary;
2343 
2344  ary = eargp->fd_open;
2345  if (ary != Qfalse) {
2346  long i;
2347  for (i = 0; i < RARRAY_LEN(ary); i++) {
2348  VALUE elt = RARRAY_AREF(ary, i);
2349  int fd = FIX2INT(RARRAY_AREF(elt, 0));
2350  VALUE param = RARRAY_AREF(elt, 1);
2351  VALUE vpath = RARRAY_AREF(param, 0);
2352  int flags = NUM2INT(RARRAY_AREF(param, 1));
2353  int perm = NUM2INT(RARRAY_AREF(param, 2));
2354  VALUE fd2v = RARRAY_AREF(param, 3);
2355  int fd2;
2356  if (NIL_P(fd2v)) {
2357  struct open_struct open_data;
2358  FilePathValue(vpath);
2359  vpath = rb_str_encode_ospath(vpath);
2360  again:
2361  open_data.fname = vpath;
2362  open_data.oflags = flags;
2363  open_data.perm = perm;
2364  open_data.ret = -1;
2365  open_data.err = EINTR;
2366  rb_thread_call_without_gvl2(open_func, (void *)&open_data, RUBY_UBF_IO, 0);
2367  if (open_data.ret == -1) {
2368  if (open_data.err == EINTR) {
2370  goto again;
2371  }
2372  rb_syserr_fail_str(open_data.err, vpath);
2373  }
2374  fd2 = open_data.ret;
2375  rb_update_max_fd(fd2);
2376  RARRAY_ASET(param, 3, INT2FIX(fd2));
2378  }
2379  else {
2380  fd2 = NUM2INT(fd2v);
2381  }
2382  rb_execarg_addopt(execarg_obj, INT2FIX(fd), INT2FIX(fd2));
2383  }
2384  }
2385 
2386  eargp->redirect_fds = check_exec_fds(eargp);
2387 
2388  ary = eargp->fd_dup2;
2389  if (ary != Qfalse) {
2390  size_t len = run_exec_dup2_tmpbuf_size(RARRAY_LEN(ary));
2391  VALUE tmpbuf = hide_obj(rb_str_new(0, len));
2392  rb_str_set_len(tmpbuf, len);
2393  eargp->dup2_tmpbuf = tmpbuf;
2394  }
2395 
2396  unsetenv_others = eargp->unsetenv_others_given && eargp->unsetenv_others_do;
2397  envopts = eargp->env_modification;
2398  if (ALWAYS_NEED_ENVP || unsetenv_others || envopts != Qfalse) {
2399  VALUE envtbl, envp_str, envp_buf;
2400  char *p, *ep;
2401  if (unsetenv_others) {
2402  envtbl = rb_hash_new();
2403  }
2404  else {
2405  envtbl = rb_const_get(rb_cObject, id_ENV);
2406  envtbl = rb_convert_type_with_id(envtbl, T_HASH, "Hash", idTo_hash);
2407  }
2408  hide_obj(envtbl);
2409  if (envopts != Qfalse) {
2410  st_table *stenv = RHASH_TBL_RAW(envtbl);
2411  long i;
2412  for (i = 0; i < RARRAY_LEN(envopts); i++) {
2413  VALUE pair = RARRAY_AREF(envopts, i);
2414  VALUE key = RARRAY_AREF(pair, 0);
2415  VALUE val = RARRAY_AREF(pair, 1);
2416  if (NIL_P(val)) {
2417  st_data_t stkey = (st_data_t)key;
2418  st_delete(stenv, &stkey, NULL);
2419  }
2420  else {
2421  st_insert(stenv, (st_data_t)key, (st_data_t)val);
2422  RB_OBJ_WRITTEN(envtbl, Qundef, key);
2423  RB_OBJ_WRITTEN(envtbl, Qundef, val);
2424  }
2425  }
2426  }
2427  envp_buf = rb_str_buf_new(0);
2428  hide_obj(envp_buf);
2429  st_foreach(RHASH_TBL_RAW(envtbl), fill_envp_buf_i, (st_data_t)envp_buf);
2430  envp_str = rb_str_buf_new(sizeof(char*) * (RHASH_SIZE(envtbl) + 1));
2431  hide_obj(envp_str);
2432  p = RSTRING_PTR(envp_buf);
2433  ep = p + RSTRING_LEN(envp_buf);
2434  while (p < ep) {
2435  rb_str_buf_cat(envp_str, (char *)&p, sizeof(p));
2436  p += strlen(p) + 1;
2437  }
2438  p = NULL;
2439  rb_str_buf_cat(envp_str, (char *)&p, sizeof(p));
2440  eargp->envp_str = envp_str;
2441  eargp->envp_buf = envp_buf;
2442 
2443  /*
2444  char **tmp_envp = (char **)RSTRING_PTR(envp_str);
2445  while (*tmp_envp) {
2446  printf("%s\n", *tmp_envp);
2447  tmp_envp++;
2448  }
2449  */
2450  }
2451 
2452  RB_GC_GUARD(execarg_obj);
2453  return Qnil;
2454 }
2455 
2456 void
2458 {
2459  int state;
2460  rb_protect(rb_execarg_parent_start1, execarg_obj, &state);
2461  if (state) {
2462  rb_execarg_parent_end(execarg_obj);
2463  rb_jump_tag(state);
2464  }
2465 }
2466 
2467 static VALUE
2468 execarg_parent_end(VALUE execarg_obj)
2469 {
2470  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2471  int err = errno;
2472  VALUE ary;
2473 
2474  ary = eargp->fd_open;
2475  if (ary != Qfalse) {
2476  long i;
2477  for (i = 0; i < RARRAY_LEN(ary); i++) {
2478  VALUE elt = RARRAY_AREF(ary, i);
2479  VALUE param = RARRAY_AREF(elt, 1);
2480  VALUE fd2v;
2481  int fd2;
2482  fd2v = RARRAY_AREF(param, 3);
2483  if (!NIL_P(fd2v)) {
2484  fd2 = FIX2INT(fd2v);
2485  parent_redirect_close(fd2);
2486  RARRAY_ASET(param, 3, Qnil);
2487  }
2488  }
2489  }
2490 
2491  errno = err;
2492  return execarg_obj;
2493 }
2494 
2495 void
2497 {
2498  execarg_parent_end(execarg_obj);
2499  RB_GC_GUARD(execarg_obj);
2500 }
2501 
2502 static void
2503 rb_exec_fail(struct rb_execarg *eargp, int err, const char *errmsg)
2504 {
2505  if (!errmsg || !*errmsg) return;
2506  if (strcmp(errmsg, "chdir") == 0) {
2507  rb_sys_fail_str(eargp->chdir_dir);
2508  }
2509  rb_sys_fail(errmsg);
2510 }
2511 
2512 #if 0
2513 void
2514 rb_execarg_fail(VALUE execarg_obj, int err, const char *errmsg)
2515 {
2516  if (!errmsg || !*errmsg) return;
2517  rb_exec_fail(rb_execarg_get(execarg_obj), err, errmsg);
2518  RB_GC_GUARD(execarg_obj);
2519 }
2520 #endif
2521 
2522 /*
2523  * call-seq:
2524  * exec([env,] command... [,options])
2525  *
2526  * Replaces the current process by running the given external _command_, which
2527  * can take one of the following forms:
2528  *
2529  * [<code>exec(commandline)</code>]
2530  * command line string which is passed to the standard shell
2531  * [<code>exec(cmdname, arg1, ...)</code>]
2532  * command name and one or more arguments (no shell)
2533  * [<code>exec([cmdname, argv0], arg1, ...)</code>]
2534  * command name, argv[0] and zero or more arguments (no shell)
2535  *
2536  * In the first form, the string is taken as a command line that is subject to
2537  * shell expansion before being executed.
2538  *
2539  * The standard shell always means <code>"/bin/sh"</code> on Unix-like systems,
2540  * same as <code>ENV["RUBYSHELL"]</code>
2541  * (or <code>ENV["COMSPEC"]</code> on Windows NT series), and similar.
2542  *
2543  * If the string from the first form (<code>exec("command")</code>) follows
2544  * these simple rules:
2545  *
2546  * * no meta characters
2547  * * no shell reserved word and no special built-in
2548  * * Ruby invokes the command directly without shell
2549  *
2550  * You can force shell invocation by adding ";" to the string (because ";" is
2551  * a meta character).
2552  *
2553  * Note that this behavior is observable by pid obtained
2554  * (return value of spawn() and IO#pid for IO.popen) is the pid of the invoked
2555  * command, not shell.
2556  *
2557  * In the second form (<code>exec("command1", "arg1", ...)</code>), the first
2558  * is taken as a command name and the rest are passed as parameters to command
2559  * with no shell expansion.
2560  *
2561  * In the third form (<code>exec(["command", "argv0"], "arg1", ...)</code>),
2562  * starting a two-element array at the beginning of the command, the first
2563  * element is the command to be executed, and the second argument is used as
2564  * the <code>argv[0]</code> value, which may show up in process listings.
2565  *
2566  * In order to execute the command, one of the <code>exec(2)</code> system
2567  * calls are used, so the running command may inherit some of the environment
2568  * of the original program (including open file descriptors).
2569  *
2570  * This behavior is modified by the given +env+ and +options+ parameters. See
2571  * ::spawn for details.
2572  *
2573  * If the command fails to execute (typically <code>Errno::ENOENT</code> when
2574  * it was not found) a SystemCallError exception is raised.
2575  *
2576  * This method modifies process attributes according to given +options+ before
2577  * <code>exec(2)</code> system call. See ::spawn for more details about the
2578  * given +options+.
2579  *
2580  * The modified attributes may be retained when <code>exec(2)</code> system
2581  * call fails.
2582  *
2583  * For example, hard resource limits are not restorable.
2584  *
2585  * Consider to create a child process using ::spawn or Kernel#system if this
2586  * is not acceptable.
2587  *
2588  * exec "echo *" # echoes list of files in current directory
2589  * # never get here
2590  *
2591  * exec "echo", "*" # echoes an asterisk
2592  * # never get here
2593  */
2594 
2595 VALUE
2596 rb_f_exec(int argc, const VALUE *argv)
2597 {
2598  VALUE execarg_obj, fail_str;
2599  struct rb_execarg *eargp;
2600 #define CHILD_ERRMSG_BUFLEN 80
2601  char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
2602  int err;
2603 
2604  execarg_obj = rb_execarg_new(argc, argv, TRUE);
2605  eargp = rb_execarg_get(execarg_obj);
2606  before_exec(); /* stop timer thread before redirects */
2607  rb_execarg_parent_start(execarg_obj);
2608  fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
2609 
2610  rb_exec_async_signal_safe(eargp, errmsg, sizeof(errmsg));
2611 
2612  err = errno;
2613  after_exec(); /* restart timer thread */
2614 
2615  rb_exec_fail(eargp, err, errmsg);
2616  RB_GC_GUARD(execarg_obj);
2617  rb_syserr_fail_str(err, fail_str);
2618  UNREACHABLE;
2619 }
2620 
2621 #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
2622 #define ERRMSG1(str, a) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a)); } while (0)
2623 #define ERRMSG2(str, a, b) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a), (b)); } while (0)
2624 
2625 static int fd_get_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
2626 static int fd_set_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
2627 static int fd_clear_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
2628 
2629 static int
2630 save_redirect_fd(int fd, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
2631 {
2632  if (sargp) {
2633  VALUE newary, redirection;
2634  int save_fd = redirect_cloexec_dup(fd), cloexec;
2635  if (save_fd == -1) {
2636  if (errno == EBADF)
2637  return 0;
2638  ERRMSG("dup");
2639  return -1;
2640  }
2641  rb_update_max_fd(save_fd);
2642  newary = sargp->fd_dup2;
2643  if (newary == Qfalse) {
2644  newary = hide_obj(rb_ary_new());
2645  sargp->fd_dup2 = newary;
2646  }
2647  cloexec = fd_get_cloexec(fd, errmsg, errmsg_buflen);
2648  redirection = hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd)));
2649  if (cloexec) rb_ary_push(redirection, Qtrue);
2650  rb_ary_push(newary, redirection);
2651 
2652  newary = sargp->fd_close;
2653  if (newary == Qfalse) {
2654  newary = hide_obj(rb_ary_new());
2655  sargp->fd_close = newary;
2656  }
2657  rb_ary_push(newary, hide_obj(rb_assoc_new(INT2FIX(save_fd), Qnil)));
2658  }
2659 
2660  return 0;
2661 }
2662 
2663 static int
2664 intcmp(const void *a, const void *b)
2665 {
2666  return *(int*)a - *(int*)b;
2667 }
2668 
2669 static int
2670 intrcmp(const void *a, const void *b)
2671 {
2672  return *(int*)b - *(int*)a;
2673 }
2674 
2676  int oldfd;
2677  int newfd;
2680  int cloexec;
2681 };
2682 
2683 static long
2684 run_exec_dup2_tmpbuf_size(long n)
2685 {
2686  return sizeof(struct run_exec_dup2_fd_pair) * n;
2687 }
2688 
2689 /* This function should be async-signal-safe. Actually it is. */
2690 static int
2691 fd_get_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
2692 {
2693 #ifdef F_GETFD
2694  int ret = 0;
2695  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
2696  if (ret == -1) {
2697  ERRMSG("fcntl(F_GETFD)");
2698  return -1;
2699  }
2700  if (ret & FD_CLOEXEC) return 1;
2701 #endif
2702  return 0;
2703 }
2704 
2705 /* This function should be async-signal-safe. Actually it is. */
2706 static int
2707 fd_set_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
2708 {
2709 #ifdef F_GETFD
2710  int ret = 0;
2711  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
2712  if (ret == -1) {
2713  ERRMSG("fcntl(F_GETFD)");
2714  return -1;
2715  }
2716  if (!(ret & FD_CLOEXEC)) {
2717  ret |= FD_CLOEXEC;
2718  ret = fcntl(fd, F_SETFD, ret); /* async-signal-safe */
2719  if (ret == -1) {
2720  ERRMSG("fcntl(F_SETFD)");
2721  return -1;
2722  }
2723  }
2724 #endif
2725  return 0;
2726 }
2727 
2728 /* This function should be async-signal-safe. Actually it is. */
2729 static int
2730 fd_clear_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
2731 {
2732 #ifdef F_GETFD
2733  int ret;
2734  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
2735  if (ret == -1) {
2736  ERRMSG("fcntl(F_GETFD)");
2737  return -1;
2738  }
2739  if (ret & FD_CLOEXEC) {
2740  ret &= ~FD_CLOEXEC;
2741  ret = fcntl(fd, F_SETFD, ret); /* async-signal-safe */
2742  if (ret == -1) {
2743  ERRMSG("fcntl(F_SETFD)");
2744  return -1;
2745  }
2746  }
2747 #endif
2748  return 0;
2749 }
2750 
2751 /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
2752 static int
2753 run_exec_dup2(VALUE ary, VALUE tmpbuf, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
2754 {
2755  long n, i;
2756  int ret;
2757  int extra_fd = -1;
2758  struct run_exec_dup2_fd_pair *pairs = 0;
2759 
2760  n = RARRAY_LEN(ary);
2761  pairs = (struct run_exec_dup2_fd_pair *)RSTRING_PTR(tmpbuf);
2762 
2763  /* initialize oldfd and newfd: O(n) */
2764  for (i = 0; i < n; i++) {
2765  VALUE elt = RARRAY_AREF(ary, i);
2766  pairs[i].oldfd = FIX2INT(RARRAY_AREF(elt, 1));
2767  pairs[i].newfd = FIX2INT(RARRAY_AREF(elt, 0)); /* unique */
2768  pairs[i].cloexec = RARRAY_LEN(elt) > 2 && RTEST(RARRAY_AREF(elt, 2));
2769  pairs[i].older_index = -1;
2770  }
2771 
2772  /* sort the table by oldfd: O(n log n) */
2773  if (!sargp)
2774  qsort(pairs, n, sizeof(struct run_exec_dup2_fd_pair), intcmp); /* hopefully async-signal-safe */
2775  else
2776  qsort(pairs, n, sizeof(struct run_exec_dup2_fd_pair), intrcmp);
2777 
2778  /* initialize older_index and num_newer: O(n log n) */
2779  for (i = 0; i < n; i++) {
2780  int newfd = pairs[i].newfd;
2781  struct run_exec_dup2_fd_pair key, *found;
2782  key.oldfd = newfd;
2783  found = bsearch(&key, pairs, n, sizeof(struct run_exec_dup2_fd_pair), intcmp); /* hopefully async-signal-safe */
2784  pairs[i].num_newer = 0;
2785  if (found) {
2786  while (pairs < found && (found-1)->oldfd == newfd)
2787  found--;
2788  while (found < pairs+n && found->oldfd == newfd) {
2789  pairs[i].num_newer++;
2790  found->older_index = i;
2791  found++;
2792  }
2793  }
2794  }
2795 
2796  /* non-cyclic redirection: O(n) */
2797  for (i = 0; i < n; i++) {
2798  long j = i;
2799  while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
2800  if (save_redirect_fd(pairs[j].newfd, sargp, errmsg, errmsg_buflen) < 0) /* async-signal-safe */
2801  goto fail;
2802  ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd); /* async-signal-safe */
2803  if (ret == -1) {
2804  ERRMSG("dup2");
2805  goto fail;
2806  }
2807  if (pairs[j].cloexec &&
2808  fd_set_cloexec(pairs[j].newfd, errmsg, errmsg_buflen)) {
2809  goto fail;
2810  }
2811  rb_update_max_fd(pairs[j].newfd); /* async-signal-safe but don't need to call it in a child process. */
2812  pairs[j].oldfd = -1;
2813  j = pairs[j].older_index;
2814  if (j != -1)
2815  pairs[j].num_newer--;
2816  }
2817  }
2818 
2819  /* cyclic redirection: O(n) */
2820  for (i = 0; i < n; i++) {
2821  long j;
2822  if (pairs[i].oldfd == -1)
2823  continue;
2824  if (pairs[i].oldfd == pairs[i].newfd) { /* self cycle */
2825  if (fd_clear_cloexec(pairs[i].oldfd, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
2826  goto fail;
2827  pairs[i].oldfd = -1;
2828  continue;
2829  }
2830  if (extra_fd == -1) {
2831  extra_fd = redirect_dup(pairs[i].oldfd); /* async-signal-safe */
2832  if (extra_fd == -1) {
2833  ERRMSG("dup");
2834  goto fail;
2835  }
2836  rb_update_max_fd(extra_fd);
2837  }
2838  else {
2839  ret = redirect_dup2(pairs[i].oldfd, extra_fd); /* async-signal-safe */
2840  if (ret == -1) {
2841  ERRMSG("dup2");
2842  goto fail;
2843  }
2844  rb_update_max_fd(extra_fd);
2845  }
2846  pairs[i].oldfd = extra_fd;
2847  j = pairs[i].older_index;
2848  pairs[i].older_index = -1;
2849  while (j != -1) {
2850  ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd); /* async-signal-safe */
2851  if (ret == -1) {
2852  ERRMSG("dup2");
2853  goto fail;
2854  }
2855  rb_update_max_fd(ret);
2856  pairs[j].oldfd = -1;
2857  j = pairs[j].older_index;
2858  }
2859  }
2860  if (extra_fd != -1) {
2861  ret = redirect_close(extra_fd); /* async-signal-safe */
2862  if (ret == -1) {
2863  ERRMSG("close");
2864  goto fail;
2865  }
2866  }
2867 
2868  return 0;
2869 
2870  fail:
2871  return -1;
2872 }
2873 
2874 /* This function should be async-signal-safe. Actually it is. */
2875 static int
2876 run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
2877 {
2878  long i;
2879  int ret;
2880 
2881  for (i = 0; i < RARRAY_LEN(ary); i++) {
2882  VALUE elt = RARRAY_AREF(ary, i);
2883  int fd = FIX2INT(RARRAY_AREF(elt, 0));
2884  ret = redirect_close(fd); /* async-signal-safe */
2885  if (ret == -1) {
2886  ERRMSG("close");
2887  return -1;
2888  }
2889  }
2890  return 0;
2891 }
2892 
2893 /* This function should be async-signal-safe when sargp is NULL. Actually it is. */
2894 static int
2895 run_exec_dup2_child(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
2896 {
2897  long i;
2898  int ret;
2899 
2900  for (i = 0; i < RARRAY_LEN(ary); i++) {
2901  VALUE elt = RARRAY_AREF(ary, i);
2902  int newfd = FIX2INT(RARRAY_AREF(elt, 0));
2903  int oldfd = FIX2INT(RARRAY_AREF(elt, 1));
2904 
2905  if (save_redirect_fd(newfd, sargp, errmsg, errmsg_buflen) < 0) /* async-signal-safe */
2906  return -1;
2907  ret = redirect_dup2(oldfd, newfd); /* async-signal-safe */
2908  if (ret == -1) {
2909  ERRMSG("dup2");
2910  return -1;
2911  }
2912  rb_update_max_fd(newfd);
2913  }
2914  return 0;
2915 }
2916 
2917 #ifdef HAVE_SETPGID
2918 /* This function should be async-signal-safe when sargp is NULL. Actually it is. */
2919 static int
2920 run_exec_pgroup(const struct rb_execarg *eargp, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
2921 {
2922  /*
2923  * If FD_CLOEXEC is available, rb_fork_async_signal_safe waits the child's execve.
2924  * So setpgid is done in the child when rb_fork_async_signal_safe is returned in
2925  * the parent.
2926  * No race condition, even without setpgid from the parent.
2927  * (Is there an environment which has setpgid but no FD_CLOEXEC?)
2928  */
2929  int ret;
2930  rb_pid_t pgroup;
2931 
2932  pgroup = eargp->pgroup_pgid;
2933  if (pgroup == -1)
2934  return 0;
2935 
2936  if (sargp) {
2937  /* maybe meaningless with no fork environment... */
2938  sargp->pgroup_given = 1;
2939  sargp->pgroup_pgid = getpgrp();
2940  }
2941 
2942  if (pgroup == 0) {
2943  pgroup = getpid(); /* async-signal-safe */
2944  }
2945  ret = setpgid(getpid(), pgroup); /* async-signal-safe */
2946  if (ret == -1) ERRMSG("setpgid");
2947  return ret;
2948 }
2949 #endif
2950 
2951 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2952 /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
2953 static int
2954 run_exec_rlimit(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
2955 {
2956  long i;
2957  for (i = 0; i < RARRAY_LEN(ary); i++) {
2958  VALUE elt = RARRAY_AREF(ary, i);
2959  int rtype = NUM2INT(RARRAY_AREF(elt, 0));
2960  struct rlimit rlim;
2961  if (sargp) {
2962  VALUE tmp, newary;
2963  if (getrlimit(rtype, &rlim) == -1) {
2964  ERRMSG("getrlimit");
2965  return -1;
2966  }
2967  tmp = hide_obj(rb_ary_new3(3, RARRAY_AREF(elt, 0),
2968  RLIM2NUM(rlim.rlim_cur),
2969  RLIM2NUM(rlim.rlim_max)));
2970  if (sargp->rlimit_limits == Qfalse)
2971  newary = sargp->rlimit_limits = hide_obj(rb_ary_new());
2972  else
2973  newary = sargp->rlimit_limits;
2974  rb_ary_push(newary, tmp);
2975  }
2976  rlim.rlim_cur = NUM2RLIM(RARRAY_AREF(elt, 1));
2977  rlim.rlim_max = NUM2RLIM(RARRAY_AREF(elt, 2));
2978  if (setrlimit(rtype, &rlim) == -1) { /* hopefully async-signal-safe */
2979  ERRMSG("setrlimit");
2980  return -1;
2981  }
2982  }
2983  return 0;
2984 }
2985 #endif
2986 
2987 #if !defined(HAVE_WORKING_FORK)
2988 static VALUE
2989 save_env_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
2990 {
2991  rb_ary_push(ary, hide_obj(rb_ary_dup(argv[0])));
2992  return Qnil;
2993 }
2994 
2995 static void
2996 save_env(struct rb_execarg *sargp)
2997 {
2998  if (!sargp)
2999  return;
3000  if (sargp->env_modification == Qfalse) {
3001  VALUE env = rb_const_get(rb_cObject, id_ENV);
3002  if (RTEST(env)) {
3003  VALUE ary = hide_obj(rb_ary_new());
3004  rb_block_call(env, idEach, 0, 0, save_env_i,
3005  (VALUE)ary);
3006  sargp->env_modification = ary;
3007  }
3008  sargp->unsetenv_others_given = 1;
3009  sargp->unsetenv_others_do = 1;
3010  }
3011 }
3012 #endif
3013 
3014 #ifdef _WIN32
3015 #undef chdir
3016 #define chdir(p) rb_w32_uchdir(p)
3017 #endif
3018 
3019 /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
3020 int
3021 rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
3022 {
3023  VALUE obj;
3024 
3025  if (sargp) {
3026  /* assume that sargp is always NULL on fork-able environments */
3027  MEMZERO(sargp, struct rb_execarg, 1);
3028  sargp->redirect_fds = Qnil;
3029  }
3030 
3031 #ifdef HAVE_SETPGID
3032  if (eargp->pgroup_given) {
3033  if (run_exec_pgroup(eargp, sargp, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
3034  return -1;
3035  }
3036 #endif
3037 
3038 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
3039  obj = eargp->rlimit_limits;
3040  if (obj != Qfalse) {
3041  if (run_exec_rlimit(obj, sargp, errmsg, errmsg_buflen) == -1) /* hopefully async-signal-safe */
3042  return -1;
3043  }
3044 #endif
3045 
3046 #if !defined(HAVE_WORKING_FORK)
3047  if (eargp->unsetenv_others_given && eargp->unsetenv_others_do) {
3048  save_env(sargp);
3049  rb_env_clear();
3050  }
3051 
3052  obj = eargp->env_modification;
3053  if (obj != Qfalse) {
3054  long i;
3055  save_env(sargp);
3056  for (i = 0; i < RARRAY_LEN(obj); i++) {
3057  VALUE pair = RARRAY_AREF(obj, i);
3058  VALUE key = RARRAY_AREF(pair, 0);
3059  VALUE val = RARRAY_AREF(pair, 1);
3060  if (NIL_P(val))
3061  ruby_setenv(StringValueCStr(key), 0);
3062  else
3064  }
3065  }
3066 #endif
3067 
3068  if (eargp->umask_given) {
3069  mode_t mask = eargp->umask_mask;
3070  mode_t oldmask = umask(mask); /* never fail */ /* async-signal-safe */
3071  if (sargp) {
3072  sargp->umask_given = 1;
3073  sargp->umask_mask = oldmask;
3074  }
3075  }
3076 
3077  obj = eargp->fd_dup2;
3078  if (obj != Qfalse) {
3079  if (run_exec_dup2(obj, eargp->dup2_tmpbuf, sargp, errmsg, errmsg_buflen) == -1) /* hopefully async-signal-safe */
3080  return -1;
3081  }
3082 
3083  obj = eargp->fd_close;
3084  if (obj != Qfalse) {
3085  if (sargp)
3086  rb_warn("cannot close fd before spawn");
3087  else {
3088  if (run_exec_close(obj, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
3089  return -1;
3090  }
3091  }
3092 
3093 #ifdef HAVE_WORKING_FORK
3094  if (!eargp->close_others_given || eargp->close_others_do) {
3095  rb_close_before_exec(3, eargp->close_others_maxhint, eargp->redirect_fds); /* async-signal-safe */
3096  }
3097 #endif
3098 
3099  obj = eargp->fd_dup2_child;
3100  if (obj != Qfalse) {
3101  if (run_exec_dup2_child(obj, sargp, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
3102  return -1;
3103  }
3104 
3105  if (eargp->chdir_given) {
3106  if (sargp) {
3107  char *cwd = my_getcwd();
3108  sargp->chdir_given = 1;
3109  sargp->chdir_dir = hide_obj(rb_str_new2(cwd));
3110  xfree(cwd);
3111  }
3112  if (chdir(RSTRING_PTR(eargp->chdir_dir)) == -1) { /* async-signal-safe */
3113  ERRMSG("chdir");
3114  return -1;
3115  }
3116  }
3117 
3118 #ifdef HAVE_SETGID
3119  if (eargp->gid_given) {
3120  if (setgid(eargp->gid) < 0) {
3121  ERRMSG("setgid");
3122  return -1;
3123  }
3124  }
3125 #endif
3126 #ifdef HAVE_SETUID
3127  if (eargp->uid_given) {
3128  if (setuid(eargp->uid) < 0) {
3129  ERRMSG("setuid");
3130  return -1;
3131  }
3132  }
3133 #endif
3134 
3135  if (sargp) {
3136  VALUE ary = sargp->fd_dup2;
3137  if (ary != Qfalse) {
3138  size_t len = run_exec_dup2_tmpbuf_size(RARRAY_LEN(ary));
3139  VALUE tmpbuf = hide_obj(rb_str_new(0, len));
3140  rb_str_set_len(tmpbuf, len);
3141  sargp->dup2_tmpbuf = tmpbuf;
3142  }
3143  }
3144 
3145  return 0;
3146 }
3147 
3148 /* This function should be async-signal-safe. Hopefully it is. */
3149 int
3150 rb_exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
3151 {
3152 #if !defined(HAVE_WORKING_FORK)
3153  struct rb_execarg sarg, *const sargp = &sarg;
3154 #else
3155  struct rb_execarg *const sargp = NULL;
3156 #endif
3157 
3158  if (rb_execarg_run_options(eargp, sargp, errmsg, errmsg_buflen) < 0) { /* hopefully async-signal-safe */
3159  goto failure;
3160  }
3161 
3162  if (eargp->use_shell) {
3163  proc_exec_sh(RSTRING_PTR(eargp->invoke.sh.shell_script), eargp->envp_str); /* async-signal-safe */
3164  }
3165  else {
3166  char *abspath = NULL;
3167  if (!NIL_P(eargp->invoke.cmd.command_abspath))
3168  abspath = RSTRING_PTR(eargp->invoke.cmd.command_abspath);
3169  proc_exec_cmd(abspath, eargp->invoke.cmd.argv_str, eargp->envp_str); /* async-signal-safe */
3170  }
3171 #if !defined(HAVE_WORKING_FORK)
3172  preserving_errno(rb_execarg_run_options(sargp, NULL, errmsg, errmsg_buflen));
3173 #endif
3174 
3175 failure:
3176  return -1;
3177 }
3178 
3179 #ifdef HAVE_WORKING_FORK
3180 /* This function should be async-signal-safe. Hopefully it is. */
3181 static int
3182 rb_exec_atfork(void* arg, char *errmsg, size_t errmsg_buflen)
3183 {
3184  return rb_exec_async_signal_safe(arg, errmsg, errmsg_buflen); /* hopefully async-signal-safe */
3185 }
3186 #endif
3187 
3188 #ifdef HAVE_WORKING_FORK
3189 #if SIZEOF_INT == SIZEOF_LONG
3190 #define proc_syswait (VALUE (*)(VALUE))rb_syswait
3191 #else
3192 static VALUE
3193 proc_syswait(VALUE pid)
3194 {
3195  rb_syswait((int)pid);
3196  return Qnil;
3197 }
3198 #endif
3199 
3200 static int
3201 move_fds_to_avoid_crash(int *fdp, int n, VALUE fds)
3202 {
3203  int min = 0;
3204  int i;
3205  for (i = 0; i < n; i++) {
3206  int ret;
3207  while (RTEST(rb_hash_lookup(fds, INT2FIX(fdp[i])))) {
3208  if (min <= fdp[i])
3209  min = fdp[i]+1;
3210  while (RTEST(rb_hash_lookup(fds, INT2FIX(min))))
3211  min++;
3212  ret = rb_cloexec_fcntl_dupfd(fdp[i], min);
3213  if (ret == -1)
3214  return -1;
3215  rb_update_max_fd(ret);
3216  close(fdp[i]);
3217  fdp[i] = ret;
3218  }
3219  }
3220  return 0;
3221 }
3222 
3223 static int
3224 pipe_nocrash(int filedes[2], VALUE fds)
3225 {
3226  int ret;
3227  ret = rb_pipe(filedes);
3228  if (ret == -1)
3229  return -1;
3230  if (RTEST(fds)) {
3231  int save = errno;
3232  if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
3233  close(filedes[0]);
3234  close(filedes[1]);
3235  return -1;
3236  }
3237  errno = save;
3238  }
3239  return ret;
3240 }
3241 
3242 #ifndef O_BINARY
3243 #define O_BINARY 0
3244 #endif
3245 
3246 static int
3247 handle_fork_error(int *status, int *ep, volatile int *try_gc_p)
3248 {
3249  int state = 0;
3250 
3251  switch (errno) {
3252  case ENOMEM:
3253  if ((*try_gc_p)-- > 0 && !rb_during_gc()) {
3254  rb_gc();
3255  return 0;
3256  }
3257  break;
3258  case EAGAIN:
3259 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
3260  case EWOULDBLOCK:
3261 #endif
3262  if (!status && !ep) {
3263  rb_thread_sleep(1);
3264  return 0;
3265  }
3266  else {
3267  rb_protect((VALUE (*)())rb_thread_sleep, 1, &state);
3268  if (status) *status = state;
3269  if (!state) return 0;
3270  }
3271  break;
3272  }
3273  if (ep) {
3274  preserving_errno((close(ep[0]), close(ep[1])));
3275  }
3276  if (state && !status) rb_jump_tag(state);
3277  return -1;
3278 }
3279 
3280 #define prefork() ( \
3281  rb_io_flush(rb_stdout), \
3282  rb_io_flush(rb_stderr) \
3283  )
3284 
3285 /*
3286  * Forks child process, and returns the process ID in the parent
3287  * process.
3288  *
3289  * If +status+ is given, protects from any exceptions and sets the
3290  * jump status to it, and returns -1. If failed to fork new process
3291  * but no exceptions occurred, sets 0 to it. Otherwise, if forked
3292  * successfully, the value of +status+ is undetermined.
3293  *
3294  * In the child process, just returns 0 if +chfunc+ is +NULL+.
3295  * Otherwise +chfunc+ will be called with +charg+, and then the child
3296  * process exits with +EXIT_SUCCESS+ when it returned zero.
3297  *
3298  * In the case of the function is called and returns non-zero value,
3299  * the child process exits with non-+EXIT_SUCCESS+ value (normally
3300  * 127). And, on the platforms where +FD_CLOEXEC+ is available,
3301  * +errno+ is propagated to the parent process, and this function
3302  * returns -1 in the parent process. On the other platforms, just
3303  * returns pid.
3304  *
3305  * If fds is not Qnil, internal pipe for the errno propagation is
3306  * arranged to avoid conflicts of the hash keys in +fds+.
3307  *
3308  * +chfunc+ must not raise any exceptions.
3309  */
3310 
3311 static ssize_t
3312 write_retry(int fd, const void *buf, size_t len)
3313 {
3314  ssize_t w;
3315 
3316  do {
3317  w = write(fd, buf, len);
3318  } while (w < 0 && errno == EINTR);
3319 
3320  return w;
3321 }
3322 
3323 static ssize_t
3324 read_retry(int fd, void *buf, size_t len)
3325 {
3326  ssize_t r;
3327 
3328  do {
3329  r = read(fd, buf, len);
3330  } while (r < 0 && errno == EINTR);
3331 
3332  return r;
3333 }
3334 
3335 static void
3336 send_child_error(int fd, char *errmsg, size_t errmsg_buflen)
3337 {
3338  int err;
3339 
3340  err = errno;
3341  if (write_retry(fd, &err, sizeof(err)) < 0) err = errno;
3342  if (errmsg && 0 < errmsg_buflen) {
3343  errmsg[errmsg_buflen-1] = '\0';
3344  errmsg_buflen = strlen(errmsg);
3345  if (errmsg_buflen > 0 && write_retry(fd, errmsg, errmsg_buflen) < 0)
3346  err = errno;
3347  }
3348 }
3349 
3350 static int
3351 recv_child_error(int fd, int *errp, char *errmsg, size_t errmsg_buflen)
3352 {
3353  int err;
3354  ssize_t size;
3355  if ((size = read_retry(fd, &err, sizeof(err))) < 0) {
3356  err = errno;
3357  }
3358  *errp = err;
3359  if (size == sizeof(err) &&
3360  errmsg && 0 < errmsg_buflen) {
3361  ssize_t ret = read_retry(fd, errmsg, errmsg_buflen-1);
3362  if (0 <= ret) {
3363  errmsg[ret] = '\0';
3364  }
3365  }
3366  close(fd);
3367  return size != 0;
3368 }
3369 
3370 #ifdef HAVE_WORKING_VFORK
3371 #if !defined(HAVE_GETRESUID) && defined(HAVE_GETUIDX)
3372 /* AIX 7.1 */
3373 static int
3374 getresuid(rb_uid_t *ruid, rb_uid_t *euid, rb_uid_t *suid)
3375 {
3376  rb_uid_t ret;
3377 
3378  *ruid = getuid();
3379  *euid = geteuid();
3380  ret = getuidx(ID_SAVED);
3381  if (ret == (rb_uid_t)-1)
3382  return -1;
3383  *suid = ret;
3384  return 0;
3385 }
3386 #define HAVE_GETRESUID
3387 #endif
3388 
3389 #if !defined(HAVE_GETRESGID) && defined(HAVE_GETGIDX)
3390 /* AIX 7.1 */
3391 static int
3392 getresgid(rb_gid_t *rgid, rb_gid_t *egid, rb_gid_t *sgid)
3393 {
3394  rb_gid_t ret;
3395 
3396  *rgid = getgid();
3397  *egid = getegid();
3398  ret = getgidx(ID_SAVED);
3399  if (ret == (rb_gid_t)-1)
3400  return -1;
3401  *sgid = ret;
3402  return 0;
3403 }
3404 #define HAVE_GETRESGID
3405 #endif
3406 
3407 static int
3408 has_privilege(void)
3409 {
3410  /*
3411  * has_privilege() is used to choose vfork() or fork().
3412  *
3413  * If the process has privilege, the parent process or
3414  * the child process can change UID/GID.
3415  * If vfork() is used to create the child process and
3416  * the parent or child process change effective UID/GID,
3417  * different privileged processes shares memory.
3418  * It is a bad situation.
3419  * So, fork() should be used.
3420  */
3421 
3422  rb_uid_t ruid, euid;
3423  rb_gid_t rgid, egid;
3424 
3425 #if defined HAVE_ISSETUGID
3426  if (issetugid())
3427  return 1;
3428 #endif
3429 
3430 #ifdef HAVE_GETRESUID
3431  {
3432  int ret;
3433  rb_uid_t suid;
3434  ret = getresuid(&ruid, &euid, &suid);
3435  if (ret == -1)
3436  rb_sys_fail("getresuid(2)");
3437  if (euid != suid)
3438  return 1;
3439  }
3440 #else
3441  ruid = getuid();
3442  euid = geteuid();
3443 #endif
3444 
3445  if (euid == 0 || euid != ruid)
3446  return 1;
3447 
3448 #ifdef HAVE_GETRESGID
3449  {
3450  int ret;
3451  rb_gid_t sgid;
3452  ret = getresgid(&rgid, &egid, &sgid);
3453  if (ret == -1)
3454  rb_sys_fail("getresgid(2)");
3455  if (egid != sgid)
3456  return 1;
3457  }
3458 #else
3459  rgid = getgid();
3460  egid = getegid();
3461 #endif
3462 
3463  if (egid != rgid)
3464  return 1;
3465 
3466  return 0;
3467 }
3468 #endif
3469 
3470 struct child_handler_disabler_state
3471 {
3472  sigset_t sigmask;
3473  int cancelstate;
3474 };
3475 
3476 static void
3477 disable_child_handler_before_fork(struct child_handler_disabler_state *old)
3478 {
3479  int ret;
3480  sigset_t all;
3481 
3482 #ifdef HAVE_PTHREAD_SIGMASK
3483  ret = sigfillset(&all);
3484  if (ret == -1)
3485  rb_sys_fail("sigfillset");
3486 
3487  ret = pthread_sigmask(SIG_SETMASK, &all, &old->sigmask); /* not async-signal-safe */
3488  if (ret != 0) {
3489  rb_syserr_fail(ret, "pthread_sigmask");
3490  }
3491 #else
3492 # pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous"
3493 #endif
3494 
3495 #ifdef PTHREAD_CANCEL_DISABLE
3496  ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old->cancelstate);
3497  if (ret != 0) {
3498  rb_syserr_fail(ret, "pthread_setcancelstate");
3499  }
3500 #endif
3501 }
3502 
3503 static void
3504 disable_child_handler_fork_parent(struct child_handler_disabler_state *old)
3505 {
3506  int ret;
3507 
3508 #ifdef PTHREAD_CANCEL_DISABLE
3509  ret = pthread_setcancelstate(old->cancelstate, NULL);
3510  if (ret != 0) {
3511  rb_syserr_fail(ret, "pthread_setcancelstate");
3512  }
3513 #endif
3514 
3515 #ifdef HAVE_PTHREAD_SIGMASK
3516  ret = pthread_sigmask(SIG_SETMASK, &old->sigmask, NULL); /* not async-signal-safe */
3517  if (ret != 0) {
3518  rb_syserr_fail(ret, "pthread_sigmask");
3519  }
3520 #else
3521 # pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous"
3522 #endif
3523 }
3524 
3525 /* This function should be async-signal-safe. Actually it is. */
3526 static int
3527 disable_child_handler_fork_child(struct child_handler_disabler_state *old, char *errmsg, size_t errmsg_buflen)
3528 {
3529  int sig;
3530  int ret;
3531 
3532  for (sig = 1; sig < NSIG; sig++) {
3533  sig_t handler = signal(sig, SIG_DFL);
3534 
3535  if (handler == SIG_ERR && errno == EINVAL) {
3536  continue; /* Ignore invalid signal number */
3537  }
3538  if (handler == SIG_ERR) {
3539  ERRMSG("signal to obtain old action");
3540  return -1;
3541  }
3542 #ifdef SIGPIPE
3543  if (sig == SIGPIPE) {
3544  continue;
3545  }
3546 #endif
3547  /* it will be reset to SIG_DFL at execve time, instead */
3548  if (handler == SIG_IGN) {
3549  signal(sig, SIG_IGN);
3550  }
3551  }
3552 
3553  ret = sigprocmask(SIG_SETMASK, &old->sigmask, NULL); /* async-signal-safe */
3554  if (ret != 0) {
3555  ERRMSG("sigprocmask");
3556  return -1;
3557  }
3558  return 0;
3559 }
3560 
3561 static rb_pid_t
3562 retry_fork_async_signal_safe(int *status, int *ep,
3563  int (*chfunc)(void*, char *, size_t), void *charg,
3564  char *errmsg, size_t errmsg_buflen)
3565 {
3566  rb_pid_t pid;
3567  volatile int try_gc = 1;
3568  struct child_handler_disabler_state old;
3569 
3570  while (1) {
3571  prefork();
3572  disable_child_handler_before_fork(&old);
3573 #ifdef HAVE_WORKING_VFORK
3574  if (!has_privilege())
3575  pid = vfork();
3576  else
3577  pid = fork();
3578 #else
3579  pid = fork();
3580 #endif
3581  if (pid == 0) {/* fork succeed, child process */
3582  int ret;
3583  close(ep[0]);
3584  ret = disable_child_handler_fork_child(&old, errmsg, errmsg_buflen); /* async-signal-safe */
3585  if (ret == 0) {
3586  ret = chfunc(charg, errmsg, errmsg_buflen);
3587  if (!ret) _exit(EXIT_SUCCESS);
3588  }
3589  send_child_error(ep[1], errmsg, errmsg_buflen);
3590 #if EXIT_SUCCESS == 127
3591  _exit(EXIT_FAILURE);
3592 #else
3593  _exit(127);
3594 #endif
3595  }
3596  preserving_errno(disable_child_handler_fork_parent(&old));
3597  if (0 < pid) /* fork succeed, parent process */
3598  return pid;
3599  /* fork failed */
3600  if (handle_fork_error(status, ep, &try_gc))
3601  return -1;
3602  }
3603 }
3604 
3605 rb_pid_t
3606 rb_fork_async_signal_safe(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds,
3607  char *errmsg, size_t errmsg_buflen)
3608 {
3609  rb_pid_t pid;
3610  int err;
3611  int ep[2];
3612  int error_occurred;
3613 
3614  if (status) *status = 0;
3615 
3616  if (pipe_nocrash(ep, fds)) return -1;
3617  pid = retry_fork_async_signal_safe(status, ep, chfunc, charg, errmsg, errmsg_buflen);
3618  if (pid < 0)
3619  return pid;
3620  close(ep[1]);
3621  error_occurred = recv_child_error(ep[0], &err, errmsg, errmsg_buflen);
3622  if (error_occurred) {
3623  if (status) {
3624  rb_protect(proc_syswait, (VALUE)pid, status);
3625  }
3626  else {
3627  rb_syswait(pid);
3628  }
3629  errno = err;
3630  return -1;
3631  }
3632  return pid;
3633 }
3634 
3635 static rb_pid_t
3636 retry_fork_ruby(int *status, struct child_handler_disabler_state *old)
3637 {
3638  rb_pid_t pid;
3639  int try_gc = 1;
3640 
3641  while (1) {
3642  prefork();
3643  before_fork_ruby();
3644  disable_child_handler_before_fork(old);
3645  pid = fork();
3646  if (pid == 0) /* fork succeed, child process */
3647  return pid;
3649  preserving_errno(disable_child_handler_fork_parent(old));
3650  if (0 < pid) /* fork succeed, parent process */
3651  return pid;
3652  /* fork failed */
3653  if (handle_fork_error(status, NULL, &try_gc))
3654  return -1;
3655  }
3656 }
3657 
3658 rb_pid_t
3659 rb_fork_ruby(int *status)
3660 {
3661  rb_pid_t pid;
3662  struct child_handler_disabler_state old;
3663 
3664  if (status) *status = 0;
3665 
3666  pid = retry_fork_ruby(status, &old);
3667  if (pid < 0)
3668  return pid;
3669  if (!pid) {
3670  after_fork_ruby();
3671  disable_child_handler_fork_parent(&old); /* yes, bad name */
3672  }
3673  return pid;
3674 }
3675 
3676 #endif
3677 
3678 #if defined(HAVE_WORKING_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
3679 /*
3680  * call-seq:
3681  * Kernel.fork [{ block }] -> integer or nil
3682  * Process.fork [{ block }] -> integer or nil
3683  *
3684  * Creates a subprocess. If a block is specified, that block is run
3685  * in the subprocess, and the subprocess terminates with a status of
3686  * zero. Otherwise, the +fork+ call returns twice, once in
3687  * the parent, returning the process ID of the child, and once in
3688  * the child, returning _nil_. The child process can exit using
3689  * <code>Kernel.exit!</code> to avoid running any
3690  * <code>at_exit</code> functions. The parent process should
3691  * use <code>Process.wait</code> to collect the termination statuses
3692  * of its children or use <code>Process.detach</code> to register
3693  * disinterest in their status; otherwise, the operating system
3694  * may accumulate zombie processes.
3695  *
3696  * The thread calling fork is the only thread in the created child process.
3697  * fork doesn't copy other threads.
3698  *
3699  * If fork is not usable, Process.respond_to?(:fork) returns false.
3700  *
3701  * Note that fork(2) is not available on some platforms like Windows and NetBSD 4.
3702  * Therefore you should use spawn() instead of fork().
3703  */
3704 
3705 static VALUE
3706 rb_f_fork(VALUE obj)
3707 {
3708  rb_pid_t pid;
3709 
3710  switch (pid = rb_fork_ruby(NULL)) {
3711  case 0:
3712  rb_thread_atfork();
3713  if (rb_block_given_p()) {
3714  int status;
3715  rb_protect(rb_yield, Qundef, &status);
3716  ruby_stop(status);
3717  }
3718  return Qnil;
3719 
3720  case -1:
3721  rb_sys_fail("fork(2)");
3722  return Qnil;
3723 
3724  default:
3725  return PIDT2NUM(pid);
3726  }
3727 }
3728 #else
3729 #define rb_f_fork rb_f_notimplement
3730 #endif
3731 
3732 static int
3733 exit_status_code(VALUE status)
3734 {
3735  int istatus;
3736 
3737  switch (status) {
3738  case Qtrue:
3739  istatus = EXIT_SUCCESS;
3740  break;
3741  case Qfalse:
3742  istatus = EXIT_FAILURE;
3743  break;
3744  default:
3745  istatus = NUM2INT(status);
3746 #if EXIT_SUCCESS != 0
3747  if (istatus == 0)
3748  istatus = EXIT_SUCCESS;
3749 #endif
3750  break;
3751  }
3752  return istatus;
3753 }
3754 
3755 /*
3756  * call-seq:
3757  * Process.exit!(status=false)
3758  *
3759  * Exits the process immediately. No exit handlers are
3760  * run. <em>status</em> is returned to the underlying system as the
3761  * exit status.
3762  *
3763  * Process.exit!(true)
3764  */
3765 
3766 static VALUE
3767 rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
3768 {
3769  int istatus;
3770 
3771  if (rb_check_arity(argc, 0, 1) == 1) {
3772  istatus = exit_status_code(argv[0]);
3773  }
3774  else {
3775  istatus = EXIT_FAILURE;
3776  }
3777  _exit(istatus);
3778 
3779  UNREACHABLE;
3780 }
3781 
3782 void
3783 rb_exit(int status)
3784 {
3785  if (GET_THREAD()->ec.tag) {
3786  VALUE args[2];
3787 
3788  args[0] = INT2NUM(status);
3789  args[1] = rb_str_new2("exit");
3791  }
3792  ruby_stop(status);
3793 }
3794 
3795 
3796 /*
3797  * call-seq:
3798  * exit(status=true)
3799  * Kernel::exit(status=true)
3800  * Process::exit(status=true)
3801  *
3802  * Initiates the termination of the Ruby script by raising the
3803  * <code>SystemExit</code> exception. This exception may be caught. The
3804  * optional parameter is used to return a status code to the invoking
3805  * environment.
3806  * +true+ and +FALSE+ of _status_ means success and failure
3807  * respectively. The interpretation of other integer values are
3808  * system dependent.
3809  *
3810  * begin
3811  * exit
3812  * puts "never get here"
3813  * rescue SystemExit
3814  * puts "rescued a SystemExit exception"
3815  * end
3816  * puts "after begin block"
3817  *
3818  * <em>produces:</em>
3819  *
3820  * rescued a SystemExit exception
3821  * after begin block
3822  *
3823  * Just prior to termination, Ruby executes any <code>at_exit</code> functions
3824  * (see Kernel::at_exit) and runs any object finalizers (see
3825  * ObjectSpace::define_finalizer).
3826  *
3827  * at_exit { puts "at_exit function" }
3828  * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
3829  * exit
3830  *
3831  * <em>produces:</em>
3832  *
3833  * at_exit function
3834  * in finalizer
3835  */
3836 
3837 VALUE
3838 rb_f_exit(int argc, const VALUE *argv)
3839 {
3840  int istatus;
3841 
3842  if (rb_check_arity(argc, 0, 1) == 1) {
3843  istatus = exit_status_code(argv[0]);
3844  }
3845  else {
3846  istatus = EXIT_SUCCESS;
3847  }
3848  rb_exit(istatus);
3849 
3850  UNREACHABLE;
3851 }
3852 
3853 
3854 /*
3855  * call-seq:
3856  * abort
3857  * Kernel::abort([msg])
3858  * Process.abort([msg])
3859  *
3860  * Terminate execution immediately, effectively by calling
3861  * <code>Kernel.exit(false)</code>. If _msg_ is given, it is written
3862  * to STDERR prior to terminating.
3863  */
3864 
3865 VALUE
3866 rb_f_abort(int argc, const VALUE *argv)
3867 {
3868  rb_check_arity(argc, 0, 1);
3869  if (argc == 0) {
3870  rb_thread_t *th = GET_THREAD();
3871  VALUE errinfo = th->ec.errinfo;
3872  if (!NIL_P(errinfo)) {
3873  rb_threadptr_error_print(th, errinfo);
3874  }
3876  }
3877  else {
3878  VALUE args[2];
3879 
3880  args[1] = args[0] = argv[0];
3881  StringValue(args[0]);
3882  rb_io_puts(1, args, rb_stderr);
3883  args[0] = INT2NUM(EXIT_FAILURE);
3885  }
3886 
3887  UNREACHABLE;
3888 }
3889 
3890 void
3891 rb_syswait(rb_pid_t pid)
3892 {
3893  int status;
3894 
3895  rb_waitpid(pid, &status, 0);
3896 }
3897 
3898 #if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV
3899 char *
3900 rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
3901 {
3902  VALUE cmd = *prog;
3903  if (eargp && !eargp->use_shell) {
3904  VALUE str = eargp->invoke.cmd.argv_str;
3905  VALUE buf = eargp->invoke.cmd.argv_buf;
3906  char *p, **argv = ARGVSTR2ARGV(str);
3907  long i, argc = ARGVSTR2ARGC(str);
3908  const char *start = RSTRING_PTR(buf);
3909  cmd = rb_str_new(start, RSTRING_LEN(buf));
3910  p = RSTRING_PTR(cmd);
3911  for (i = 1; i < argc; ++i) {
3912  p[argv[i] - start - 1] = ' ';
3913  }
3914  *prog = cmd;
3915  return p;
3916  }
3917  return StringValueCStr(*prog);
3918 }
3919 #endif
3920 
3921 static rb_pid_t
3922 rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
3923 {
3924  rb_pid_t pid;
3925 #if !defined HAVE_WORKING_FORK || USE_SPAWNV
3926  VALUE prog;
3927  struct rb_execarg sarg;
3928 # if !defined HAVE_SPAWNV
3929  int status;
3930 # endif
3931 #endif
3932 
3933 #if defined HAVE_WORKING_FORK && !USE_SPAWNV
3934  pid = rb_fork_async_signal_safe(NULL, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen);
3935 #else
3936  prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
3937 
3938  if (rb_execarg_run_options(eargp, &sarg, errmsg, errmsg_buflen) < 0) {
3939  return -1;
3940  }
3941 
3942  if (prog && !eargp->use_shell) {
3943  char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
3944  argv[0] = RSTRING_PTR(prog);
3945  }
3946 # if defined HAVE_SPAWNV
3947  if (eargp->use_shell) {
3948  pid = proc_spawn_sh(RSTRING_PTR(prog));
3949  }
3950  else {
3951  char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
3952  pid = proc_spawn_cmd(argv, prog, eargp);
3953  }
3954  if (pid == -1)
3955  rb_last_status_set(0x7f << 8, 0);
3956 # else
3957  status = system(rb_execarg_commandline(eargp, &prog));
3958  rb_last_status_set((status & 0xff) << 8, 0);
3959  pid = 1; /* dummy */
3960 # endif
3961 
3962  rb_execarg_run_options(&sarg, NULL, errmsg, errmsg_buflen);
3963 #endif
3964  return pid;
3965 }
3966 
3967 struct spawn_args {
3969  struct {
3970  char *ptr;
3971  size_t buflen;
3972  } errmsg;
3973 };
3974 
3975 static VALUE
3976 do_spawn_process(VALUE arg)
3977 {
3978  struct spawn_args *argp = (struct spawn_args *)arg;
3979  rb_execarg_parent_start1(argp->execarg);
3980  return (VALUE)rb_spawn_process(DATA_PTR(argp->execarg),
3981  argp->errmsg.ptr, argp->errmsg.buflen);
3982 }
3983 
3984 static rb_pid_t
3985 rb_execarg_spawn(VALUE execarg_obj, char *errmsg, size_t errmsg_buflen)
3986 {
3987  struct spawn_args args;
3988 
3989  args.execarg = execarg_obj;
3990  args.errmsg.ptr = errmsg;
3991  args.errmsg.buflen = errmsg_buflen;
3992  return (rb_pid_t)rb_ensure(do_spawn_process, (VALUE)&args,
3993  execarg_parent_end, execarg_obj);
3994 }
3995 
3996 static rb_pid_t
3997 rb_spawn_internal(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
3998 {
3999  VALUE execarg_obj;
4000 
4001  execarg_obj = rb_execarg_new(argc, argv, TRUE);
4002  return rb_execarg_spawn(execarg_obj, errmsg, errmsg_buflen);
4003 }
4004 
4005 rb_pid_t
4006 rb_spawn_err(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
4007 {
4008  return rb_spawn_internal(argc, argv, errmsg, errmsg_buflen);
4009 }
4010 
4011 rb_pid_t
4012 rb_spawn(int argc, const VALUE *argv)
4013 {
4014  return rb_spawn_internal(argc, argv, NULL, 0);
4015 }
4016 
4017 /*
4018  * call-seq:
4019  * system([env,] command... [,options]) -> true, false or nil
4020  *
4021  * Executes _command..._ in a subshell.
4022  * _command..._ is one of following forms.
4023  *
4024  * commandline : command line string which is passed to the standard shell
4025  * cmdname, arg1, ... : command name and one or more arguments (no shell)
4026  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
4027  *
4028  * system returns +true+ if the command gives zero exit status,
4029  * +false+ for non zero exit status.
4030  * Returns +nil+ if command execution fails.
4031  * An error status is available in <code>$?</code>.
4032  * The arguments are processed in the same way as
4033  * for <code>Kernel.spawn</code>.
4034  *
4035  * The hash arguments, env and options, are same as
4036  * <code>exec</code> and <code>spawn</code>.
4037  * See <code>Kernel.spawn</code> for details.
4038  *
4039  * system("echo *")
4040  * system("echo", "*")
4041  *
4042  * <em>produces:</em>
4043  *
4044  * config.h main.rb
4045  * *
4046  *
4047  * See <code>Kernel.exec</code> for the standard shell.
4048  */
4049 
4050 static VALUE
4051 rb_f_system(int argc, VALUE *argv)
4052 {
4053  rb_pid_t pid;
4054  int status;
4055 
4056 #if defined(SIGCLD) && !defined(SIGCHLD)
4057 # define SIGCHLD SIGCLD
4058 #endif
4059 
4060 #ifdef SIGCHLD
4061  RETSIGTYPE (*chfunc)(int);
4062 
4064  chfunc = signal(SIGCHLD, SIG_DFL);
4065 #endif
4066  pid = rb_spawn_internal(argc, argv, NULL, 0);
4067 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
4068  if (pid > 0) {
4069  int ret, status;
4070  ret = rb_waitpid(pid, &status, 0);
4071  if (ret == (rb_pid_t)-1)
4072  rb_sys_fail("Another thread waited the process started by system().");
4073  }
4074 #endif
4075 #ifdef SIGCHLD
4076  signal(SIGCHLD, chfunc);
4077 #endif
4078  if (pid < 0) {
4079  return Qnil;
4080  }
4081  status = PST2INT(rb_last_status_get());
4082  if (status == EXIT_SUCCESS) return Qtrue;
4083  return Qfalse;
4084 }
4085 
4086 /*
4087  * call-seq:
4088  * spawn([env,] command... [,options]) -> pid
4089  * Process.spawn([env,] command... [,options]) -> pid
4090  *
4091  * spawn executes specified command and return its pid.
4092  *
4093  * pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
4094  * Process.wait pid
4095  *
4096  * pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
4097  * Process.wait pid
4098  *
4099  * This method is similar to Kernel#system but it doesn't wait for the command
4100  * to finish.
4101  *
4102  * The parent process should
4103  * use <code>Process.wait</code> to collect
4104  * the termination status of its child or
4105  * use <code>Process.detach</code> to register
4106  * disinterest in their status;
4107  * otherwise, the operating system may accumulate zombie processes.
4108  *
4109  * spawn has bunch of options to specify process attributes:
4110  *
4111  * env: hash
4112  * name => val : set the environment variable
4113  * name => nil : unset the environment variable
4114  *
4115  * the keys and the values except for +nil+ must be strings.
4116  * command...:
4117  * commandline : command line string which is passed to the standard shell
4118  * cmdname, arg1, ... : command name and one or more arguments (This form does not use the shell. See below for caveats.)
4119  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
4120  * options: hash
4121  * clearing environment variables:
4122  * :unsetenv_others => true : clear environment variables except specified by env
4123  * :unsetenv_others => false : don't clear (default)
4124  * process group:
4125  * :pgroup => true or 0 : make a new process group
4126  * :pgroup => pgid : join the specified process group
4127  * :pgroup => nil : don't change the process group (default)
4128  * create new process group: Windows only
4129  * :new_pgroup => true : the new process is the root process of a new process group
4130  * :new_pgroup => false : don't create a new process group (default)
4131  * resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
4132  * :rlimit_resourcename => limit
4133  * :rlimit_resourcename => [cur_limit, max_limit]
4134  * umask:
4135  * :umask => int
4136  * redirection:
4137  * key:
4138  * FD : single file descriptor in child process
4139  * [FD, FD, ...] : multiple file descriptor in child process
4140  * value:
4141  * FD : redirect to the file descriptor in parent process
4142  * string : redirect to file with open(string, "r" or "w")
4143  * [string] : redirect to file with open(string, File::RDONLY)
4144  * [string, open_mode] : redirect to file with open(string, open_mode, 0644)
4145  * [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
4146  * [:child, FD] : redirect to the redirected file descriptor
4147  * :close : close the file descriptor in child process
4148  * FD is one of follows
4149  * :in : the file descriptor 0 which is the standard input
4150  * :out : the file descriptor 1 which is the standard output
4151  * :err : the file descriptor 2 which is the standard error
4152  * integer : the file descriptor of specified the integer
4153  * io : the file descriptor specified as io.fileno
4154  * file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
4155  * :close_others => true : don't inherit
4156  * current directory:
4157  * :chdir => str
4158  *
4159  * The 'cmdname, arg1, ...' form does not use the shell. However,
4160  * on different OSes, different things are provided as built-in
4161  * commands. An example of this is 'echo', which is a built-in
4162  * on Windows, but is a normal program on Linux and Mac OS X.
4163  * This means that `Process.spawn 'echo', '%Path%'` will display
4164  * the contents of the `%Path%` environment variable on Windows,
4165  * but `Process.spawn 'echo', '$PATH'` prints the literal '$PATH'.
4166  *
4167  * If a hash is given as +env+, the environment is
4168  * updated by +env+ before <code>exec(2)</code> in the child process.
4169  * If a pair in +env+ has nil as the value, the variable is deleted.
4170  *
4171  * # set FOO as BAR and unset BAZ.
4172  * pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
4173  *
4174  * If a hash is given as +options+,
4175  * it specifies
4176  * process group,
4177  * create new process group,
4178  * resource limit,
4179  * current directory,
4180  * umask and
4181  * redirects for the child process.
4182  * Also, it can be specified to clear environment variables.
4183  *
4184  * The <code>:unsetenv_others</code> key in +options+ specifies
4185  * to clear environment variables, other than specified by +env+.
4186  *
4187  * pid = spawn(command, :unsetenv_others=>true) # no environment variable
4188  * pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
4189  *
4190  * The <code>:pgroup</code> key in +options+ specifies a process group.
4191  * The corresponding value should be true, zero, a positive integer, or nil.
4192  * true and zero cause the process to be a process leader of a new process group.
4193  * A non-zero positive integer causes the process to join the provided process group.
4194  * The default value, nil, causes the process to remain in the same process group.
4195  *
4196  * pid = spawn(command, :pgroup=>true) # process leader
4197  * pid = spawn(command, :pgroup=>10) # belongs to the process group 10
4198  *
4199  * The <code>:new_pgroup</code> key in +options+ specifies to pass
4200  * +CREATE_NEW_PROCESS_GROUP+ flag to <code>CreateProcessW()</code> that is
4201  * Windows API. This option is only for Windows.
4202  * true means the new process is the root process of the new process group.
4203  * The new process has CTRL+C disabled. This flag is necessary for
4204  * <code>Process.kill(:SIGINT, pid)</code> on the subprocess.
4205  * :new_pgroup is false by default.
4206  *
4207  * pid = spawn(command, :new_pgroup=>true) # new process group
4208  * pid = spawn(command, :new_pgroup=>false) # same process group
4209  *
4210  * The <code>:rlimit_</code><em>foo</em> key specifies a resource limit.
4211  * <em>foo</em> should be one of resource types such as <code>core</code>.
4212  * The corresponding value should be an integer or an array which have one or
4213  * two integers: same as cur_limit and max_limit arguments for
4214  * Process.setrlimit.
4215  *
4216  * cur, max = Process.getrlimit(:CORE)
4217  * pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
4218  * pid = spawn(command, :rlimit_core=>max) # enable core dump
4219  * pid = spawn(command, :rlimit_core=>0) # never dump core.
4220  *
4221  * The <code>:umask</code> key in +options+ specifies the umask.
4222  *
4223  * pid = spawn(command, :umask=>077)
4224  *
4225  * The :in, :out, :err, an integer, an IO and an array key specifies a redirection.
4226  * The redirection maps a file descriptor in the child process.
4227  *
4228  * For example, stderr can be merged into stdout as follows:
4229  *
4230  * pid = spawn(command, :err=>:out)
4231  * pid = spawn(command, 2=>1)
4232  * pid = spawn(command, STDERR=>:out)
4233  * pid = spawn(command, STDERR=>STDOUT)
4234  *
4235  * The hash keys specifies a file descriptor
4236  * in the child process started by <code>spawn</code>.
4237  * :err, 2 and STDERR specifies the standard error stream (stderr).
4238  *
4239  * The hash values specifies a file descriptor
4240  * in the parent process which invokes <code>spawn</code>.
4241  * :out, 1 and STDOUT specifies the standard output stream (stdout).
4242  *
4243  * In the above example,
4244  * the standard output in the child process is not specified.
4245  * So it is inherited from the parent process.
4246  *
4247  * The standard input stream (stdin) can be specified by :in, 0 and STDIN.
4248  *
4249  * A filename can be specified as a hash value.
4250  *
4251  * pid = spawn(command, :in=>"/dev/null") # read mode
4252  * pid = spawn(command, :out=>"/dev/null") # write mode
4253  * pid = spawn(command, :err=>"log") # write mode
4254  * pid = spawn(command, [:out, :err]=>"/dev/null") # write mode
4255  * pid = spawn(command, 3=>"/dev/null") # read mode
4256  *
4257  * For stdout and stderr (and combination of them),
4258  * it is opened in write mode.
4259  * Otherwise read mode is used.
4260  *
4261  * For specifying flags and permission of file creation explicitly,
4262  * an array is used instead.
4263  *
4264  * pid = spawn(command, :in=>["file"]) # read mode is assumed
4265  * pid = spawn(command, :in=>["file", "r"])
4266  * pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
4267  * pid = spawn(command, :out=>["log", "w", 0600])
4268  * pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
4269  *
4270  * The array specifies a filename, flags and permission.
4271  * The flags can be a string or an integer.
4272  * If the flags is omitted or nil, File::RDONLY is assumed.
4273  * The permission should be an integer.
4274  * If the permission is omitted or nil, 0644 is assumed.
4275  *
4276  * If an array of IOs and integers are specified as a hash key,
4277  * all the elements are redirected.
4278  *
4279  * # stdout and stderr is redirected to log file.
4280  * # The file "log" is opened just once.
4281  * pid = spawn(command, [:out, :err]=>["log", "w"])
4282  *
4283  * Another way to merge multiple file descriptors is [:child, fd].
4284  * \[:child, fd] means the file descriptor in the child process.
4285  * This is different from fd.
4286  * For example, :err=>:out means redirecting child stderr to parent stdout.
4287  * But :err=>[:child, :out] means redirecting child stderr to child stdout.
4288  * They differ if stdout is redirected in the child process as follows.
4289  *
4290  * # stdout and stderr is redirected to log file.
4291  * # The file "log" is opened just once.
4292  * pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
4293  *
4294  * \[:child, :out] can be used to merge stderr into stdout in IO.popen.
4295  * In this case, IO.popen redirects stdout to a pipe in the child process
4296  * and [:child, :out] refers the redirected stdout.
4297  *
4298  * io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
4299  * p io.read #=> "out\nerr\n"
4300  *
4301  * The <code>:chdir</code> key in +options+ specifies the current directory.
4302  *
4303  * pid = spawn(command, :chdir=>"/var/tmp")
4304  *
4305  * spawn closes all non-standard unspecified descriptors by default.
4306  * The "standard" descriptors are 0, 1 and 2.
4307  * This behavior is specified by :close_others option.
4308  * :close_others doesn't affect the standard descriptors which are
4309  * closed only if :close is specified explicitly.
4310  *
4311  * pid = spawn(command, :close_others=>true) # close 3,4,5,... (default)
4312  * pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
4313  *
4314  * :close_others is true by default for spawn and IO.popen.
4315  *
4316  * Note that fds which close-on-exec flag is already set are closed
4317  * regardless of :close_others option.
4318  *
4319  * So IO.pipe and spawn can be used as IO.popen.
4320  *
4321  * # similar to r = IO.popen(command)
4322  * r, w = IO.pipe
4323  * pid = spawn(command, :out=>w) # r, w is closed in the child process.
4324  * w.close
4325  *
4326  * :close is specified as a hash value to close a fd individually.
4327  *
4328  * f = open(foo)
4329  * system(command, f=>:close) # don't inherit f.
4330  *
4331  * If a file descriptor need to be inherited,
4332  * io=>io can be used.
4333  *
4334  * # valgrind has --log-fd option for log destination.
4335  * # log_w=>log_w indicates log_w.fileno inherits to child process.
4336  * log_r, log_w = IO.pipe
4337  * pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
4338  * log_w.close
4339  * p log_r.read
4340  *
4341  * It is also possible to exchange file descriptors.
4342  *
4343  * pid = spawn(command, :out=>:err, :err=>:out)
4344  *
4345  * The hash keys specify file descriptors in the child process.
4346  * The hash values specifies file descriptors in the parent process.
4347  * So the above specifies exchanging stdout and stderr.
4348  * Internally, +spawn+ uses an extra file descriptor to resolve such cyclic
4349  * file descriptor mapping.
4350  *
4351  * See <code>Kernel.exec</code> for the standard shell.
4352  */
4353 
4354 static VALUE
4355 rb_f_spawn(int argc, VALUE *argv)
4356 {
4357  rb_pid_t pid;
4358  char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
4359  VALUE execarg_obj, fail_str;
4360  struct rb_execarg *eargp;
4361 
4362  execarg_obj = rb_execarg_new(argc, argv, TRUE);
4363  eargp = rb_execarg_get(execarg_obj);
4364  fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
4365 
4366  pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));
4367 
4368  if (pid == -1) {
4369  int err = errno;
4370  rb_exec_fail(eargp, err, errmsg);
4371  RB_GC_GUARD(execarg_obj);
4372  rb_syserr_fail_str(err, fail_str);
4373  }
4374 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
4375  return PIDT2NUM(pid);
4376 #else
4377  return Qnil;
4378 #endif
4379 }
4380 
4381 /*
4382  * call-seq:
4383  * sleep([duration]) -> integer
4384  *
4385  * Suspends the current thread for _duration_ seconds (which may be any number,
4386  * including a +Float+ with fractional seconds). Returns the actual number of
4387  * seconds slept (rounded), which may be less than that asked for if another
4388  * thread calls <code>Thread#run</code>. Called without an argument, sleep()
4389  * will sleep forever.
4390  *
4391  * Time.new #=> 2008-03-08 19:56:19 +0900
4392  * sleep 1.2 #=> 1
4393  * Time.new #=> 2008-03-08 19:56:20 +0900
4394  * sleep 1.9 #=> 2
4395  * Time.new #=> 2008-03-08 19:56:22 +0900
4396  */
4397 
4398 static VALUE
4399 rb_f_sleep(int argc, VALUE *argv)
4400 {
4401  time_t beg, end;
4402 
4403  beg = time(0);
4404  if (argc == 0) {
4406  }
4407  else {
4408  rb_check_arity(argc, 0, 1);
4410  }
4411 
4412  end = time(0) - beg;
4413 
4414  return INT2FIX(end);
4415 }
4416 
4417 
4418 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
4419 /*
4420  * call-seq:
4421  * Process.getpgrp -> integer
4422  *
4423  * Returns the process group ID for this process. Not available on
4424  * all platforms.
4425  *
4426  * Process.getpgid(0) #=> 25527
4427  * Process.getpgrp #=> 25527
4428  */
4429 
4430 static VALUE
4431 proc_getpgrp(void)
4432 {
4433  rb_pid_t pgrp;
4434 
4435 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
4436  pgrp = getpgrp();
4437  if (pgrp < 0) rb_sys_fail(0);
4438  return PIDT2NUM(pgrp);
4439 #else /* defined(HAVE_GETPGID) */
4440  pgrp = getpgid(0);
4441  if (pgrp < 0) rb_sys_fail(0);
4442  return PIDT2NUM(pgrp);
4443 #endif
4444 }
4445 #else
4446 #define proc_getpgrp rb_f_notimplement
4447 #endif
4448 
4449 
4450 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
4451 /*
4452  * call-seq:
4453  * Process.setpgrp -> 0
4454  *
4455  * Equivalent to <code>setpgid(0,0)</code>. Not available on all
4456  * platforms.
4457  */
4458 
4459 static VALUE
4460 proc_setpgrp(void)
4461 {
4462  /* check for posix setpgid() first; this matches the posix */
4463  /* getpgrp() above. It appears that configure will set SETPGRP_VOID */
4464  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
4465  /* this confusion. */
4466 #ifdef HAVE_SETPGID
4467  if (setpgid(0,0) < 0) rb_sys_fail(0);
4468 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
4469  if (setpgrp() < 0) rb_sys_fail(0);
4470 #endif
4471  return INT2FIX(0);
4472 }
4473 #else
4474 #define proc_setpgrp rb_f_notimplement
4475 #endif
4476 
4477 
4478 #if defined(HAVE_GETPGID)
4479 /*
4480  * call-seq:
4481  * Process.getpgid(pid) -> integer
4482  *
4483  * Returns the process group ID for the given process id. Not
4484  * available on all platforms.
4485  *
4486  * Process.getpgid(Process.ppid()) #=> 25527
4487  */
4488 
4489 static VALUE
4490 proc_getpgid(VALUE obj, VALUE pid)
4491 {
4492  rb_pid_t i;
4493 
4494  i = getpgid(NUM2PIDT(pid));
4495  if (i < 0) rb_sys_fail(0);
4496  return PIDT2NUM(i);
4497 }
4498 #else
4499 #define proc_getpgid rb_f_notimplement
4500 #endif
4501 
4502 
4503 #ifdef HAVE_SETPGID
4504 /*
4505  * call-seq:
4506  * Process.setpgid(pid, integer) -> 0
4507  *
4508  * Sets the process group ID of _pid_ (0 indicates this
4509  * process) to <em>integer</em>. Not available on all platforms.
4510  */
4511 
4512 static VALUE
4513 proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
4514 {
4515  rb_pid_t ipid, ipgrp;
4516 
4517  ipid = NUM2PIDT(pid);
4518  ipgrp = NUM2PIDT(pgrp);
4519 
4520  if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
4521  return INT2FIX(0);
4522 }
4523 #else
4524 #define proc_setpgid rb_f_notimplement
4525 #endif
4526 
4527 
4528 #ifdef HAVE_GETSID
4529 /*
4530  * call-seq:
4531  * Process.getsid() -> integer
4532  * Process.getsid(pid) -> integer
4533  *
4534  * Returns the session ID for the given process id. If not given,
4535  * return current process sid. Not available on all platforms.
4536  *
4537  * Process.getsid() #=> 27422
4538  * Process.getsid(0) #=> 27422
4539  * Process.getsid(Process.pid()) #=> 27422
4540  */
4541 static VALUE
4542 proc_getsid(int argc, VALUE *argv)
4543 {
4544  rb_pid_t sid;
4545  rb_pid_t pid = 0;
4546 
4547  if (rb_check_arity(argc, 0, 1) == 1 && !NIL_P(argv[0]))
4548  pid = NUM2PIDT(argv[0]);
4549 
4550  sid = getsid(pid);
4551  if (sid < 0) rb_sys_fail(0);
4552  return PIDT2NUM(sid);
4553 }
4554 #else
4555 #define proc_getsid rb_f_notimplement
4556 #endif
4557 
4558 
4559 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
4560 #if !defined(HAVE_SETSID)
4561 static rb_pid_t ruby_setsid(void);
4562 #define setsid() ruby_setsid()
4563 #endif
4564 /*
4565  * call-seq:
4566  * Process.setsid -> integer
4567  *
4568  * Establishes this process as a new session and process group
4569  * leader, with no controlling tty. Returns the session id. Not
4570  * available on all platforms.
4571  *
4572  * Process.setsid #=> 27422
4573  */
4574 
4575 static VALUE
4576 proc_setsid(void)
4577 {
4578  rb_pid_t pid;
4579 
4580  pid = setsid();
4581  if (pid < 0) rb_sys_fail(0);
4582  return PIDT2NUM(pid);
4583 }
4584 
4585 #if !defined(HAVE_SETSID)
4586 #define HAVE_SETSID 1
4587 static rb_pid_t
4588 ruby_setsid(void)
4589 {
4590  rb_pid_t pid;
4591  int ret;
4592 
4593  pid = getpid();
4594 #if defined(SETPGRP_VOID)
4595  ret = setpgrp();
4596  /* If `pid_t setpgrp(void)' is equivalent to setsid(),
4597  `ret' will be the same value as `pid', and following open() will fail.
4598  In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
4599 #else
4600  ret = setpgrp(0, pid);
4601 #endif
4602  if (ret == -1) return -1;
4603 
4604  if ((fd = rb_cloexec_open("/dev/tty", O_RDWR, 0)) >= 0) {
4605  rb_update_max_fd(fd);
4606  ioctl(fd, TIOCNOTTY, NULL);
4607  close(fd);
4608  }
4609  return pid;
4610 }
4611 #endif
4612 #else
4613 #define proc_setsid rb_f_notimplement
4614 #endif
4615 
4616 
4617 #ifdef HAVE_GETPRIORITY
4618 /*
4619  * call-seq:
4620  * Process.getpriority(kind, integer) -> integer
4621  *
4622  * Gets the scheduling priority for specified process, process group,
4623  * or user. <em>kind</em> indicates the kind of entity to find: one
4624  * of <code>Process::PRIO_PGRP</code>,
4625  * <code>Process::PRIO_USER</code>, or
4626  * <code>Process::PRIO_PROCESS</code>. _integer_ is an id
4627  * indicating the particular process, process group, or user (an id
4628  * of 0 means _current_). Lower priorities are more favorable
4629  * for scheduling. Not available on all platforms.
4630  *
4631  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
4632  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
4633  */
4634 
4635 static VALUE
4636 proc_getpriority(VALUE obj, VALUE which, VALUE who)
4637 {
4638  int prio, iwhich, iwho;
4639 
4640  iwhich = NUM2INT(which);
4641  iwho = NUM2INT(who);
4642 
4643  errno = 0;
4644  prio = getpriority(iwhich, iwho);
4645  if (errno) rb_sys_fail(0);
4646  return INT2FIX(prio);
4647 }
4648 #else
4649 #define proc_getpriority rb_f_notimplement
4650 #endif
4651 
4652 
4653 #ifdef HAVE_GETPRIORITY
4654 /*
4655  * call-seq:
4656  * Process.setpriority(kind, integer, priority) -> 0
4657  *
4658  * See <code>Process#getpriority</code>.
4659  *
4660  * Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0
4661  * Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0
4662  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
4663  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
4664  */
4665 
4666 static VALUE
4667 proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
4668 {
4669  int iwhich, iwho, iprio;
4670 
4671  iwhich = NUM2INT(which);
4672  iwho = NUM2INT(who);
4673  iprio = NUM2INT(prio);
4674 
4675  if (setpriority(iwhich, iwho, iprio) < 0)
4676  rb_sys_fail(0);
4677  return INT2FIX(0);
4678 }
4679 #else
4680 #define proc_setpriority rb_f_notimplement
4681 #endif
4682 
4683 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
4684 static int
4685 rlimit_resource_name2int(const char *name, long len, int casetype)
4686 {
4687  int resource;
4688  const char *p;
4689 #define RESCHECK(r) \
4690  do { \
4691  if (len == rb_strlen_lit(#r) && STRCASECMP(name, #r) == 0) { \
4692  resource = RLIMIT_##r; \
4693  goto found; \
4694  } \
4695  } while (0)
4696 
4697  switch (TOUPPER(*name)) {
4698  case 'A':
4699 #ifdef RLIMIT_AS
4700  RESCHECK(AS);
4701 #endif
4702  break;
4703 
4704  case 'C':
4705 #ifdef RLIMIT_CORE
4706  RESCHECK(CORE);
4707 #endif
4708 #ifdef RLIMIT_CPU
4709  RESCHECK(CPU);
4710 #endif
4711  break;
4712 
4713  case 'D':
4714 #ifdef RLIMIT_DATA
4715  RESCHECK(DATA);
4716 #endif
4717  break;
4718 
4719  case 'F':
4720 #ifdef RLIMIT_FSIZE
4721  RESCHECK(FSIZE);
4722 #endif
4723  break;
4724 
4725  case 'M':
4726 #ifdef RLIMIT_MEMLOCK
4727  RESCHECK(MEMLOCK);
4728 #endif
4729 #ifdef RLIMIT_MSGQUEUE
4730  RESCHECK(MSGQUEUE);
4731 #endif
4732  break;
4733 
4734  case 'N':
4735 #ifdef RLIMIT_NOFILE
4736  RESCHECK(NOFILE);
4737 #endif
4738 #ifdef RLIMIT_NPROC
4739  RESCHECK(NPROC);
4740 #endif
4741 #ifdef RLIMIT_NICE
4742  RESCHECK(NICE);
4743 #endif
4744  break;
4745 
4746  case 'R':
4747 #ifdef RLIMIT_RSS
4748  RESCHECK(RSS);
4749 #endif
4750 #ifdef RLIMIT_RTPRIO
4751  RESCHECK(RTPRIO);
4752 #endif
4753 #ifdef RLIMIT_RTTIME
4754  RESCHECK(RTTIME);
4755 #endif
4756  break;
4757 
4758  case 'S':
4759 #ifdef RLIMIT_STACK
4760  RESCHECK(STACK);
4761 #endif
4762 #ifdef RLIMIT_SBSIZE
4763  RESCHECK(SBSIZE);
4764 #endif
4765 #ifdef RLIMIT_SIGPENDING
4766  RESCHECK(SIGPENDING);
4767 #endif
4768  break;
4769  }
4770  return -1;
4771 
4772  found:
4773  switch (casetype) {
4774  case 0:
4775  for (p = name; *p; p++)
4776  if (!ISUPPER(*p))
4777  return -1;
4778  break;
4779 
4780  case 1:
4781  for (p = name; *p; p++)
4782  if (!ISLOWER(*p))
4783  return -1;
4784  break;
4785 
4786  default:
4787  rb_bug("unexpected casetype");
4788  }
4789  return resource;
4790 #undef RESCHECK
4791 }
4792 
4793 static int
4794 rlimit_type_by_hname(const char *name, long len)
4795 {
4796  return rlimit_resource_name2int(name, len, 0);
4797 }
4798 
4799 static int
4800 rlimit_type_by_lname(const char *name, long len)
4801 {
4802  return rlimit_resource_name2int(name, len, 1);
4803 }
4804 
4805 static int
4806 rlimit_type_by_sym(VALUE key)
4807 {
4808  VALUE name = rb_sym2str(key);
4809  const char *rname = RSTRING_PTR(name);
4810  long len = RSTRING_LEN(name);
4811  int rtype = -1;
4812  static const char prefix[] = "rlimit_";
4813  enum {prefix_len = sizeof(prefix)-1};
4814 
4815  if (len > prefix_len && strncmp(prefix, rname, prefix_len) == 0) {
4816  rtype = rlimit_type_by_lname(rname + prefix_len, len - prefix_len);
4817  }
4818 
4819  RB_GC_GUARD(key);
4820  return rtype;
4821 }
4822 
4823 static int
4824 rlimit_resource_type(VALUE rtype)
4825 {
4826  const char *name;
4827  long len;
4828  VALUE v;
4829  int r;
4830 
4831  switch (TYPE(rtype)) {
4832  case T_SYMBOL:
4833  v = rb_sym2str(rtype);
4834  name = RSTRING_PTR(v);
4835  len = RSTRING_LEN(v);
4836  break;
4837 
4838  default:
4839  v = rb_check_string_type(rtype);
4840  if (!NIL_P(v)) {
4841  rtype = v;
4842  case T_STRING:
4843  name = StringValueCStr(rtype);
4844  len = RSTRING_LEN(rtype);
4845  break;
4846  }
4847  /* fall through */
4848 
4849  case T_FIXNUM:
4850  case T_BIGNUM:
4851  return NUM2INT(rtype);
4852  }
4853 
4854  r = rlimit_type_by_hname(name, len);
4855  if (r != -1)
4856  return r;
4857 
4858  rb_raise(rb_eArgError, "invalid resource name: % "PRIsVALUE, rtype);
4859 
4860  UNREACHABLE;
4861 }
4862 
4863 static rlim_t
4864 rlimit_resource_value(VALUE rval)
4865 {
4866  const char *name;
4867  VALUE v;
4868 
4869  switch (TYPE(rval)) {
4870  case T_SYMBOL:
4871  v = rb_sym2str(rval);
4872  name = RSTRING_PTR(v);
4873  break;
4874 
4875  default:
4876  v = rb_check_string_type(rval);
4877  if (!NIL_P(v)) {
4878  rval = v;
4879  case T_STRING:
4880  name = StringValueCStr(rval);
4881  break;
4882  }
4883  /* fall through */
4884 
4885  case T_FIXNUM:
4886  case T_BIGNUM:
4887  return NUM2RLIM(rval);
4888  }
4889 
4890 #ifdef RLIM_INFINITY
4891  if (strcmp(name, "INFINITY") == 0) return RLIM_INFINITY;
4892 #endif
4893 #ifdef RLIM_SAVED_MAX
4894  if (strcmp(name, "SAVED_MAX") == 0) return RLIM_SAVED_MAX;
4895 #endif
4896 #ifdef RLIM_SAVED_CUR
4897  if (strcmp(name, "SAVED_CUR") == 0) return RLIM_SAVED_CUR;
4898 #endif
4899  rb_raise(rb_eArgError, "invalid resource value: %"PRIsVALUE, rval);
4900 
4901  UNREACHABLE;
4902 }
4903 #endif
4904 
4905 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
4906 /*
4907  * call-seq:
4908  * Process.getrlimit(resource) -> [cur_limit, max_limit]
4909  *
4910  * Gets the resource limit of the process.
4911  * _cur_limit_ means current (soft) limit and
4912  * _max_limit_ means maximum (hard) limit.
4913  *
4914  * _resource_ indicates the kind of resource to limit.
4915  * It is specified as a symbol such as <code>:CORE</code>,
4916  * a string such as <code>"CORE"</code> or
4917  * a constant such as <code>Process::RLIMIT_CORE</code>.
4918  * See Process.setrlimit for details.
4919  *
4920  * _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
4921  * <code>Process::RLIM_SAVED_MAX</code> or
4922  * <code>Process::RLIM_SAVED_CUR</code>.
4923  * See Process.setrlimit and the system getrlimit(2) manual for details.
4924  */
4925 
4926 static VALUE
4927 proc_getrlimit(VALUE obj, VALUE resource)
4928 {
4929  struct rlimit rlim;
4930 
4931  if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4932  rb_sys_fail("getrlimit");
4933  }
4934  return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
4935 }
4936 #else
4937 #define proc_getrlimit rb_f_notimplement
4938 #endif
4939 
4940 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
4941 /*
4942  * call-seq:
4943  * Process.setrlimit(resource, cur_limit, max_limit) -> nil
4944  * Process.setrlimit(resource, cur_limit) -> nil
4945  *
4946  * Sets the resource limit of the process.
4947  * _cur_limit_ means current (soft) limit and
4948  * _max_limit_ means maximum (hard) limit.
4949  *
4950  * If _max_limit_ is not given, _cur_limit_ is used.
4951  *
4952  * _resource_ indicates the kind of resource to limit.
4953  * It should be a symbol such as <code>:CORE</code>,
4954  * a string such as <code>"CORE"</code> or
4955  * a constant such as <code>Process::RLIMIT_CORE</code>.
4956  * The available resources are OS dependent.
4957  * Ruby may support following resources.
4958  *
4959  * [AS] total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)
4960  * [CORE] core size (bytes) (SUSv3)
4961  * [CPU] CPU time (seconds) (SUSv3)
4962  * [DATA] data segment (bytes) (SUSv3)
4963  * [FSIZE] file size (bytes) (SUSv3)
4964  * [MEMLOCK] total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)
4965  * [MSGQUEUE] allocation for POSIX message queues (bytes) (GNU/Linux)
4966  * [NICE] ceiling on process's nice(2) value (number) (GNU/Linux)
4967  * [NOFILE] file descriptors (number) (SUSv3)
4968  * [NPROC] number of processes for the user (number) (4.4BSD, GNU/Linux)
4969  * [RSS] resident memory size (bytes) (4.2BSD, GNU/Linux)
4970  * [RTPRIO] ceiling on the process's real-time priority (number) (GNU/Linux)
4971  * [RTTIME] CPU time for real-time process (us) (GNU/Linux)
4972  * [SBSIZE] all socket buffers (bytes) (NetBSD, FreeBSD)
4973  * [SIGPENDING] number of queued signals allowed (signals) (GNU/Linux)
4974  * [STACK] stack size (bytes) (SUSv3)
4975  *
4976  * _cur_limit_ and _max_limit_ may be
4977  * <code>:INFINITY</code>, <code>"INFINITY"</code> or
4978  * <code>Process::RLIM_INFINITY</code>,
4979  * which means that the resource is not limited.
4980  * They may be <code>Process::RLIM_SAVED_MAX</code>,
4981  * <code>Process::RLIM_SAVED_CUR</code> and
4982  * corresponding symbols and strings too.
4983  * See system setrlimit(2) manual for details.
4984  *
4985  * The following example raises the soft limit of core size to
4986  * the hard limit to try to make core dump possible.
4987  *
4988  * Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
4989  *
4990  */
4991 
4992 static VALUE
4993 proc_setrlimit(int argc, VALUE *argv, VALUE obj)
4994 {
4995  VALUE resource, rlim_cur, rlim_max;
4996  struct rlimit rlim;
4997 
4998  rb_check_arity(argc, 2, 3);
4999  resource = argv[0];
5000  rlim_cur = argv[1];
5001  if (argc < 3 || NIL_P(rlim_max = argv[2]))
5002  rlim_max = rlim_cur;
5003 
5004  rlim.rlim_cur = rlimit_resource_value(rlim_cur);
5005  rlim.rlim_max = rlimit_resource_value(rlim_max);
5006 
5007  if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
5008  rb_sys_fail("setrlimit");
5009  }
5010  return Qnil;
5011 }
5012 #else
5013 #define proc_setrlimit rb_f_notimplement
5014 #endif
5015 
5016 static int under_uid_switch = 0;
5017 static void
5018 check_uid_switch(void)
5019 {
5020  if (under_uid_switch) {
5021  rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
5022  }
5023 }
5024 
5025 static int under_gid_switch = 0;
5026 static void
5027 check_gid_switch(void)
5028 {
5029  if (under_gid_switch) {
5030  rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
5031  }
5032 }
5033 
5034 
5035 /*********************************************************************
5036  * Document-class: Process::Sys
5037  *
5038  * The <code>Process::Sys</code> module contains UID and GID
5039  * functions which provide direct bindings to the system calls of the
5040  * same names instead of the more-portable versions of the same
5041  * functionality found in the <code>Process</code>,
5042  * <code>Process::UID</code>, and <code>Process::GID</code> modules.
5043  */
5044 
5045 #if defined(HAVE_PWD_H)
5046 static rb_uid_t
5047 obj2uid(VALUE id
5048 # ifdef USE_GETPWNAM_R
5049  , VALUE *getpw_tmp
5050 # endif
5051  )
5052 {
5053  rb_uid_t uid;
5054  VALUE tmp;
5055 
5056  if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
5057  uid = NUM2UIDT(id);
5058  }
5059  else {
5060  const char *usrname = StringValueCStr(id);
5061  struct passwd *pwptr;
5062 #ifdef USE_GETPWNAM_R
5063  struct passwd pwbuf;
5064  char *getpw_buf;
5065  long getpw_buf_len;
5066  int e;
5067  if (!*getpw_tmp) {
5068  getpw_buf_len = GETPW_R_SIZE_INIT;
5069  if (getpw_buf_len < 0) getpw_buf_len = GETPW_R_SIZE_DEFAULT;
5070  *getpw_tmp = rb_str_tmp_new(getpw_buf_len);
5071  }
5072  getpw_buf = RSTRING_PTR(*getpw_tmp);
5073  getpw_buf_len = rb_str_capacity(*getpw_tmp);
5074  rb_str_set_len(*getpw_tmp, getpw_buf_len);
5075  errno = 0;
5076  while ((e = getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) != 0) {
5077  if (e != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) {
5078  rb_str_resize(*getpw_tmp, 0);
5079  rb_syserr_fail(e, "getpwnam_r");
5080  }
5081  rb_str_modify_expand(*getpw_tmp, getpw_buf_len);
5082  getpw_buf = RSTRING_PTR(*getpw_tmp);
5083  getpw_buf_len = rb_str_capacity(*getpw_tmp);
5084  }
5085 #else
5086  pwptr = getpwnam(usrname);
5087 #endif
5088  if (!pwptr) {
5089 #ifndef USE_GETPWNAM_R
5090  endpwent();
5091 #endif
5092  rb_raise(rb_eArgError, "can't find user for %s", usrname);
5093  }
5094  uid = pwptr->pw_uid;
5095 #ifndef USE_GETPWNAM_R
5096  endpwent();
5097 #endif
5098  }
5099  return uid;
5100 }
5101 
5102 # ifdef p_uid_from_name
5103 /*
5104  * call-seq:
5105  * Process::UID.from_name(name) -> uid
5106  *
5107  * Get the user ID by the _name_.
5108  * If the user is not found, +ArgumentError+ will be raised.
5109  *
5110  * Process::UID.from_name("root") #=> 0
5111  * Process::UID.from_name("nosuchuser") #=> can't find user for nosuchuser (ArgumentError)
5112  */
5113 
5114 static VALUE
5115 p_uid_from_name(VALUE self, VALUE id)
5116 {
5117  return UIDT2NUM(OBJ2UID(id));
5118 }
5119 # endif
5120 #endif
5121 
5122 #if defined(HAVE_GRP_H)
5123 static rb_gid_t
5124 obj2gid(VALUE id
5125 # ifdef USE_GETGRNAM_R
5126  , VALUE *getgr_tmp
5127 # endif
5128  )
5129 {
5130  rb_gid_t gid;
5131  VALUE tmp;
5132 
5133  if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
5134  gid = NUM2GIDT(id);
5135  }
5136  else {
5137  const char *grpname = StringValueCStr(id);
5138  struct group *grptr;
5139 #ifdef USE_GETGRNAM_R
5140  struct group grbuf;
5141  char *getgr_buf;
5142  long getgr_buf_len;
5143  int e;
5144  if (!*getgr_tmp) {
5145  getgr_buf_len = GETGR_R_SIZE_INIT;
5146  if (getgr_buf_len < 0) getgr_buf_len = GETGR_R_SIZE_DEFAULT;
5147  *getgr_tmp = rb_str_tmp_new(getgr_buf_len);
5148  }
5149  getgr_buf = RSTRING_PTR(*getgr_tmp);
5150  getgr_buf_len = rb_str_capacity(*getgr_tmp);
5151  rb_str_set_len(*getgr_tmp, getgr_buf_len);
5152  errno = 0;
5153  while ((e = getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) != 0) {
5154  if (e != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) {
5155  rb_str_resize(*getgr_tmp, 0);
5156  rb_syserr_fail(e, "getgrnam_r");
5157  }
5158  rb_str_modify_expand(*getgr_tmp, getgr_buf_len);
5159  getgr_buf = RSTRING_PTR(*getgr_tmp);
5160  getgr_buf_len = rb_str_capacity(*getgr_tmp);
5161  }
5162 #elif defined(HAVE_GETGRNAM)
5163  grptr = getgrnam(grpname);
5164 #else
5165  grptr = NULL;
5166 #endif
5167  if (!grptr) {
5168 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
5169  endgrent();
5170 #endif
5171  rb_raise(rb_eArgError, "can't find group for %s", grpname);
5172  }
5173  gid = grptr->gr_gid;
5174 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
5175  endgrent();
5176 #endif
5177  }
5178  return gid;
5179 }
5180 
5181 # ifdef p_gid_from_name
5182 /*
5183  * call-seq:
5184  * Process::GID.from_name(name) -> gid
5185  *
5186  * Get the group ID by the _name_.
5187  * If the group is not found, +ArgumentError+ will be raised.
5188  *
5189  * Process::GID.from_name("wheel") #=> 0
5190  * Process::GID.from_name("nosuchgroup") #=> can't find group for nosuchgroup (ArgumentError)
5191  */
5192 
5193 static VALUE
5194 p_gid_from_name(VALUE self, VALUE id)
5195 {
5196  return GIDT2NUM(OBJ2GID(id));
5197 }
5198 # endif
5199 #endif
5200 
5201 #if defined HAVE_SETUID
5202 /*
5203  * call-seq:
5204  * Process::Sys.setuid(user) -> nil
5205  *
5206  * Set the user ID of the current process to _user_. Not
5207  * available on all platforms.
5208  *
5209  */
5210 
5211 static VALUE
5212 p_sys_setuid(VALUE obj, VALUE id)
5213 {
5214  check_uid_switch();
5215  if (setuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
5216  return Qnil;
5217 }
5218 #else
5219 #define p_sys_setuid rb_f_notimplement
5220 #endif
5221 
5222 
5223 #if defined HAVE_SETRUID
5224 /*
5225  * call-seq:
5226  * Process::Sys.setruid(user) -> nil
5227  *
5228  * Set the real user ID of the calling process to _user_.
5229  * Not available on all platforms.
5230  *
5231  */
5232 
5233 static VALUE
5234 p_sys_setruid(VALUE obj, VALUE id)
5235 {
5236  check_uid_switch();
5237  if (setruid(OBJ2UID(id)) != 0) rb_sys_fail(0);
5238  return Qnil;
5239 }
5240 #else
5241 #define p_sys_setruid rb_f_notimplement
5242 #endif
5243 
5244 
5245 #if defined HAVE_SETEUID
5246 /*
5247  * call-seq:
5248  * Process::Sys.seteuid(user) -> nil
5249  *
5250  * Set the effective user ID of the calling process to
5251  * _user_. Not available on all platforms.
5252  *
5253  */
5254 
5255 static VALUE
5256 p_sys_seteuid(VALUE obj, VALUE id)
5257 {
5258  check_uid_switch();
5259  if (seteuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
5260  return Qnil;
5261 }
5262 #else
5263 #define p_sys_seteuid rb_f_notimplement
5264 #endif
5265 
5266 
5267 #if defined HAVE_SETREUID
5268 /*
5269  * call-seq:
5270  * Process::Sys.setreuid(rid, eid) -> nil
5271  *
5272  * Sets the (user) real and/or effective user IDs of the current
5273  * process to _rid_ and _eid_, respectively. A value of
5274  * <code>-1</code> for either means to leave that ID unchanged. Not
5275  * available on all platforms.
5276  *
5277  */
5278 
5279 static VALUE
5280 p_sys_setreuid(VALUE obj, VALUE rid, VALUE eid)
5281 {
5282  rb_uid_t ruid, euid;
5284  check_uid_switch();
5285  ruid = OBJ2UID1(rid);
5286  euid = OBJ2UID1(eid);
5288  if (setreuid(ruid, euid) != 0) rb_sys_fail(0);
5289  return Qnil;
5290 }
5291 #else
5292 #define p_sys_setreuid rb_f_notimplement
5293 #endif
5294 
5295 
5296 #if defined HAVE_SETRESUID
5297 /*
5298  * call-seq:
5299  * Process::Sys.setresuid(rid, eid, sid) -> nil
5300  *
5301  * Sets the (user) real, effective, and saved user IDs of the
5302  * current process to _rid_, _eid_, and _sid_ respectively. A
5303  * value of <code>-1</code> for any value means to
5304  * leave that ID unchanged. Not available on all platforms.
5305  *
5306  */
5307 
5308 static VALUE
5309 p_sys_setresuid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
5310 {
5311  rb_uid_t ruid, euid, suid;
5313  check_uid_switch();
5314  ruid = OBJ2UID1(rid);
5315  euid = OBJ2UID1(eid);
5316  suid = OBJ2UID1(sid);
5318  if (setresuid(ruid, euid, suid) != 0) rb_sys_fail(0);
5319  return Qnil;
5320 }
5321 #else
5322 #define p_sys_setresuid rb_f_notimplement
5323 #endif
5324 
5325 
5326 /*
5327  * call-seq:
5328  * Process.uid -> integer
5329  * Process::UID.rid -> integer
5330  * Process::Sys.getuid -> integer
5331  *
5332  * Returns the (real) user ID of this process.
5333  *
5334  * Process.uid #=> 501
5335  */
5336 
5337 static VALUE
5338 proc_getuid(VALUE obj)
5339 {
5340  rb_uid_t uid = getuid();
5341  return UIDT2NUM(uid);
5342 }
5343 
5344 
5345 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
5346 /*
5347  * call-seq:
5348  * Process.uid= user -> numeric
5349  *
5350  * Sets the (user) user ID for this process. Not available on all
5351  * platforms.
5352  */
5353 
5354 static VALUE
5355 proc_setuid(VALUE obj, VALUE id)
5356 {
5357  rb_uid_t uid;
5358 
5359  check_uid_switch();
5360 
5361  uid = OBJ2UID(id);
5362 #if defined(HAVE_SETRESUID)
5363  if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
5364 #elif defined HAVE_SETREUID
5365  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
5366 #elif defined HAVE_SETRUID
5367  if (setruid(uid) < 0) rb_sys_fail(0);
5368 #elif defined HAVE_SETUID
5369  {
5370  if (geteuid() == uid) {
5371  if (setuid(uid) < 0) rb_sys_fail(0);
5372  }
5373  else {
5374  rb_notimplement();
5375  }
5376  }
5377 #endif
5378  return id;
5379 }
5380 #else
5381 #define proc_setuid rb_f_notimplement
5382 #endif
5383 
5384 
5385 /********************************************************************
5386  *
5387  * Document-class: Process::UID
5388  *
5389  * The <code>Process::UID</code> module contains a collection of
5390  * module functions which can be used to portably get, set, and
5391  * switch the current process's real, effective, and saved user IDs.
5392  *
5393  */
5394 
5395 static rb_uid_t SAVED_USER_ID = -1;
5396 
5397 #ifdef BROKEN_SETREUID
5398 int
5399 setreuid(rb_uid_t ruid, rb_uid_t euid)
5400 {
5401  if (ruid != (rb_uid_t)-1 && ruid != getuid()) {
5402  if (euid == (rb_uid_t)-1) euid = geteuid();
5403  if (setuid(ruid) < 0) return -1;
5404  }
5405  if (euid != (rb_uid_t)-1 && euid != geteuid()) {
5406  if (seteuid(euid) < 0) return -1;
5407  }
5408  return 0;
5409 }
5410 #endif
5411 
5412 /*
5413  * call-seq:
5414  * Process::UID.change_privilege(user) -> integer
5415  *
5416  * Change the current process's real and effective user ID to that
5417  * specified by _user_. Returns the new user ID. Not
5418  * available on all platforms.
5419  *
5420  * [Process.uid, Process.euid] #=> [0, 0]
5421  * Process::UID.change_privilege(31) #=> 31
5422  * [Process.uid, Process.euid] #=> [31, 31]
5423  */
5424 
5425 static VALUE
5426 p_uid_change_privilege(VALUE obj, VALUE id)
5427 {
5428  rb_uid_t uid;
5429 
5430  check_uid_switch();
5431 
5432  uid = OBJ2UID(id);
5433 
5434  if (geteuid() == 0) { /* root-user */
5435 #if defined(HAVE_SETRESUID)
5436  if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
5437  SAVED_USER_ID = uid;
5438 #elif defined(HAVE_SETUID)
5439  if (setuid(uid) < 0) rb_sys_fail(0);
5440  SAVED_USER_ID = uid;
5441 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5442  if (getuid() == uid) {
5443  if (SAVED_USER_ID == uid) {
5444  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
5445  }
5446  else {
5447  if (uid == 0) { /* (r,e,s) == (root, root, x) */
5448  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
5449  if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
5450  SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
5451  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
5452  SAVED_USER_ID = uid;
5453  }
5454  else {
5455  if (setreuid(0, -1) < 0) rb_sys_fail(0);
5456  SAVED_USER_ID = 0;
5457  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
5458  SAVED_USER_ID = uid;
5459  }
5460  }
5461  }
5462  else {
5463  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
5464  SAVED_USER_ID = uid;
5465  }
5466 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
5467  if (getuid() == uid) {
5468  if (SAVED_USER_ID == uid) {
5469  if (seteuid(uid) < 0) rb_sys_fail(0);
5470  }
5471  else {
5472  if (uid == 0) {
5473  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
5474  SAVED_USER_ID = 0;
5475  if (setruid(0) < 0) rb_sys_fail(0);
5476  }
5477  else {
5478  if (setruid(0) < 0) rb_sys_fail(0);
5479  SAVED_USER_ID = 0;
5480  if (seteuid(uid) < 0) rb_sys_fail(0);
5481  if (setruid(uid) < 0) rb_sys_fail(0);
5482  SAVED_USER_ID = uid;
5483  }
5484  }
5485  }
5486  else {
5487  if (seteuid(uid) < 0) rb_sys_fail(0);
5488  if (setruid(uid) < 0) rb_sys_fail(0);
5489  SAVED_USER_ID = uid;
5490  }
5491 #else
5492  (void)uid;
5493  rb_notimplement();
5494 #endif
5495  }
5496  else { /* unprivileged user */
5497 #if defined(HAVE_SETRESUID)
5498  if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
5499  (geteuid() == uid)? (rb_uid_t)-1: uid,
5500  (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
5501  SAVED_USER_ID = uid;
5502 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5503  if (SAVED_USER_ID == uid) {
5504  if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
5505  (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5506  rb_sys_fail(0);
5507  }
5508  else if (getuid() != uid) {
5509  if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5510  rb_sys_fail(0);
5511  SAVED_USER_ID = uid;
5512  }
5513  else if (/* getuid() == uid && */ geteuid() != uid) {
5514  if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
5515  SAVED_USER_ID = uid;
5516  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
5517  }
5518  else { /* getuid() == uid && geteuid() == uid */
5519  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
5520  if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
5521  SAVED_USER_ID = uid;
5522  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
5523  }
5524 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
5525  if (SAVED_USER_ID == uid) {
5526  if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
5527  if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
5528  }
5529  else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
5530  if (getuid() != uid) {
5531  if (setruid(uid) < 0) rb_sys_fail(0);
5532  SAVED_USER_ID = uid;
5533  }
5534  else {
5535  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
5536  SAVED_USER_ID = uid;
5537  if (setruid(uid) < 0) rb_sys_fail(0);
5538  }
5539  }
5540  else if (/* geteuid() != uid && */ getuid() == uid) {
5541  if (seteuid(uid) < 0) rb_sys_fail(0);
5542  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
5543  SAVED_USER_ID = uid;
5544  if (setruid(uid) < 0) rb_sys_fail(0);
5545  }
5546  else {
5547  rb_syserr_fail(EPERM, 0);
5548  }
5549 #elif defined HAVE_44BSD_SETUID
5550  if (getuid() == uid) {
5551  /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
5552  if (setuid(uid) < 0) rb_sys_fail(0);
5553  SAVED_USER_ID = uid;
5554  }
5555  else {
5556  rb_syserr_fail(EPERM, 0);
5557  }
5558 #elif defined HAVE_SETEUID
5559  if (getuid() == uid && SAVED_USER_ID == uid) {
5560  if (seteuid(uid) < 0) rb_sys_fail(0);
5561  }
5562  else {
5563  rb_syserr_fail(EPERM, 0);
5564  }
5565 #elif defined HAVE_SETUID
5566  if (getuid() == uid && SAVED_USER_ID == uid) {
5567  if (setuid(uid) < 0) rb_sys_fail(0);
5568  }
5569  else {
5570  rb_syserr_fail(EPERM, 0);
5571  }
5572 #else
5573  rb_notimplement();
5574 #endif
5575  }
5576  return id;
5577 }
5578 
5579 
5580 
5581 #if defined HAVE_SETGID
5582 /*
5583  * call-seq:
5584  * Process::Sys.setgid(group) -> nil
5585  *
5586  * Set the group ID of the current process to _group_. Not
5587  * available on all platforms.
5588  *
5589  */
5590 
5591 static VALUE
5592 p_sys_setgid(VALUE obj, VALUE id)
5593 {
5594  check_gid_switch();
5595  if (setgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
5596  return Qnil;
5597 }
5598 #else
5599 #define p_sys_setgid rb_f_notimplement
5600 #endif
5601 
5602 
5603 #if defined HAVE_SETRGID
5604 /*
5605  * call-seq:
5606  * Process::Sys.setrgid(group) -> nil
5607  *
5608  * Set the real group ID of the calling process to _group_.
5609  * Not available on all platforms.
5610  *
5611  */
5612 
5613 static VALUE
5614 p_sys_setrgid(VALUE obj, VALUE id)
5615 {
5616  check_gid_switch();
5617  if (setrgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
5618  return Qnil;
5619 }
5620 #else
5621 #define p_sys_setrgid rb_f_notimplement
5622 #endif
5623 
5624 
5625 #if defined HAVE_SETEGID
5626 /*
5627  * call-seq:
5628  * Process::Sys.setegid(group) -> nil
5629  *
5630  * Set the effective group ID of the calling process to
5631  * _group_. Not available on all platforms.
5632  *
5633  */
5634 
5635 static VALUE
5636 p_sys_setegid(VALUE obj, VALUE id)
5637 {
5638  check_gid_switch();
5639  if (setegid(OBJ2GID(id)) != 0) rb_sys_fail(0);
5640  return Qnil;
5641 }
5642 #else
5643 #define p_sys_setegid rb_f_notimplement
5644 #endif
5645 
5646 
5647 #if defined HAVE_SETREGID
5648 /*
5649  * call-seq:
5650  * Process::Sys.setregid(rid, eid) -> nil
5651  *
5652  * Sets the (group) real and/or effective group IDs of the current
5653  * process to <em>rid</em> and <em>eid</em>, respectively. A value of
5654  * <code>-1</code> for either means to leave that ID unchanged. Not
5655  * available on all platforms.
5656  *
5657  */
5658 
5659 static VALUE
5660 p_sys_setregid(VALUE obj, VALUE rid, VALUE eid)
5661 {
5662  rb_gid_t rgid, egid;
5664  check_gid_switch();
5665  rgid = OBJ2GID(rid);
5666  egid = OBJ2GID(eid);
5668  if (setregid(rgid, egid) != 0) rb_sys_fail(0);
5669  return Qnil;
5670 }
5671 #else
5672 #define p_sys_setregid rb_f_notimplement
5673 #endif
5674 
5675 #if defined HAVE_SETRESGID
5676 /*
5677  * call-seq:
5678  * Process::Sys.setresgid(rid, eid, sid) -> nil
5679  *
5680  * Sets the (group) real, effective, and saved user IDs of the
5681  * current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
5682  * respectively. A value of <code>-1</code> for any value means to
5683  * leave that ID unchanged. Not available on all platforms.
5684  *
5685  */
5686 
5687 static VALUE
5688 p_sys_setresgid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
5689 {
5690  rb_gid_t rgid, egid, sgid;
5692  check_gid_switch();
5693  rgid = OBJ2GID(rid);
5694  egid = OBJ2GID(eid);
5695  sgid = OBJ2GID(sid);
5697  if (setresgid(rgid, egid, sgid) != 0) rb_sys_fail(0);
5698  return Qnil;
5699 }
5700 #else
5701 #define p_sys_setresgid rb_f_notimplement
5702 #endif
5703 
5704 
5705 #if defined HAVE_ISSETUGID
5706 /*
5707  * call-seq:
5708  * Process::Sys.issetugid -> true or false
5709  *
5710  * Returns +true+ if the process was created as a result
5711  * of an execve(2) system call which had either of the setuid or
5712  * setgid bits set (and extra privileges were given as a result) or
5713  * if it has changed any of its real, effective or saved user or
5714  * group IDs since it began execution.
5715  *
5716  */
5717 
5718 static VALUE
5720 {
5721  if (issetugid()) {
5722  return Qtrue;
5723  }
5724  else {
5725  return Qfalse;
5726  }
5727 }
5728 #else
5729 #define p_sys_issetugid rb_f_notimplement
5730 #endif
5731 
5732 
5733 /*
5734  * call-seq:
5735  * Process.gid -> integer
5736  * Process::GID.rid -> integer
5737  * Process::Sys.getgid -> integer
5738  *
5739  * Returns the (real) group ID for this process.
5740  *
5741  * Process.gid #=> 500
5742  */
5743 
5744 static VALUE
5745 proc_getgid(VALUE obj)
5746 {
5747  rb_gid_t gid = getgid();
5748  return GIDT2NUM(gid);
5749 }
5750 
5751 
5752 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
5753 /*
5754  * call-seq:
5755  * Process.gid= integer -> integer
5756  *
5757  * Sets the group ID for this process.
5758  */
5759 
5760 static VALUE
5761 proc_setgid(VALUE obj, VALUE id)
5762 {
5763  rb_gid_t gid;
5764 
5765  check_gid_switch();
5766 
5767  gid = OBJ2GID(id);
5768 #if defined(HAVE_SETRESGID)
5769  if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
5770 #elif defined HAVE_SETREGID
5771  if (setregid(gid, -1) < 0) rb_sys_fail(0);
5772 #elif defined HAVE_SETRGID
5773  if (setrgid(gid) < 0) rb_sys_fail(0);
5774 #elif defined HAVE_SETGID
5775  {
5776  if (getegid() == gid) {
5777  if (setgid(gid) < 0) rb_sys_fail(0);
5778  }
5779  else {
5780  rb_notimplement();
5781  }
5782  }
5783 #endif
5784  return GIDT2NUM(gid);
5785 }
5786 #else
5787 #define proc_setgid rb_f_notimplement
5788 #endif
5789 
5790 
5791 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
5792 /*
5793  * Maximum supplementary groups are platform dependent.
5794  * FWIW, 65536 is enough big for our supported OSs.
5795  *
5796  * OS Name max groups
5797  * -----------------------------------------------
5798  * Linux Kernel >= 2.6.3 65536
5799  * Linux Kernel < 2.6.3 32
5800  * IBM AIX 5.2 64
5801  * IBM AIX 5.3 ... 6.1 128
5802  * IBM AIX 7.1 128 (can be configured to be up to 2048)
5803  * OpenBSD, NetBSD 16
5804  * FreeBSD < 8.0 16
5805  * FreeBSD >=8.0 1023
5806  * Darwin (Mac OS X) 16
5807  * Sun Solaris 7,8,9,10 16
5808  * Sun Solaris 11 / OpenSolaris 1024
5809  * HP-UX 20
5810  * Windows 1015
5811  */
5812 static int _maxgroups = -1;
5813 static int
5814 get_sc_ngroups_max(void)
5815 {
5816 #ifdef _SC_NGROUPS_MAX
5817  return (int)sysconf(_SC_NGROUPS_MAX);
5818 #elif defined(NGROUPS_MAX)
5819  return (int)NGROUPS_MAX;
5820 #else
5821  return -1;
5822 #endif
5823 }
5824 static int
5825 maxgroups(void)
5826 {
5827  if (_maxgroups < 0) {
5828  _maxgroups = get_sc_ngroups_max();
5829  if (_maxgroups < 0)
5830  _maxgroups = RB_MAX_GROUPS;
5831  }
5832 
5833  return _maxgroups;
5834 }
5835 #endif
5836 
5837 
5838 
5839 #ifdef HAVE_GETGROUPS
5840 /*
5841  * call-seq:
5842  * Process.groups -> array
5843  *
5844  * Get an <code>Array</code> of the gids of groups in the
5845  * supplemental group access list for this process.
5846  *
5847  * Process.groups #=> [27, 6, 10, 11]
5848  *
5849  */
5850 
5851 static VALUE
5852 proc_getgroups(VALUE obj)
5853 {
5854  VALUE ary, tmp;
5855  int i, ngroups;
5856  rb_gid_t *groups;
5857 
5858  ngroups = getgroups(0, NULL);
5859  if (ngroups == -1)
5860  rb_sys_fail(0);
5861 
5862  groups = ALLOCV_N(rb_gid_t, tmp, ngroups);
5863 
5864  ngroups = getgroups(ngroups, groups);
5865  if (ngroups == -1)
5866  rb_sys_fail(0);
5867 
5868  ary = rb_ary_new();
5869  for (i = 0; i < ngroups; i++)
5870  rb_ary_push(ary, GIDT2NUM(groups[i]));
5871 
5872  ALLOCV_END(tmp);
5873 
5874  return ary;
5875 }
5876 #else
5877 #define proc_getgroups rb_f_notimplement
5878 #endif
5879 
5880 
5881 #ifdef HAVE_SETGROUPS
5882 /*
5883  * call-seq:
5884  * Process.groups= array -> array
5885  *
5886  * Set the supplemental group access list to the given
5887  * <code>Array</code> of group IDs.
5888  *
5889  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
5890  * Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11]
5891  * Process.groups #=> [27, 6, 10, 11]
5892  *
5893  */
5894 
5895 static VALUE
5896 proc_setgroups(VALUE obj, VALUE ary)
5897 {
5898  int ngroups, i;
5899  rb_gid_t *groups;
5900  VALUE tmp;
5902 
5903  Check_Type(ary, T_ARRAY);
5904 
5905  ngroups = RARRAY_LENINT(ary);
5906  if (ngroups > maxgroups())
5907  rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());
5908 
5909  groups = ALLOCV_N(rb_gid_t, tmp, ngroups);
5910 
5911  for (i = 0; i < ngroups; i++) {
5912  VALUE g = RARRAY_AREF(ary, i);
5913 
5914  groups[i] = OBJ2GID1(g);
5915  }
5917 
5918  if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
5919  rb_sys_fail(0);
5920 
5921  ALLOCV_END(tmp);
5922 
5923  return proc_getgroups(obj);
5924 }
5925 #else
5926 #define proc_setgroups rb_f_notimplement
5927 #endif
5928 
5929 
5930 #ifdef HAVE_INITGROUPS
5931 /*
5932  * call-seq:
5933  * Process.initgroups(username, gid) -> array
5934  *
5935  * Initializes the supplemental group access list by reading the
5936  * system group database and using all groups of which the given user
5937  * is a member. The group with the specified <em>gid</em> is also
5938  * added to the list. Returns the resulting <code>Array</code> of the
5939  * gids of all the groups in the supplementary group access list. Not
5940  * available on all platforms.
5941  *
5942  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
5943  * Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
5944  * Process.groups #=> [30, 6, 10, 11]
5945  *
5946  */
5947 
5948 static VALUE
5949 proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
5950 {
5951  if (initgroups(StringValueCStr(uname), OBJ2GID(base_grp)) != 0) {
5952  rb_sys_fail(0);
5953  }
5954  return proc_getgroups(obj);
5955 }
5956 #else
5957 #define proc_initgroups rb_f_notimplement
5958 #endif
5959 
5960 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
5961 /*
5962  * call-seq:
5963  * Process.maxgroups -> integer
5964  *
5965  * Returns the maximum number of gids allowed in the supplemental
5966  * group access list.
5967  *
5968  * Process.maxgroups #=> 32
5969  */
5970 
5971 static VALUE
5973 {
5974  return INT2FIX(maxgroups());
5975 }
5976 #else
5977 #define proc_getmaxgroups rb_f_notimplement
5978 #endif
5979 
5980 #ifdef HAVE_SETGROUPS
5981 /*
5982  * call-seq:
5983  * Process.maxgroups= integer -> integer
5984  *
5985  * Sets the maximum number of gids allowed in the supplemental group
5986  * access list.
5987  */
5988 
5989 static VALUE
5991 {
5992  int ngroups = FIX2INT(val);
5993  int ngroups_max = get_sc_ngroups_max();
5994 
5995  if (ngroups <= 0)
5996  rb_raise(rb_eArgError, "maxgroups %d shold be positive", ngroups);
5997 
5998  if (ngroups > RB_MAX_GROUPS)
5999  ngroups = RB_MAX_GROUPS;
6000 
6001  if (ngroups_max > 0 && ngroups > ngroups_max)
6002  ngroups = ngroups_max;
6003 
6004  _maxgroups = ngroups;
6005 
6006  return INT2FIX(_maxgroups);
6007 }
6008 #else
6009 #define proc_setmaxgroups rb_f_notimplement
6010 #endif
6011 
6012 #if defined(HAVE_DAEMON) || (defined(HAVE_WORKING_FORK) && defined(HAVE_SETSID))
6013 static int rb_daemon(int nochdir, int noclose);
6014 
6015 /*
6016  * call-seq:
6017  * Process.daemon() -> 0
6018  * Process.daemon(nochdir=nil,noclose=nil) -> 0
6019  *
6020  * Detach the process from controlling terminal and run in
6021  * the background as system daemon. Unless the argument
6022  * nochdir is true (i.e. non false), it changes the current
6023  * working directory to the root ("/"). Unless the argument
6024  * noclose is true, daemon() will redirect standard input,
6025  * standard output and standard error to /dev/null.
6026  * Return zero on success, or raise one of Errno::*.
6027  */
6028 
6029 static VALUE
6030 proc_daemon(int argc, VALUE *argv)
6031 {
6032  int n, nochdir = FALSE, noclose = FALSE;
6033 
6034  switch (rb_check_arity(argc, 0, 2)) {
6035  case 2: noclose = RTEST(argv[1]);
6036  case 1: nochdir = RTEST(argv[0]);
6037  }
6038 
6039  prefork();
6040  n = rb_daemon(nochdir, noclose);
6041  if (n < 0) rb_sys_fail("daemon");
6042  return INT2FIX(n);
6043 }
6044 
6045 static int
6046 rb_daemon(int nochdir, int noclose)
6047 {
6048  int err = 0;
6049 #ifdef HAVE_DAEMON
6050  before_fork_ruby();
6051  err = daemon(nochdir, noclose);
6052  after_fork_ruby();
6053  rb_thread_atfork();
6054 #else
6055  int n;
6056 
6057 #define fork_daemon() \
6058  switch (rb_fork_ruby(NULL)) { \
6059  case -1: return -1; \
6060  case 0: rb_thread_atfork(); break; \
6061  default: _exit(EXIT_SUCCESS); \
6062  }
6063 
6064  fork_daemon();
6065 
6066  if (setsid() < 0) return -1;
6067 
6068  /* must not be process-leader */
6069  fork_daemon();
6070 
6071  if (!nochdir)
6072  err = chdir("/");
6073 
6074  if (!noclose && (n = rb_cloexec_open("/dev/null", O_RDWR, 0)) != -1) {
6075  rb_update_max_fd(n);
6076  (void)dup2(n, 0);
6077  (void)dup2(n, 1);
6078  (void)dup2(n, 2);
6079  if (n > 2)
6080  (void)close (n);
6081  }
6082 #endif
6083  return err;
6084 }
6085 #else
6086 #define proc_daemon rb_f_notimplement
6087 #endif
6088 
6089 /********************************************************************
6090  *
6091  * Document-class: Process::GID
6092  *
6093  * The <code>Process::GID</code> module contains a collection of
6094  * module functions which can be used to portably get, set, and
6095  * switch the current process's real, effective, and saved group IDs.
6096  *
6097  */
6098 
6099 static rb_gid_t SAVED_GROUP_ID = -1;
6100 
6101 #ifdef BROKEN_SETREGID
6102 int
6103 setregid(rb_gid_t rgid, rb_gid_t egid)
6104 {
6105  if (rgid != (rb_gid_t)-1 && rgid != getgid()) {
6106  if (egid == (rb_gid_t)-1) egid = getegid();
6107  if (setgid(rgid) < 0) return -1;
6108  }
6109  if (egid != (rb_gid_t)-1 && egid != getegid()) {
6110  if (setegid(egid) < 0) return -1;
6111  }
6112  return 0;
6113 }
6114 #endif
6115 
6116 /*
6117  * call-seq:
6118  * Process::GID.change_privilege(group) -> integer
6119  *
6120  * Change the current process's real and effective group ID to that
6121  * specified by _group_. Returns the new group ID. Not
6122  * available on all platforms.
6123  *
6124  * [Process.gid, Process.egid] #=> [0, 0]
6125  * Process::GID.change_privilege(33) #=> 33
6126  * [Process.gid, Process.egid] #=> [33, 33]
6127  */
6128 
6129 static VALUE
6130 p_gid_change_privilege(VALUE obj, VALUE id)
6131 {
6132  rb_gid_t gid;
6133 
6134  check_gid_switch();
6135 
6136  gid = OBJ2GID(id);
6137 
6138  if (geteuid() == 0) { /* root-user */
6139 #if defined(HAVE_SETRESGID)
6140  if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
6141  SAVED_GROUP_ID = gid;
6142 #elif defined HAVE_SETGID
6143  if (setgid(gid) < 0) rb_sys_fail(0);
6144  SAVED_GROUP_ID = gid;
6145 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6146  if (getgid() == gid) {
6147  if (SAVED_GROUP_ID == gid) {
6148  if (setregid(-1, gid) < 0) rb_sys_fail(0);
6149  }
6150  else {
6151  if (gid == 0) { /* (r,e,s) == (root, y, x) */
6152  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6153  if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
6154  SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
6155  if (setregid(gid, gid) < 0) rb_sys_fail(0);
6156  SAVED_GROUP_ID = gid;
6157  }
6158  else { /* (r,e,s) == (z, y, x) */
6159  if (setregid(0, 0) < 0) rb_sys_fail(0);
6160  SAVED_GROUP_ID = 0;
6161  if (setregid(gid, gid) < 0) rb_sys_fail(0);
6162  SAVED_GROUP_ID = gid;
6163  }
6164  }
6165  }
6166  else {
6167  if (setregid(gid, gid) < 0) rb_sys_fail(0);
6168  SAVED_GROUP_ID = gid;
6169  }
6170 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
6171  if (getgid() == gid) {
6172  if (SAVED_GROUP_ID == gid) {
6173  if (setegid(gid) < 0) rb_sys_fail(0);
6174  }
6175  else {
6176  if (gid == 0) {
6177  if (setegid(gid) < 0) rb_sys_fail(0);
6178  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6179  SAVED_GROUP_ID = 0;
6180  if (setrgid(0) < 0) rb_sys_fail(0);
6181  }
6182  else {
6183  if (setrgid(0) < 0) rb_sys_fail(0);
6184  SAVED_GROUP_ID = 0;
6185  if (setegid(gid) < 0) rb_sys_fail(0);
6186  if (setrgid(gid) < 0) rb_sys_fail(0);
6187  SAVED_GROUP_ID = gid;
6188  }
6189  }
6190  }
6191  else {
6192  if (setegid(gid) < 0) rb_sys_fail(0);
6193  if (setrgid(gid) < 0) rb_sys_fail(0);
6194  SAVED_GROUP_ID = gid;
6195  }
6196 #else
6197  rb_notimplement();
6198 #endif
6199  }
6200  else { /* unprivileged user */
6201 #if defined(HAVE_SETRESGID)
6202  if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
6203  (getegid() == gid)? (rb_gid_t)-1: gid,
6204  (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
6205  SAVED_GROUP_ID = gid;
6206 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6207  if (SAVED_GROUP_ID == gid) {
6208  if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
6209  (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
6210  rb_sys_fail(0);
6211  }
6212  else if (getgid() != gid) {
6213  if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
6214  rb_sys_fail(0);
6215  SAVED_GROUP_ID = gid;
6216  }
6217  else if (/* getgid() == gid && */ getegid() != gid) {
6218  if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
6219  SAVED_GROUP_ID = gid;
6220  if (setregid(gid, -1) < 0) rb_sys_fail(0);
6221  }
6222  else { /* getgid() == gid && getegid() == gid */
6223  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6224  if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
6225  SAVED_GROUP_ID = gid;
6226  if (setregid(gid, -1) < 0) rb_sys_fail(0);
6227  }
6228 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
6229  if (SAVED_GROUP_ID == gid) {
6230  if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
6231  if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
6232  }
6233  else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
6234  if (getgid() != gid) {
6235  if (setrgid(gid) < 0) rb_sys_fail(0);
6236  SAVED_GROUP_ID = gid;
6237  }
6238  else {
6239  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6240  SAVED_GROUP_ID = gid;
6241  if (setrgid(gid) < 0) rb_sys_fail(0);
6242  }
6243  }
6244  else if (/* getegid() != gid && */ getgid() == gid) {
6245  if (setegid(gid) < 0) rb_sys_fail(0);
6246  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6247  SAVED_GROUP_ID = gid;
6248  if (setrgid(gid) < 0) rb_sys_fail(0);
6249  }
6250  else {
6251  rb_syserr_fail(EPERM, 0);
6252  }
6253 #elif defined HAVE_44BSD_SETGID
6254  if (getgid() == gid) {
6255  /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
6256  if (setgid(gid) < 0) rb_sys_fail(0);
6257  SAVED_GROUP_ID = gid;
6258  }
6259  else {
6260  rb_syserr_fail(EPERM, 0);
6261  }
6262 #elif defined HAVE_SETEGID
6263  if (getgid() == gid && SAVED_GROUP_ID == gid) {
6264  if (setegid(gid) < 0) rb_sys_fail(0);
6265  }
6266  else {
6267  rb_syserr_fail(EPERM, 0);
6268  }
6269 #elif defined HAVE_SETGID
6270  if (getgid() == gid && SAVED_GROUP_ID == gid) {
6271  if (setgid(gid) < 0) rb_sys_fail(0);
6272  }
6273  else {
6274  rb_syserr_fail(EPERM, 0);
6275  }
6276 #else
6277  (void)gid;
6278  rb_notimplement();
6279 #endif
6280  }
6281  return id;
6282 }
6283 
6284 
6285 /*
6286  * call-seq:
6287  * Process.euid -> integer
6288  * Process::UID.eid -> integer
6289  * Process::Sys.geteuid -> integer
6290  *
6291  * Returns the effective user ID for this process.
6292  *
6293  * Process.euid #=> 501
6294  */
6295 
6296 static VALUE
6297 proc_geteuid(VALUE obj)
6298 {
6299  rb_uid_t euid = geteuid();
6300  return UIDT2NUM(euid);
6301 }
6302 
6303 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
6304 static void
6305 proc_seteuid(rb_uid_t uid)
6306 {
6307 #if defined(HAVE_SETRESUID)
6308  if (setresuid(-1, uid, -1) < 0) rb_sys_fail(0);
6309 #elif defined HAVE_SETREUID
6310  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
6311 #elif defined HAVE_SETEUID
6312  if (seteuid(uid) < 0) rb_sys_fail(0);
6313 #elif defined HAVE_SETUID
6314  if (uid == getuid()) {
6315  if (setuid(uid) < 0) rb_sys_fail(0);
6316  }
6317  else {
6318  rb_notimplement();
6319  }
6320 #else
6321  rb_notimplement();
6322 #endif
6323 }
6324 #endif
6325 
6326 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
6327 /*
6328  * call-seq:
6329  * Process.euid= user
6330  *
6331  * Sets the effective user ID for this process. Not available on all
6332  * platforms.
6333  */
6334 
6335 static VALUE
6337 {
6338  check_uid_switch();
6339  proc_seteuid(OBJ2UID(euid));
6340  return euid;
6341 }
6342 #else
6343 #define proc_seteuid_m rb_f_notimplement
6344 #endif
6345 
6346 static rb_uid_t
6347 rb_seteuid_core(rb_uid_t euid)
6348 {
6349 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6350  rb_uid_t uid;
6351 #endif
6352 
6353  check_uid_switch();
6354 
6355 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6356  uid = getuid();
6357 #endif
6358 
6359 #if defined(HAVE_SETRESUID)
6360  if (uid != euid) {
6361  if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
6362  SAVED_USER_ID = euid;
6363  }
6364  else {
6365  if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
6366  }
6367 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6368  if (setreuid(-1, euid) < 0) rb_sys_fail(0);
6369  if (uid != euid) {
6370  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
6371  if (setreuid(uid,euid) < 0) rb_sys_fail(0);
6372  SAVED_USER_ID = euid;
6373  }
6374 #elif defined HAVE_SETEUID
6375  if (seteuid(euid) < 0) rb_sys_fail(0);
6376 #elif defined HAVE_SETUID
6377  if (geteuid() == 0) rb_sys_fail(0);
6378  if (setuid(euid) < 0) rb_sys_fail(0);
6379 #else
6380  rb_notimplement();
6381 #endif
6382  return euid;
6383 }
6384 
6385 
6386 /*
6387  * call-seq:
6388  * Process::UID.grant_privilege(user) -> integer
6389  * Process::UID.eid= user -> integer
6390  *
6391  * Set the effective user ID, and if possible, the saved user ID of
6392  * the process to the given _user_. Returns the new
6393  * effective user ID. Not available on all platforms.
6394  *
6395  * [Process.uid, Process.euid] #=> [0, 0]
6396  * Process::UID.grant_privilege(31) #=> 31
6397  * [Process.uid, Process.euid] #=> [0, 31]
6398  */
6399 
6400 static VALUE
6401 p_uid_grant_privilege(VALUE obj, VALUE id)
6402 {
6403  rb_seteuid_core(OBJ2UID(id));
6404  return id;
6405 }
6406 
6407 
6408 /*
6409  * call-seq:
6410  * Process.egid -> integer
6411  * Process::GID.eid -> integer
6412  * Process::Sys.geteid -> integer
6413  *
6414  * Returns the effective group ID for this process. Not available on
6415  * all platforms.
6416  *
6417  * Process.egid #=> 500
6418  */
6419 
6420 static VALUE
6421 proc_getegid(VALUE obj)
6422 {
6423  rb_gid_t egid = getegid();
6424 
6425  return GIDT2NUM(egid);
6426 }
6427 
6428 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
6429 /*
6430  * call-seq:
6431  * Process.egid = integer -> integer
6432  *
6433  * Sets the effective group ID for this process. Not available on all
6434  * platforms.
6435  */
6436 
6437 static VALUE
6438 proc_setegid(VALUE obj, VALUE egid)
6439 {
6440 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6441  rb_gid_t gid;
6442 #endif
6443 
6444  check_gid_switch();
6445 
6446 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6447  gid = OBJ2GID(egid);
6448 #endif
6449 
6450 #if defined(HAVE_SETRESGID)
6451  if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
6452 #elif defined HAVE_SETREGID
6453  if (setregid(-1, gid) < 0) rb_sys_fail(0);
6454 #elif defined HAVE_SETEGID
6455  if (setegid(gid) < 0) rb_sys_fail(0);
6456 #elif defined HAVE_SETGID
6457  if (gid == getgid()) {
6458  if (setgid(gid) < 0) rb_sys_fail(0);
6459  }
6460  else {
6461  rb_notimplement();
6462  }
6463 #else
6464  rb_notimplement();
6465 #endif
6466  return egid;
6467 }
6468 #endif
6469 
6470 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6471 #define proc_setegid_m proc_setegid
6472 #else
6473 #define proc_setegid_m rb_f_notimplement
6474 #endif
6475 
6476 static rb_gid_t
6477 rb_setegid_core(rb_gid_t egid)
6478 {
6479 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6480  rb_gid_t gid;
6481 #endif
6482 
6483  check_gid_switch();
6484 
6485 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6486  gid = getgid();
6487 #endif
6488 
6489 #if defined(HAVE_SETRESGID)
6490  if (gid != egid) {
6491  if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
6492  SAVED_GROUP_ID = egid;
6493  }
6494  else {
6495  if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
6496  }
6497 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6498  if (setregid(-1, egid) < 0) rb_sys_fail(0);
6499  if (gid != egid) {
6500  if (setregid(egid,gid) < 0) rb_sys_fail(0);
6501  if (setregid(gid,egid) < 0) rb_sys_fail(0);
6502  SAVED_GROUP_ID = egid;
6503  }
6504 #elif defined HAVE_SETEGID
6505  if (setegid(egid) < 0) rb_sys_fail(0);
6506 #elif defined HAVE_SETGID
6507  if (geteuid() == 0 /* root user */) rb_sys_fail(0);
6508  if (setgid(egid) < 0) rb_sys_fail(0);
6509 #else
6510  rb_notimplement();
6511 #endif
6512  return egid;
6513 }
6514 
6515 
6516 /*
6517  * call-seq:
6518  * Process::GID.grant_privilege(group) -> integer
6519  * Process::GID.eid = group -> integer
6520  *
6521  * Set the effective group ID, and if possible, the saved group ID of
6522  * the process to the given _group_. Returns the new
6523  * effective group ID. Not available on all platforms.
6524  *
6525  * [Process.gid, Process.egid] #=> [0, 0]
6526  * Process::GID.grant_privilege(31) #=> 33
6527  * [Process.gid, Process.egid] #=> [0, 33]
6528  */
6529 
6530 static VALUE
6531 p_gid_grant_privilege(VALUE obj, VALUE id)
6532 {
6533  rb_setegid_core(OBJ2GID(id));
6534  return id;
6535 }
6536 
6537 
6538 /*
6539  * call-seq:
6540  * Process::UID.re_exchangeable? -> true or false
6541  *
6542  * Returns +true+ if the real and effective user IDs of a
6543  * process may be exchanged on the current platform.
6544  *
6545  */
6546 
6547 static VALUE
6548 p_uid_exchangeable(void)
6549 {
6550 #if defined(HAVE_SETRESUID)
6551  return Qtrue;
6552 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6553  return Qtrue;
6554 #else
6555  return Qfalse;
6556 #endif
6557 }
6558 
6559 
6560 /*
6561  * call-seq:
6562  * Process::UID.re_exchange -> integer
6563  *
6564  * Exchange real and effective user IDs and return the new effective
6565  * user ID. Not available on all platforms.
6566  *
6567  * [Process.uid, Process.euid] #=> [0, 31]
6568  * Process::UID.re_exchange #=> 0
6569  * [Process.uid, Process.euid] #=> [31, 0]
6570  */
6571 
6572 static VALUE
6573 p_uid_exchange(VALUE obj)
6574 {
6575  rb_uid_t uid;
6576 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6577  rb_uid_t euid;
6578 #endif
6579 
6580  check_uid_switch();
6581 
6582  uid = getuid();
6583 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6584  euid = geteuid();
6585 #endif
6586 
6587 #if defined(HAVE_SETRESUID)
6588  if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
6589  SAVED_USER_ID = uid;
6590 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6591  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
6592  SAVED_USER_ID = uid;
6593 #else
6594  rb_notimplement();
6595 #endif
6596  return UIDT2NUM(uid);
6597 }
6598 
6599 
6600 /*
6601  * call-seq:
6602  * Process::GID.re_exchangeable? -> true or false
6603  *
6604  * Returns +true+ if the real and effective group IDs of a
6605  * process may be exchanged on the current platform.
6606  *
6607  */
6608 
6609 static VALUE
6610 p_gid_exchangeable(void)
6611 {
6612 #if defined(HAVE_SETRESGID)
6613  return Qtrue;
6614 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6615  return Qtrue;
6616 #else
6617  return Qfalse;
6618 #endif
6619 }
6620 
6621 
6622 /*
6623  * call-seq:
6624  * Process::GID.re_exchange -> integer
6625  *
6626  * Exchange real and effective group IDs and return the new effective
6627  * group ID. Not available on all platforms.
6628  *
6629  * [Process.gid, Process.egid] #=> [0, 33]
6630  * Process::GID.re_exchange #=> 0
6631  * [Process.gid, Process.egid] #=> [33, 0]
6632  */
6633 
6634 static VALUE
6635 p_gid_exchange(VALUE obj)
6636 {
6637  rb_gid_t gid;
6638 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6639  rb_gid_t egid;
6640 #endif
6641 
6642  check_gid_switch();
6643 
6644  gid = getgid();
6645 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6646  egid = getegid();
6647 #endif
6648 
6649 #if defined(HAVE_SETRESGID)
6650  if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
6651  SAVED_GROUP_ID = gid;
6652 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6653  if (setregid(egid,gid) < 0) rb_sys_fail(0);
6654  SAVED_GROUP_ID = gid;
6655 #else
6656  rb_notimplement();
6657 #endif
6658  return GIDT2NUM(gid);
6659 }
6660 
6661 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
6662 
6663 /*
6664  * call-seq:
6665  * Process::UID.sid_available? -> true or false
6666  *
6667  * Returns +true+ if the current platform has saved user
6668  * ID functionality.
6669  *
6670  */
6671 
6672 static VALUE
6673 p_uid_have_saved_id(void)
6674 {
6675 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
6676  return Qtrue;
6677 #else
6678  return Qfalse;
6679 #endif
6680 }
6681 
6682 
6683 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
6684 static VALUE
6685 p_uid_sw_ensure(rb_uid_t id)
6686 {
6687  under_uid_switch = 0;
6688  id = rb_seteuid_core(id);
6689  return UIDT2NUM(id);
6690 }
6691 
6692 
6693 /*
6694  * call-seq:
6695  * Process::UID.switch -> integer
6696  * Process::UID.switch {|| block} -> object
6697  *
6698  * Switch the effective and real user IDs of the current process. If
6699  * a <em>block</em> is given, the user IDs will be switched back
6700  * after the block is executed. Returns the new effective user ID if
6701  * called without a block, and the return value of the block if one
6702  * is given.
6703  *
6704  */
6705 
6706 static VALUE
6707 p_uid_switch(VALUE obj)
6708 {
6709  rb_uid_t uid, euid;
6710 
6711  check_uid_switch();
6712 
6713  uid = getuid();
6714  euid = geteuid();
6715 
6716  if (uid != euid) {
6717  proc_seteuid(uid);
6718  if (rb_block_given_p()) {
6719  under_uid_switch = 1;
6720  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
6721  }
6722  else {
6723  return UIDT2NUM(euid);
6724  }
6725  }
6726  else if (euid != SAVED_USER_ID) {
6727  proc_seteuid(SAVED_USER_ID);
6728  if (rb_block_given_p()) {
6729  under_uid_switch = 1;
6730  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
6731  }
6732  else {
6733  return UIDT2NUM(uid);
6734  }
6735  }
6736  else {
6737  rb_syserr_fail(EPERM, 0);
6738  }
6739 
6740  UNREACHABLE;
6741 }
6742 #else
6743 static VALUE
6744 p_uid_sw_ensure(VALUE obj)
6745 {
6746  under_uid_switch = 0;
6747  return p_uid_exchange(obj);
6748 }
6749 
6750 static VALUE
6751 p_uid_switch(VALUE obj)
6752 {
6753  rb_uid_t uid, euid;
6754 
6755  check_uid_switch();
6756 
6757  uid = getuid();
6758  euid = geteuid();
6759 
6760  if (uid == euid) {
6761  rb_syserr_fail(EPERM, 0);
6762  }
6763  p_uid_exchange(obj);
6764  if (rb_block_given_p()) {
6765  under_uid_switch = 1;
6766  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
6767  }
6768  else {
6769  return UIDT2NUM(euid);
6770  }
6771 }
6772 #endif
6773 
6774 
6775 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
6776 
6777 /*
6778  * call-seq:
6779  * Process::GID.sid_available? -> true or false
6780  *
6781  * Returns +true+ if the current platform has saved group
6782  * ID functionality.
6783  *
6784  */
6785 
6786 static VALUE
6787 p_gid_have_saved_id(void)
6788 {
6789 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
6790  return Qtrue;
6791 #else
6792  return Qfalse;
6793 #endif
6794 }
6795 
6796 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
6797 static VALUE
6798 p_gid_sw_ensure(rb_gid_t id)
6799 {
6800  under_gid_switch = 0;
6801  id = rb_setegid_core(id);
6802  return GIDT2NUM(id);
6803 }
6804 
6805 
6806 /*
6807  * call-seq:
6808  * Process::GID.switch -> integer
6809  * Process::GID.switch {|| block} -> object
6810  *
6811  * Switch the effective and real group IDs of the current process. If
6812  * a <em>block</em> is given, the group IDs will be switched back
6813  * after the block is executed. Returns the new effective group ID if
6814  * called without a block, and the return value of the block if one
6815  * is given.
6816  *
6817  */
6818 
6819 static VALUE
6820 p_gid_switch(VALUE obj)
6821 {
6822  rb_gid_t gid, egid;
6823 
6824  check_gid_switch();
6825 
6826  gid = getgid();
6827  egid = getegid();
6828 
6829  if (gid != egid) {
6830  proc_setegid(obj, GIDT2NUM(gid));
6831  if (rb_block_given_p()) {
6832  under_gid_switch = 1;
6833  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
6834  }
6835  else {
6836  return GIDT2NUM(egid);
6837  }
6838  }
6839  else if (egid != SAVED_GROUP_ID) {
6840  proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
6841  if (rb_block_given_p()) {
6842  under_gid_switch = 1;
6843  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
6844  }
6845  else {
6846  return GIDT2NUM(gid);
6847  }
6848  }
6849  else {
6850  rb_syserr_fail(EPERM, 0);
6851  }
6852 
6853  UNREACHABLE;
6854 }
6855 #else
6856 static VALUE
6857 p_gid_sw_ensure(VALUE obj)
6858 {
6859  under_gid_switch = 0;
6860  return p_gid_exchange(obj);
6861 }
6862 
6863 static VALUE
6864 p_gid_switch(VALUE obj)
6865 {
6866  rb_gid_t gid, egid;
6867 
6868  check_gid_switch();
6869 
6870  gid = getgid();
6871  egid = getegid();
6872 
6873  if (gid == egid) {
6874  rb_syserr_fail(EPERM, 0);
6875  }
6876  p_gid_exchange(obj);
6877  if (rb_block_given_p()) {
6878  under_gid_switch = 1;
6879  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
6880  }
6881  else {
6882  return GIDT2NUM(egid);
6883  }
6884 }
6885 #endif
6886 
6887 
6888 #if defined(HAVE_TIMES)
6889 static long
6890 get_clk_tck(void)
6891 {
6892  long hertz =
6893 #ifdef HAVE__SC_CLK_TCK
6894  (double)sysconf(_SC_CLK_TCK);
6895 #else
6896 #ifndef HZ
6897 # ifdef CLK_TCK
6898 # define HZ CLK_TCK
6899 # else
6900 # define HZ 60
6901 # endif
6902 #endif /* HZ */
6903  HZ;
6904 #endif
6905  return hertz;
6906 }
6907 
6908 /*
6909  * call-seq:
6910  * Process.times -> aProcessTms
6911  *
6912  * Returns a <code>Tms</code> structure (see <code>Process::Tms</code>)
6913  * that contains user and system CPU times for this process,
6914  * and also for children processes.
6915  *
6916  * t = Process.times
6917  * [ t.utime, t.stime, t.cutime, t.cstime ] #=> [0.0, 0.02, 0.00, 0.00]
6918  */
6919 
6920 VALUE
6921 rb_proc_times(VALUE obj)
6922 {
6923  VALUE utime, stime, cutime, cstime, ret;
6924 #if defined(RUSAGE_SELF) && defined(RUSAGE_CHILDREN)
6925  struct rusage usage_s, usage_c;
6926 
6927  if (getrusage(RUSAGE_SELF, &usage_s) != 0 || getrusage(RUSAGE_CHILDREN, &usage_c) != 0)
6928  rb_sys_fail("getrusage");
6929  utime = DBL2NUM((double)usage_s.ru_utime.tv_sec + (double)usage_s.ru_utime.tv_usec/1e6);
6930  stime = DBL2NUM((double)usage_s.ru_stime.tv_sec + (double)usage_s.ru_stime.tv_usec/1e6);
6931  cutime = DBL2NUM((double)usage_c.ru_utime.tv_sec + (double)usage_c.ru_utime.tv_usec/1e6);
6932  cstime = DBL2NUM((double)usage_c.ru_stime.tv_sec + (double)usage_c.ru_stime.tv_usec/1e6);
6933 #else
6934  const double hertz = get_clk_tck();
6935  struct tms buf;
6936 
6937  times(&buf);
6938  utime = DBL2NUM(buf.tms_utime / hertz);
6939  stime = DBL2NUM(buf.tms_stime / hertz);
6940  cutime = DBL2NUM(buf.tms_cutime / hertz);
6941  cstime = DBL2NUM(buf.tms_cstime / hertz);
6942 #endif
6943  ret = rb_struct_new(rb_cProcessTms, utime, stime, cutime, cstime);
6944  RB_GC_GUARD(utime);
6945  RB_GC_GUARD(stime);
6946  RB_GC_GUARD(cutime);
6947  RB_GC_GUARD(cstime);
6948  return ret;
6949 }
6950 #else
6951 #define rb_proc_times rb_f_notimplement
6952 #endif
6953 
6954 #ifdef HAVE_LONG_LONG
6955 typedef LONG_LONG timetick_int_t;
6956 #define TIMETICK_INT_MIN LLONG_MIN
6957 #define TIMETICK_INT_MAX LLONG_MAX
6958 #define TIMETICK_INT2NUM(v) LL2NUM(v)
6959 #define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_LONG_P(a, b)
6960 #else
6961 typedef long timetick_int_t;
6962 #define TIMETICK_INT_MIN LONG_MIN
6963 #define TIMETICK_INT_MAX LONG_MAX
6964 #define TIMETICK_INT2NUM(v) LONG2NUM(v)
6965 #define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_P(a, b)
6966 #endif
6967 
6968 CONSTFUNC(static timetick_int_t gcd_timetick_int(timetick_int_t, timetick_int_t));
6969 static timetick_int_t
6970 gcd_timetick_int(timetick_int_t a, timetick_int_t b)
6971 {
6972  timetick_int_t t;
6973 
6974  if (a < b) {
6975  t = a;
6976  a = b;
6977  b = t;
6978  }
6979 
6980  while (1) {
6981  t = a % b;
6982  if (t == 0)
6983  return b;
6984  a = b;
6985  b = t;
6986  }
6987 }
6988 
6989 static void
6990 reduce_fraction(timetick_int_t *np, timetick_int_t *dp)
6991 {
6992  timetick_int_t gcd = gcd_timetick_int(*np, *dp);
6993  if (gcd != 1) {
6994  *np /= gcd;
6995  *dp /= gcd;
6996  }
6997 }
6998 
6999 static void
7000 reduce_factors(timetick_int_t *numerators, int num_numerators,
7001  timetick_int_t *denominators, int num_denominators)
7002 {
7003  int i, j;
7004  for (i = 0; i < num_numerators; i++) {
7005  if (numerators[i] == 1)
7006  continue;
7007  for (j = 0; j < num_denominators; j++) {
7008  if (denominators[j] == 1)
7009  continue;
7010  reduce_fraction(&numerators[i], &denominators[j]);
7011  }
7012  }
7013 }
7014 
7015 struct timetick {
7016  timetick_int_t giga_count;
7017  int32_t count; /* 0 .. 999999999 */
7018 };
7019 
7020 static VALUE
7021 timetick2dblnum(struct timetick *ttp,
7022  timetick_int_t *numerators, int num_numerators,
7023  timetick_int_t *denominators, int num_denominators)
7024 {
7025  double d;
7026  int i;
7027 
7028  reduce_factors(numerators, num_numerators,
7029  denominators, num_denominators);
7030 
7031  d = ttp->giga_count * 1e9 + ttp->count;
7032 
7033  for (i = 0; i < num_numerators; i++)
7034  d *= numerators[i];
7035  for (i = 0; i < num_denominators; i++)
7036  d /= denominators[i];
7037 
7038  return DBL2NUM(d);
7039 }
7040 
7041 static VALUE
7042 timetick2dblnum_reciprocal(struct timetick *ttp,
7043  timetick_int_t *numerators, int num_numerators,
7044  timetick_int_t *denominators, int num_denominators)
7045 {
7046  double d;
7047  int i;
7048 
7049  reduce_factors(numerators, num_numerators,
7050  denominators, num_denominators);
7051 
7052  d = 1.0;
7053  for (i = 0; i < num_denominators; i++)
7054  d *= denominators[i];
7055  for (i = 0; i < num_numerators; i++)
7056  d /= numerators[i];
7057  d /= ttp->giga_count * 1e9 + ttp->count;
7058 
7059  return DBL2NUM(d);
7060 }
7061 
7062 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
7063 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
7064 
7065 static VALUE
7066 timetick2integer(struct timetick *ttp,
7067  timetick_int_t *numerators, int num_numerators,
7068  timetick_int_t *denominators, int num_denominators)
7069 {
7070  VALUE v;
7071  int i;
7072 
7073  reduce_factors(numerators, num_numerators,
7074  denominators, num_denominators);
7075 
7076  if (!MUL_OVERFLOW_SIGNED_INTEGER_P(1000000000, ttp->giga_count,
7078  timetick_int_t t = ttp->giga_count * 1000000000 + ttp->count;
7079  for (i = 0; i < num_numerators; i++) {
7080  timetick_int_t factor = numerators[i];
7081  if (MUL_OVERFLOW_TIMETICK_P(factor, t))
7082  goto generic;
7083  t *= factor;
7084  }
7085  for (i = 0; i < num_denominators; i++) {
7086  t = DIV(t, denominators[i]);
7087  }
7088  return TIMETICK_INT2NUM(t);
7089  }
7090 
7091  generic:
7092  v = TIMETICK_INT2NUM(ttp->giga_count);
7093  v = rb_funcall(v, '*', 1, LONG2FIX(1000000000));
7094  v = rb_funcall(v, '+', 1, LONG2FIX(ttp->count));
7095  for (i = 0; i < num_numerators; i++) {
7096  timetick_int_t factor = numerators[i];
7097  if (factor == 1)
7098  continue;
7099  v = rb_funcall(v, '*', 1, TIMETICK_INT2NUM(factor));
7100  }
7101  for (i = 0; i < num_denominators; i++) {
7102  v = rb_funcall(v, '/', 1, TIMETICK_INT2NUM(denominators[i])); /* Ruby's '/' is div. */
7103  }
7104  return v;
7105 }
7106 
7107 static VALUE
7108 make_clock_result(struct timetick *ttp,
7109  timetick_int_t *numerators, int num_numerators,
7110  timetick_int_t *denominators, int num_denominators,
7111  VALUE unit)
7112 {
7113  if (unit == ID2SYM(id_nanosecond)) {
7114  numerators[num_numerators++] = 1000000000;
7115  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7116  }
7117  else if (unit == ID2SYM(id_microsecond)) {
7118  numerators[num_numerators++] = 1000000;
7119  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7120  }
7121  else if (unit == ID2SYM(id_millisecond)) {
7122  numerators[num_numerators++] = 1000;
7123  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7124  }
7125  else if (unit == ID2SYM(id_second)) {
7126  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7127  }
7128  else if (unit == ID2SYM(id_float_microsecond)) {
7129  numerators[num_numerators++] = 1000000;
7130  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7131  }
7132  else if (unit == ID2SYM(id_float_millisecond)) {
7133  numerators[num_numerators++] = 1000;
7134  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7135  }
7136  else if (NIL_P(unit) || unit == ID2SYM(id_float_second)) {
7137  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7138  }
7139  else
7140  rb_raise(rb_eArgError, "unexpected unit: %"PRIsVALUE, unit);
7141 }
7142 
7143 #ifdef __APPLE__
7144 static mach_timebase_info_data_t *
7145 get_mach_timebase_info(void)
7146 {
7147  static mach_timebase_info_data_t sTimebaseInfo;
7148 
7149  if ( sTimebaseInfo.denom == 0 ) {
7150  (void) mach_timebase_info(&sTimebaseInfo);
7151  }
7152 
7153  return &sTimebaseInfo;
7154 }
7155 #endif
7156 
7157 /*
7158  * call-seq:
7159  * Process.clock_gettime(clock_id [, unit]) -> number
7160  *
7161  * Returns a time returned by POSIX clock_gettime() function.
7162  *
7163  * p Process.clock_gettime(Process::CLOCK_MONOTONIC)
7164  * #=> 896053.968060096
7165  *
7166  * +clock_id+ specifies a kind of clock.
7167  * It is specified as a constant which begins with <code>Process::CLOCK_</code>
7168  * such as Process::CLOCK_REALTIME and Process::CLOCK_MONOTONIC.
7169  *
7170  * The supported constants depends on OS and version.
7171  * Ruby provides following types of +clock_id+ if available.
7172  *
7173  * [CLOCK_REALTIME] SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12
7174  * [CLOCK_MONOTONIC] SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12
7175  * [CLOCK_PROCESS_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, OpenBSD 5.4, macOS 10.12
7176  * [CLOCK_THREAD_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD 5.4, macOS 10.12
7177  * [CLOCK_VIRTUAL] FreeBSD 3.0, OpenBSD 2.1
7178  * [CLOCK_PROF] FreeBSD 3.0, OpenBSD 2.1
7179  * [CLOCK_REALTIME_FAST] FreeBSD 8.1
7180  * [CLOCK_REALTIME_PRECISE] FreeBSD 8.1
7181  * [CLOCK_REALTIME_COARSE] Linux 2.6.32
7182  * [CLOCK_REALTIME_ALARM] Linux 3.0
7183  * [CLOCK_MONOTONIC_FAST] FreeBSD 8.1
7184  * [CLOCK_MONOTONIC_PRECISE] FreeBSD 8.1
7185  * [CLOCK_MONOTONIC_COARSE] Linux 2.6.32
7186  * [CLOCK_MONOTONIC_RAW] Linux 2.6.28, macOS 10.12
7187  * [CLOCK_MONOTONIC_RAW_APPROX] macOS 10.12
7188  * [CLOCK_BOOTTIME] Linux 2.6.39
7189  * [CLOCK_BOOTTIME_ALARM] Linux 3.0
7190  * [CLOCK_UPTIME] FreeBSD 7.0, OpenBSD 5.5
7191  * [CLOCK_UPTIME_FAST] FreeBSD 8.1
7192  * [CLOCK_UPTIME_RAW] macOS 10.12
7193  * [CLOCK_UPTIME_RAW_APPROX] macOS 10.12
7194  * [CLOCK_UPTIME_PRECISE] FreeBSD 8.1
7195  * [CLOCK_SECOND] FreeBSD 8.1
7196  *
7197  * Note that SUS stands for Single Unix Specification.
7198  * SUS contains POSIX and clock_gettime is defined in the POSIX part.
7199  * SUS defines CLOCK_REALTIME mandatory but
7200  * CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID are optional.
7201  *
7202  * Also, several symbols are accepted as +clock_id+.
7203  * There are emulations for clock_gettime().
7204  *
7205  * For example, Process::CLOCK_REALTIME is defined as
7206  * +:GETTIMEOFDAY_BASED_CLOCK_REALTIME+ when clock_gettime() is not available.
7207  *
7208  * Emulations for +CLOCK_REALTIME+:
7209  * [:GETTIMEOFDAY_BASED_CLOCK_REALTIME]
7210  * Use gettimeofday() defined by SUS.
7211  * (SUSv4 obsoleted it, though.)
7212  * The resolution is 1 microsecond.
7213  * [:TIME_BASED_CLOCK_REALTIME]
7214  * Use time() defined by ISO C.
7215  * The resolution is 1 second.
7216  *
7217  * Emulations for +CLOCK_MONOTONIC+:
7218  * [:MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC]
7219  * Use mach_absolute_time(), available on Darwin.
7220  * The resolution is CPU dependent.
7221  * [:TIMES_BASED_CLOCK_MONOTONIC]
7222  * Use the result value of times() defined by POSIX.
7223  * POSIX defines it as "times() shall return the elapsed real time, in clock ticks, since an arbitrary point in the past (for example, system start-up time)".
7224  * For example, GNU/Linux returns a value based on jiffies and it is monotonic.
7225  * However, 4.4BSD uses gettimeofday() and it is not monotonic.
7226  * (FreeBSD uses clock_gettime(CLOCK_MONOTONIC) instead, though.)
7227  * The resolution is the clock tick.
7228  * "getconf CLK_TCK" command shows the clock ticks per second.
7229  * (The clock ticks per second is defined by HZ macro in older systems.)
7230  * If it is 100 and clock_t is 32 bits integer type, the resolution is 10 millisecond and
7231  * cannot represent over 497 days.
7232  *
7233  * Emulations for +CLOCK_PROCESS_CPUTIME_ID+:
7234  * [:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID]
7235  * Use getrusage() defined by SUS.
7236  * getrusage() is used with RUSAGE_SELF to obtain the time only for
7237  * the calling process (excluding the time for child processes).
7238  * The result is addition of user time (ru_utime) and system time (ru_stime).
7239  * The resolution is 1 microsecond.
7240  * [:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID]
7241  * Use times() defined by POSIX.
7242  * The result is addition of user time (tms_utime) and system time (tms_stime).
7243  * tms_cutime and tms_cstime are ignored to exclude the time for child processes.
7244  * The resolution is the clock tick.
7245  * "getconf CLK_TCK" command shows the clock ticks per second.
7246  * (The clock ticks per second is defined by HZ macro in older systems.)
7247  * If it is 100, the resolution is 10 millisecond.
7248  * [:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID]
7249  * Use clock() defined by ISO C.
7250  * The resolution is 1/CLOCKS_PER_SEC.
7251  * CLOCKS_PER_SEC is the C-level macro defined by time.h.
7252  * SUS defines CLOCKS_PER_SEC is 1000000.
7253  * Non-Unix systems may define it a different value, though.
7254  * If CLOCKS_PER_SEC is 1000000 as SUS, the resolution is 1 microsecond.
7255  * If CLOCKS_PER_SEC is 1000000 and clock_t is 32 bits integer type, it cannot represent over 72 minutes.
7256  *
7257  * If the given +clock_id+ is not supported, Errno::EINVAL is raised.
7258  *
7259  * +unit+ specifies a type of the return value.
7260  *
7261  * [:float_second] number of seconds as a float (default)
7262  * [:float_millisecond] number of milliseconds as a float
7263  * [:float_microsecond] number of microseconds as a float
7264  * [:second] number of seconds as an integer
7265  * [:millisecond] number of milliseconds as an integer
7266  * [:microsecond] number of microseconds as an integer
7267  * [:nanosecond] number of nanoseconds as an integer
7268  *
7269  * The underlying function, clock_gettime(), returns a number of nanoseconds.
7270  * Float object (IEEE 754 double) is not enough to represent
7271  * the return value for CLOCK_REALTIME.
7272  * If the exact nanoseconds value is required, use +:nanoseconds+ as the +unit+.
7273  *
7274  * The origin (zero) of the returned value varies.
7275  * For example, system start up time, process start up time, the Epoch, etc.
7276  *
7277  * The origin in CLOCK_REALTIME is defined as the Epoch
7278  * (1970-01-01 00:00:00 UTC).
7279  * But some systems count leap seconds and others doesn't.
7280  * So the result can be interpreted differently across systems.
7281  * Time.now is recommended over CLOCK_REALTIME.
7282  */
7283 VALUE
7284 rb_clock_gettime(int argc, VALUE *argv)
7285 {
7286  int ret;
7287 
7288  struct timetick tt;
7289  timetick_int_t numerators[2];
7290  timetick_int_t denominators[2];
7291  int num_numerators = 0;
7292  int num_denominators = 0;
7293 
7294  VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
7295  VALUE clk_id = argv[0];
7296 
7297  if (SYMBOL_P(clk_id)) {
7298  /*
7299  * Non-clock_gettime clocks are provided by symbol clk_id.
7300  *
7301  * gettimeofday is always available on platforms supported by Ruby.
7302  * GETTIMEOFDAY_BASED_CLOCK_REALTIME is used for
7303  * CLOCK_REALTIME if clock_gettime is not available.
7304  */
7305 #define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ID2SYM(id_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
7307  struct timeval tv;
7308  ret = gettimeofday(&tv, 0);
7309  if (ret != 0)
7310  rb_sys_fail("gettimeofday");
7311  tt.giga_count = tv.tv_sec;
7312  tt.count = (int32_t)tv.tv_usec * 1000;
7313  denominators[num_denominators++] = 1000000000;
7314  goto success;
7315  }
7316 
7317 #define RUBY_TIME_BASED_CLOCK_REALTIME ID2SYM(id_TIME_BASED_CLOCK_REALTIME)
7318  if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
7319  time_t t;
7320  t = time(NULL);
7321  if (t == (time_t)-1)
7322  rb_sys_fail("time");
7323  tt.giga_count = t;
7324  tt.count = 0;
7325  denominators[num_denominators++] = 1000000000;
7326  goto success;
7327  }
7328 
7329 #ifdef HAVE_TIMES
7330 #define RUBY_TIMES_BASED_CLOCK_MONOTONIC \
7331  ID2SYM(id_TIMES_BASED_CLOCK_MONOTONIC)
7332  if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
7333  struct tms buf;
7334  clock_t c;
7335  unsigned_clock_t uc;
7336  c = times(&buf);
7337  if (c == (clock_t)-1)
7338  rb_sys_fail("times");
7339  uc = (unsigned_clock_t)c;
7340  tt.count = (int32_t)(uc % 1000000000);
7341  tt.giga_count = (uc / 1000000000);
7342  denominators[num_denominators++] = get_clk_tck();
7343  goto success;
7344  }
7345 #endif
7346 
7347 #ifdef RUSAGE_SELF
7348 #define RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID \
7349  ID2SYM(id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
7350  if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7351  struct rusage usage;
7352  int32_t usec;
7353  ret = getrusage(RUSAGE_SELF, &usage);
7354  if (ret != 0)
7355  rb_sys_fail("getrusage");
7356  tt.giga_count = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
7357  usec = (int32_t)(usage.ru_utime.tv_usec + usage.ru_stime.tv_usec);
7358  if (1000000 <= usec) {
7359  tt.giga_count++;
7360  usec -= 1000000;
7361  }
7362  tt.count = usec * 1000;
7363  denominators[num_denominators++] = 1000000000;
7364  goto success;
7365  }
7366 #endif
7367 
7368 #ifdef HAVE_TIMES
7369 #define RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID \
7370  ID2SYM(id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID)
7371  if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7372  struct tms buf;
7373  unsigned_clock_t utime, stime;
7374  if (times(&buf) == (clock_t)-1)
7375  rb_sys_fail("times");
7376  utime = (unsigned_clock_t)buf.tms_utime;
7377  stime = (unsigned_clock_t)buf.tms_stime;
7378  tt.count = (int32_t)((utime % 1000000000) + (stime % 1000000000));
7379  tt.giga_count = (utime / 1000000000) + (stime / 1000000000);
7380  if (1000000000 <= tt.count) {
7381  tt.count -= 1000000000;
7382  tt.giga_count++;
7383  }
7384  denominators[num_denominators++] = get_clk_tck();
7385  goto success;
7386  }
7387 #endif
7388 
7389 #define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID \
7390  ID2SYM(id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID)
7392  clock_t c;
7393  unsigned_clock_t uc;
7394  errno = 0;
7395  c = clock();
7396  if (c == (clock_t)-1)
7397  rb_sys_fail("clock");
7398  uc = (unsigned_clock_t)c;
7399  tt.count = (int32_t)(uc % 1000000000);
7400  tt.giga_count = uc / 1000000000;
7401  denominators[num_denominators++] = CLOCKS_PER_SEC;
7402  goto success;
7403  }
7404 
7405 #ifdef __APPLE__
7406 #define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
7407  if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
7408  mach_timebase_info_data_t *info = get_mach_timebase_info();
7409  uint64_t t = mach_absolute_time();
7410  tt.count = (int32_t)(t % 1000000000);
7411  tt.giga_count = t / 1000000000;
7412  numerators[num_numerators++] = info->numer;
7413  denominators[num_denominators++] = info->denom;
7414  denominators[num_denominators++] = 1000000000;
7415  goto success;
7416  }
7417 #endif
7418  }
7419  else {
7420 #if defined(HAVE_CLOCK_GETTIME)
7421  struct timespec ts;
7422  clockid_t c;
7423  c = NUM2CLOCKID(clk_id);
7424  ret = clock_gettime(c, &ts);
7425  if (ret == -1)
7426  rb_sys_fail("clock_gettime");
7427  tt.count = (int32_t)ts.tv_nsec;
7428  tt.giga_count = ts.tv_sec;
7429  denominators[num_denominators++] = 1000000000;
7430  goto success;
7431 #endif
7432  }
7433  /* EINVAL emulates clock_gettime behavior when clock_id is invalid. */
7434  rb_syserr_fail(EINVAL, 0);
7435 
7436  success:
7437  return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
7438 }
7439 
7440 /*
7441  * call-seq:
7442  * Process.clock_getres(clock_id [, unit]) -> number
7443  *
7444  * Returns the time resolution returned by POSIX clock_getres() function.
7445  *
7446  * +clock_id+ specifies a kind of clock.
7447  * See the document of +Process.clock_gettime+ for details.
7448  *
7449  * +clock_id+ can be a symbol as +Process.clock_gettime+.
7450  * However the result may not be accurate.
7451  * For example, +Process.clock_getres(:GETTIMEOFDAY_BASED_CLOCK_REALTIME)+
7452  * returns 1.0e-06 which means 1 microsecond, but actual resolution can be more coarse.
7453  *
7454  * If the given +clock_id+ is not supported, Errno::EINVAL is raised.
7455  *
7456  * +unit+ specifies a type of the return value.
7457  * +Process.clock_getres+ accepts +unit+ as +Process.clock_gettime+.
7458  * The default value, +:float_second+, is also same as
7459  * +Process.clock_gettime+.
7460  *
7461  * +Process.clock_getres+ also accepts +:hertz+ as +unit+.
7462  * +:hertz+ means a the reciprocal of +:float_second+.
7463  *
7464  * +:hertz+ can be used to obtain the exact value of
7465  * the clock ticks per second for times() function and
7466  * CLOCKS_PER_SEC for clock() function.
7467  *
7468  * +Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)+
7469  * returns the clock ticks per second.
7470  *
7471  * +Process.clock_getres(:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)+
7472  * returns CLOCKS_PER_SEC.
7473  *
7474  * p Process.clock_getres(Process::CLOCK_MONOTONIC)
7475  * #=> 1.0e-09
7476  *
7477  */
7478 VALUE
7479 rb_clock_getres(int argc, VALUE *argv)
7480 {
7481  struct timetick tt;
7482  timetick_int_t numerators[2];
7483  timetick_int_t denominators[2];
7484  int num_numerators = 0;
7485  int num_denominators = 0;
7486 
7487  VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
7488  VALUE clk_id = argv[0];
7489 
7490  if (SYMBOL_P(clk_id)) {
7491 #ifdef RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
7493  tt.giga_count = 0;
7494  tt.count = 1000;
7495  denominators[num_denominators++] = 1000000000;
7496  goto success;
7497  }
7498 #endif
7499 
7500 #ifdef RUBY_TIME_BASED_CLOCK_REALTIME
7501  if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
7502  tt.giga_count = 1;
7503  tt.count = 0;
7504  denominators[num_denominators++] = 1000000000;
7505  goto success;
7506  }
7507 #endif
7508 
7509 #ifdef RUBY_TIMES_BASED_CLOCK_MONOTONIC
7510  if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
7511  tt.count = 1;
7512  tt.giga_count = 0;
7513  denominators[num_denominators++] = get_clk_tck();
7514  goto success;
7515  }
7516 #endif
7517 
7518 #ifdef RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
7519  if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7520  tt.giga_count = 0;
7521  tt.count = 1000;
7522  denominators[num_denominators++] = 1000000000;
7523  goto success;
7524  }
7525 #endif
7526 
7527 #ifdef RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID
7528  if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7529  tt.count = 1;
7530  tt.giga_count = 0;
7531  denominators[num_denominators++] = get_clk_tck();
7532  goto success;
7533  }
7534 #endif
7535 
7536 #ifdef RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
7538  tt.count = 1;
7539  tt.giga_count = 0;
7540  denominators[num_denominators++] = CLOCKS_PER_SEC;
7541  goto success;
7542  }
7543 #endif
7544 
7545 #ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
7546  if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
7547  mach_timebase_info_data_t *info = get_mach_timebase_info();
7548  tt.count = 1;
7549  tt.giga_count = 0;
7550  numerators[num_numerators++] = info->numer;
7551  denominators[num_denominators++] = info->denom;
7552  denominators[num_denominators++] = 1000000000;
7553  goto success;
7554  }
7555 #endif
7556  }
7557  else {
7558 #if defined(HAVE_CLOCK_GETRES)
7559  struct timespec ts;
7560  clockid_t c = NUM2CLOCKID(clk_id);
7561  int ret = clock_getres(c, &ts);
7562  if (ret == -1)
7563  rb_sys_fail("clock_getres");
7564  tt.count = (int32_t)ts.tv_nsec;
7565  tt.giga_count = ts.tv_sec;
7566  denominators[num_denominators++] = 1000000000;
7567  goto success;
7568 #endif
7569  }
7570  /* EINVAL emulates clock_getres behavior when clock_id is invalid. */
7571  rb_syserr_fail(EINVAL, 0);
7572 
7573  success:
7574  if (unit == ID2SYM(id_hertz)) {
7575  return timetick2dblnum_reciprocal(&tt, numerators, num_numerators, denominators, num_denominators);
7576  }
7577  else {
7578  return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
7579  }
7580 }
7581 
7586 
7587 
7588 /*
7589  * The <code>Process</code> module is a collection of methods used to
7590  * manipulate processes.
7591  */
7592 
7593 void
7595 {
7596 #undef rb_intern
7597 #define rb_intern(str) rb_intern_const(str)
7599  rb_define_virtual_variable("$$", get_pid, 0);
7600  rb_define_global_function("exec", rb_f_exec, -1);
7602  rb_define_global_function("exit!", rb_f_exit_bang, -1);
7603  rb_define_global_function("system", rb_f_system, -1);
7604  rb_define_global_function("spawn", rb_f_spawn, -1);
7605  rb_define_global_function("sleep", rb_f_sleep, -1);
7606  rb_define_global_function("exit", rb_f_exit, -1);
7607  rb_define_global_function("abort", rb_f_abort, -1);
7608 
7609  rb_mProcess = rb_define_module("Process");
7610 
7611 #ifdef WNOHANG
7612  /* see Process.wait */
7613  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
7614 #else
7615  /* see Process.wait */
7616  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
7617 #endif
7618 #ifdef WUNTRACED
7619  /* see Process.wait */
7620  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
7621 #else
7622  /* see Process.wait */
7623  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
7624 #endif
7625 
7626  rb_define_singleton_method(rb_mProcess, "exec", rb_f_exec, -1);
7627  rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
7628  rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
7629  rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
7630  rb_define_singleton_method(rb_mProcess, "exit", rb_f_exit, -1);
7631  rb_define_singleton_method(rb_mProcess, "abort", rb_f_abort, -1);
7632 
7633  rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1); /* in signal.c */
7634  rb_define_module_function(rb_mProcess, "wait", proc_wait, -1);
7635  rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
7636  rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
7637  rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
7638  rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
7639  rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
7640 
7641  rb_cWaiter = rb_define_class_under(rb_mProcess, "Waiter", rb_cThread);
7642  rb_undef_alloc_func(rb_cWaiter);
7643  rb_undef_method(CLASS_OF(rb_cWaiter), "new");
7644  rb_define_method(rb_cWaiter, "pid", detach_process_pid, 0);
7645 
7646  rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
7647  rb_undef_method(CLASS_OF(rb_cProcessStatus), "new");
7648 
7649  rb_define_method(rb_cProcessStatus, "==", pst_equal, 1);
7650  rb_define_method(rb_cProcessStatus, "&", pst_bitand, 1);
7651  rb_define_method(rb_cProcessStatus, ">>", pst_rshift, 1);
7652  rb_define_method(rb_cProcessStatus, "to_i", pst_to_i, 0);
7653  rb_define_method(rb_cProcessStatus, "to_s", pst_to_s, 0);
7654  rb_define_method(rb_cProcessStatus, "inspect", pst_inspect, 0);
7655 
7656  rb_define_method(rb_cProcessStatus, "pid", pst_pid, 0);
7657 
7658  rb_define_method(rb_cProcessStatus, "stopped?", pst_wifstopped, 0);
7659  rb_define_method(rb_cProcessStatus, "stopsig", pst_wstopsig, 0);
7660  rb_define_method(rb_cProcessStatus, "signaled?", pst_wifsignaled, 0);
7661  rb_define_method(rb_cProcessStatus, "termsig", pst_wtermsig, 0);
7662  rb_define_method(rb_cProcessStatus, "exited?", pst_wifexited, 0);
7663  rb_define_method(rb_cProcessStatus, "exitstatus", pst_wexitstatus, 0);
7664  rb_define_method(rb_cProcessStatus, "success?", pst_success_p, 0);
7665  rb_define_method(rb_cProcessStatus, "coredump?", pst_wcoredump, 0);
7666 
7667  rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
7668  rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
7669 
7670  rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, 0);
7671  rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, 0);
7672  rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
7673  rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
7674 
7675  rb_define_module_function(rb_mProcess, "getsid", proc_getsid, -1);
7676  rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
7677 
7678  rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
7679  rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
7680 
7681 #ifdef HAVE_GETPRIORITY
7682  /* see Process.setpriority */
7683  rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
7684  /* see Process.setpriority */
7685  rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
7686  /* see Process.setpriority */
7687  rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
7688 #endif
7689 
7690  rb_define_module_function(rb_mProcess, "getrlimit", proc_getrlimit, 1);
7691  rb_define_module_function(rb_mProcess, "setrlimit", proc_setrlimit, -1);
7692 #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
7693  {
7694  VALUE inf = RLIM2NUM(RLIM_INFINITY);
7695 #ifdef RLIM_SAVED_MAX
7696  {
7697  VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
7698  /* see Process.setrlimit */
7699  rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
7700  }
7701 #endif
7702  /* see Process.setrlimit */
7703  rb_define_const(rb_mProcess, "RLIM_INFINITY", inf);
7704 #ifdef RLIM_SAVED_CUR
7705  {
7706  VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
7707  /* see Process.setrlimit */
7708  rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
7709  }
7710 #endif
7711  }
7712 #ifdef RLIMIT_AS
7713  /* Maximum size of the process's virtual memory (address space) in bytes.
7714  *
7715  * see the system getrlimit(2) manual for details.
7716  */
7717  rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
7718 #endif
7719 #ifdef RLIMIT_CORE
7720  /* Maximum size of the core file.
7721  *
7722  * see the system getrlimit(2) manual for details.
7723  */
7724  rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
7725 #endif
7726 #ifdef RLIMIT_CPU
7727  /* CPU time limit in seconds.
7728  *
7729  * see the system getrlimit(2) manual for details.
7730  */
7731  rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
7732 #endif
7733 #ifdef RLIMIT_DATA
7734  /* Maximum size of the process's data segment.
7735  *
7736  * see the system getrlimit(2) manual for details.
7737  */
7738  rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
7739 #endif
7740 #ifdef RLIMIT_FSIZE
7741  /* Maximum size of files that the process may create.
7742  *
7743  * see the system getrlimit(2) manual for details.
7744  */
7745  rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
7746 #endif
7747 #ifdef RLIMIT_MEMLOCK
7748  /* Maximum number of bytes of memory that may be locked into RAM.
7749  *
7750  * see the system getrlimit(2) manual for details.
7751  */
7752  rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
7753 #endif
7754 #ifdef RLIMIT_MSGQUEUE
7755  /* Specifies the limit on the number of bytes that can be allocated
7756  * for POSIX message queues for the real user ID of the calling process.
7757  *
7758  * see the system getrlimit(2) manual for details.
7759  */
7760  rb_define_const(rb_mProcess, "RLIMIT_MSGQUEUE", INT2FIX(RLIMIT_MSGQUEUE));
7761 #endif
7762 #ifdef RLIMIT_NICE
7763  /* Specifies a ceiling to which the process's nice value can be raised.
7764  *
7765  * see the system getrlimit(2) manual for details.
7766  */
7767  rb_define_const(rb_mProcess, "RLIMIT_NICE", INT2FIX(RLIMIT_NICE));
7768 #endif
7769 #ifdef RLIMIT_NOFILE
7770  /* Specifies a value one greater than the maximum file descriptor
7771  * number that can be opened by this process.
7772  *
7773  * see the system getrlimit(2) manual for details.
7774  */
7775  rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
7776 #endif
7777 #ifdef RLIMIT_NPROC
7778  /* The maximum number of processes that can be created for the
7779  * real user ID of the calling process.
7780  *
7781  * see the system getrlimit(2) manual for details.
7782  */
7783  rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
7784 #endif
7785 #ifdef RLIMIT_RSS
7786  /* Specifies the limit (in pages) of the process's resident set.
7787  *
7788  * see the system getrlimit(2) manual for details.
7789  */
7790  rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
7791 #endif
7792 #ifdef RLIMIT_RTPRIO
7793  /* Specifies a ceiling on the real-time priority that may be set for this process.
7794  *
7795  * see the system getrlimit(2) manual for details.
7796  */
7797  rb_define_const(rb_mProcess, "RLIMIT_RTPRIO", INT2FIX(RLIMIT_RTPRIO));
7798 #endif
7799 #ifdef RLIMIT_RTTIME
7800  /* Specifies limit on CPU time this process scheduled under a real-time
7801  * scheduling policy can consume.
7802  *
7803  * see the system getrlimit(2) manual for details.
7804  */
7805  rb_define_const(rb_mProcess, "RLIMIT_RTTIME", INT2FIX(RLIMIT_RTTIME));
7806 #endif
7807 #ifdef RLIMIT_SBSIZE
7808  /* Maximum size of the socket buffer.
7809  */
7810  rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
7811 #endif
7812 #ifdef RLIMIT_SIGPENDING
7813  /* Specifies a limit on the number of signals that may be queued for
7814  * the real user ID of the calling process.
7815  *
7816  * see the system getrlimit(2) manual for details.
7817  */
7818  rb_define_const(rb_mProcess, "RLIMIT_SIGPENDING", INT2FIX(RLIMIT_SIGPENDING));
7819 #endif
7820 #ifdef RLIMIT_STACK
7821  /* Maximum size of the stack, in bytes.
7822  *
7823  * see the system getrlimit(2) manual for details.
7824  */
7825  rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
7826 #endif
7827 #endif
7828 
7829  rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
7830  rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
7831  rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
7832  rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
7833  rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
7834  rb_define_module_function(rb_mProcess, "euid=", proc_seteuid_m, 1);
7835  rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
7836  rb_define_module_function(rb_mProcess, "egid=", proc_setegid_m, 1);
7837  rb_define_module_function(rb_mProcess, "initgroups", proc_initgroups, 2);
7838  rb_define_module_function(rb_mProcess, "groups", proc_getgroups, 0);
7839  rb_define_module_function(rb_mProcess, "groups=", proc_setgroups, 1);
7840  rb_define_module_function(rb_mProcess, "maxgroups", proc_getmaxgroups, 0);
7841  rb_define_module_function(rb_mProcess, "maxgroups=", proc_setmaxgroups, 1);
7842 
7843  rb_define_module_function(rb_mProcess, "daemon", proc_daemon, -1);
7844 
7845  rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
7846 
7847 #ifdef CLOCK_REALTIME
7848  /* see Process.clock_gettime */
7849  rb_define_const(rb_mProcess, "CLOCK_REALTIME", CLOCKID2NUM(CLOCK_REALTIME));
7850 #elif defined(RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
7851  /* see Process.clock_gettime */
7852  rb_define_const(rb_mProcess, "CLOCK_REALTIME", RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME);
7853 #endif
7854 #ifdef CLOCK_MONOTONIC
7855  /* see Process.clock_gettime */
7856  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", CLOCKID2NUM(CLOCK_MONOTONIC));
7857 #elif defined(RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
7858  /* see Process.clock_gettime */
7859  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC);
7860 #endif
7861 #ifdef CLOCK_PROCESS_CPUTIME_ID
7862  /* see Process.clock_gettime */
7863  rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", CLOCKID2NUM(CLOCK_PROCESS_CPUTIME_ID));
7864 #elif defined(RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
7865  /* see Process.clock_gettime */
7866  rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID);
7867 #endif
7868 #ifdef CLOCK_THREAD_CPUTIME_ID
7869  /* see Process.clock_gettime */
7870  rb_define_const(rb_mProcess, "CLOCK_THREAD_CPUTIME_ID", CLOCKID2NUM(CLOCK_THREAD_CPUTIME_ID));
7871 #endif
7872 #ifdef CLOCK_VIRTUAL
7873  /* see Process.clock_gettime */
7874  rb_define_const(rb_mProcess, "CLOCK_VIRTUAL", CLOCKID2NUM(CLOCK_VIRTUAL));
7875 #endif
7876 #ifdef CLOCK_PROF
7877  /* see Process.clock_gettime */
7878  rb_define_const(rb_mProcess, "CLOCK_PROF", CLOCKID2NUM(CLOCK_PROF));
7879 #endif
7880 #ifdef CLOCK_REALTIME_FAST
7881  /* see Process.clock_gettime */
7882  rb_define_const(rb_mProcess, "CLOCK_REALTIME_FAST", CLOCKID2NUM(CLOCK_REALTIME_FAST));
7883 #endif
7884 #ifdef CLOCK_REALTIME_PRECISE
7885  /* see Process.clock_gettime */
7886  rb_define_const(rb_mProcess, "CLOCK_REALTIME_PRECISE", CLOCKID2NUM(CLOCK_REALTIME_PRECISE));
7887 #endif
7888 #ifdef CLOCK_REALTIME_COARSE
7889  /* see Process.clock_gettime */
7890  rb_define_const(rb_mProcess, "CLOCK_REALTIME_COARSE", CLOCKID2NUM(CLOCK_REALTIME_COARSE));
7891 #endif
7892 #ifdef CLOCK_REALTIME_ALARM
7893  /* see Process.clock_gettime */
7894  rb_define_const(rb_mProcess, "CLOCK_REALTIME_ALARM", CLOCKID2NUM(CLOCK_REALTIME_ALARM));
7895 #endif
7896 #ifdef CLOCK_MONOTONIC_FAST
7897  /* see Process.clock_gettime */
7898  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_FAST", CLOCKID2NUM(CLOCK_MONOTONIC_FAST));
7899 #endif
7900 #ifdef CLOCK_MONOTONIC_PRECISE
7901  /* see Process.clock_gettime */
7902  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_PRECISE", CLOCKID2NUM(CLOCK_MONOTONIC_PRECISE));
7903 #endif
7904 #ifdef CLOCK_MONOTONIC_RAW
7905  /* see Process.clock_gettime */
7906  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_RAW", CLOCKID2NUM(CLOCK_MONOTONIC_RAW));
7907 #endif
7908 #ifdef CLOCK_MONOTONIC_RAW_APPROX
7909  /* see Process.clock_gettime */
7910  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_RAW_APPROX", CLOCKID2NUM(CLOCK_MONOTONIC_RAW_APPROX));
7911 #endif
7912 #ifdef CLOCK_MONOTONIC_COARSE
7913  /* see Process.clock_gettime */
7914  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_COARSE", CLOCKID2NUM(CLOCK_MONOTONIC_COARSE));
7915 #endif
7916 #ifdef CLOCK_BOOTTIME
7917  /* see Process.clock_gettime */
7918  rb_define_const(rb_mProcess, "CLOCK_BOOTTIME", CLOCKID2NUM(CLOCK_BOOTTIME));
7919 #endif
7920 #ifdef CLOCK_BOOTTIME_ALARM
7921  /* see Process.clock_gettime */
7922  rb_define_const(rb_mProcess, "CLOCK_BOOTTIME_ALARM", CLOCKID2NUM(CLOCK_BOOTTIME_ALARM));
7923 #endif
7924 #ifdef CLOCK_UPTIME
7925  /* see Process.clock_gettime */
7926  rb_define_const(rb_mProcess, "CLOCK_UPTIME", CLOCKID2NUM(CLOCK_UPTIME));
7927 #endif
7928 #ifdef CLOCK_UPTIME_FAST
7929  /* see Process.clock_gettime */
7930  rb_define_const(rb_mProcess, "CLOCK_UPTIME_FAST", CLOCKID2NUM(CLOCK_UPTIME_FAST));
7931 #endif
7932 #ifdef CLOCK_UPTIME_PRECISE
7933  /* see Process.clock_gettime */
7934  rb_define_const(rb_mProcess, "CLOCK_UPTIME_PRECISE", CLOCKID2NUM(CLOCK_UPTIME_PRECISE));
7935 #endif
7936 #ifdef CLOCK_UPTIME_RAW
7937  /* see Process.clock_gettime */
7938  rb_define_const(rb_mProcess, "CLOCK_UPTIME_RAW", CLOCKID2NUM(CLOCK_UPTIME_RAW));
7939 #endif
7940 #ifdef CLOCK_UPTIME_RAW_APPROX
7941  /* see Process.clock_gettime */
7942  rb_define_const(rb_mProcess, "CLOCK_UPTIME_RAW_APPROX", CLOCKID2NUM(CLOCK_UPTIME_RAW_APPROX));
7943 #endif
7944 #ifdef CLOCK_SECOND
7945  /* see Process.clock_gettime */
7946  rb_define_const(rb_mProcess, "CLOCK_SECOND", CLOCKID2NUM(CLOCK_SECOND));
7947 #endif
7948  rb_define_module_function(rb_mProcess, "clock_gettime", rb_clock_gettime, -1);
7949  rb_define_module_function(rb_mProcess, "clock_getres", rb_clock_getres, -1);
7950 
7951 #if defined(HAVE_TIMES) || defined(_WIN32)
7952  rb_cProcessTms = rb_struct_define_under(rb_mProcess, "Tms", "utime", "stime", "cutime", "cstime", NULL);
7953  rb_define_const(rb_cStruct, "Tms", rb_cProcessTms); /* for the backward compatibility */
7954 #endif
7955 
7956  SAVED_USER_ID = geteuid();
7957  SAVED_GROUP_ID = getegid();
7958 
7959  rb_mProcUID = rb_define_module_under(rb_mProcess, "UID");
7960  rb_mProcGID = rb_define_module_under(rb_mProcess, "GID");
7961 
7962  rb_define_module_function(rb_mProcUID, "rid", proc_getuid, 0);
7963  rb_define_module_function(rb_mProcGID, "rid", proc_getgid, 0);
7964  rb_define_module_function(rb_mProcUID, "eid", proc_geteuid, 0);
7965  rb_define_module_function(rb_mProcGID, "eid", proc_getegid, 0);
7966  rb_define_module_function(rb_mProcUID, "change_privilege", p_uid_change_privilege, 1);
7967  rb_define_module_function(rb_mProcGID, "change_privilege", p_gid_change_privilege, 1);
7968  rb_define_module_function(rb_mProcUID, "grant_privilege", p_uid_grant_privilege, 1);
7969  rb_define_module_function(rb_mProcGID, "grant_privilege", p_gid_grant_privilege, 1);
7970  rb_define_alias(rb_singleton_class(rb_mProcUID), "eid=", "grant_privilege");
7971  rb_define_alias(rb_singleton_class(rb_mProcGID), "eid=", "grant_privilege");
7972  rb_define_module_function(rb_mProcUID, "re_exchange", p_uid_exchange, 0);
7973  rb_define_module_function(rb_mProcGID, "re_exchange", p_gid_exchange, 0);
7974  rb_define_module_function(rb_mProcUID, "re_exchangeable?", p_uid_exchangeable, 0);
7975  rb_define_module_function(rb_mProcGID, "re_exchangeable?", p_gid_exchangeable, 0);
7976  rb_define_module_function(rb_mProcUID, "sid_available?", p_uid_have_saved_id, 0);
7977  rb_define_module_function(rb_mProcGID, "sid_available?", p_gid_have_saved_id, 0);
7978  rb_define_module_function(rb_mProcUID, "switch", p_uid_switch, 0);
7979  rb_define_module_function(rb_mProcGID, "switch", p_gid_switch, 0);
7980 #ifdef p_uid_from_name
7981  rb_define_module_function(rb_mProcUID, "from_name", p_uid_from_name, 1);
7982 #endif
7983 #ifdef p_gid_from_name
7984  rb_define_module_function(rb_mProcGID, "from_name", p_gid_from_name, 1);
7985 #endif
7986 
7987  rb_mProcID_Syscall = rb_define_module_under(rb_mProcess, "Sys");
7988 
7989  rb_define_module_function(rb_mProcID_Syscall, "getuid", proc_getuid, 0);
7990  rb_define_module_function(rb_mProcID_Syscall, "geteuid", proc_geteuid, 0);
7991  rb_define_module_function(rb_mProcID_Syscall, "getgid", proc_getgid, 0);
7992  rb_define_module_function(rb_mProcID_Syscall, "getegid", proc_getegid, 0);
7993 
7994  rb_define_module_function(rb_mProcID_Syscall, "setuid", p_sys_setuid, 1);
7995  rb_define_module_function(rb_mProcID_Syscall, "setgid", p_sys_setgid, 1);
7996 
7997  rb_define_module_function(rb_mProcID_Syscall, "setruid", p_sys_setruid, 1);
7998  rb_define_module_function(rb_mProcID_Syscall, "setrgid", p_sys_setrgid, 1);
7999 
8000  rb_define_module_function(rb_mProcID_Syscall, "seteuid", p_sys_seteuid, 1);
8001  rb_define_module_function(rb_mProcID_Syscall, "setegid", p_sys_setegid, 1);
8002 
8003  rb_define_module_function(rb_mProcID_Syscall, "setreuid", p_sys_setreuid, 2);
8004  rb_define_module_function(rb_mProcID_Syscall, "setregid", p_sys_setregid, 2);
8005 
8006  rb_define_module_function(rb_mProcID_Syscall, "setresuid", p_sys_setresuid, 3);
8007  rb_define_module_function(rb_mProcID_Syscall, "setresgid", p_sys_setresgid, 3);
8008  rb_define_module_function(rb_mProcID_Syscall, "issetugid", p_sys_issetugid, 0);
8009 }
8010 
8011 void
8013 {
8014  id_in = rb_intern("in");
8015  id_out = rb_intern("out");
8016  id_err = rb_intern("err");
8017  id_pid = rb_intern("pid");
8018  id_uid = rb_intern("uid");
8019  id_gid = rb_intern("gid");
8020  id_close = rb_intern("close");
8021  id_child = rb_intern("child");
8022 #ifdef HAVE_SETPGID
8023  id_pgroup = rb_intern("pgroup");
8024 #endif
8025 #ifdef _WIN32
8026  id_new_pgroup = rb_intern("new_pgroup");
8027 #endif
8028  id_unsetenv_others = rb_intern("unsetenv_others");
8029  id_chdir = rb_intern("chdir");
8030  id_umask = rb_intern("umask");
8031  id_close_others = rb_intern("close_others");
8032  id_ENV = rb_intern("ENV");
8033  id_nanosecond = rb_intern("nanosecond");
8034  id_microsecond = rb_intern("microsecond");
8035  id_millisecond = rb_intern("millisecond");
8036  id_second = rb_intern("second");
8037  id_float_microsecond = rb_intern("float_microsecond");
8038  id_float_millisecond = rb_intern("float_millisecond");
8039  id_float_second = rb_intern("float_second");
8040  id_GETTIMEOFDAY_BASED_CLOCK_REALTIME = rb_intern("GETTIMEOFDAY_BASED_CLOCK_REALTIME");
8041  id_TIME_BASED_CLOCK_REALTIME = rb_intern("TIME_BASED_CLOCK_REALTIME");
8042 #ifdef HAVE_TIMES
8043  id_TIMES_BASED_CLOCK_MONOTONIC = rb_intern("TIMES_BASED_CLOCK_MONOTONIC");
8044  id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID");
8045 #endif
8046 #ifdef RUSAGE_SELF
8047  id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID");
8048 #endif
8049  id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID");
8050 #ifdef __APPLE__
8051  id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC = rb_intern("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC");
8052 #endif
8053  id_hertz = rb_intern("hertz");
8054 
8055  InitVM(process);
8056 }
VALUE fd_dup2
Definition: internal.h:1550
#define p_sys_setreuid
Definition: process.c:5292
#define proc_setegid_m
Definition: process.c:6473
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1469
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2299
void rb_syswait(rb_pid_t pid)
Definition: process.c:3891
void rb_gc(void)
Definition: gc.c:6727
#define WNOHANG
Definition: win32.h:128
#define T_SYMBOL
Definition: ruby.h:508
#define proc_setpgid
Definition: process.c:4524
#define NUM2UIDT(v)
Definition: ruby.h:332
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:915
#define RUBY_VM_CHECK_INTS(th)
Definition: vm_core.h:1627
#define EXPORT_STR(str)
Definition: process.c:1383
#define redirect_close(fd)
Definition: process.c:401
RUBY_EXTERN VALUE rb_cData
Definition: ruby.h:1902
size_t buflen
Definition: process.c:3971
void rb_thread_atfork(void)
Definition: thread.c:4186
#define OBJ2UID(id)
Definition: process.c:199
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:992
void rb_warn(const char *fmt,...)
Definition: error.c:246
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:362
void rb_bug(const char *fmt,...)
Definition: error.c:521
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1215
#define F_SETFD
Definition: win32.h:583
VALUE execarg
Definition: process.c:3968
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define WTERMSIG(w)
Definition: process.c:119
int gettimeofday(struct timeval *, struct timezone *)
Definition: win32.c:4596
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:2391
#define FALSE
Definition: nkf.h:174
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
int ioctl(int, int,...)
Definition: win32.c:2756
#define proc_setpriority
Definition: process.c:4680
size_t strlen(const char *)
#define INT2NUM(x)
Definition: ruby.h:1538
unsigned int unsigned_clock_t
Definition: process.c:250
struct spawn_args::@92 errmsg
void rb_update_max_fd(int fd)
Definition: io.c:191
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2268
#define T_FIXNUM
Definition: ruby.h:503
Definition: st.h:79
long timetick_int_t
Definition: process.c:6961
#define proc_getpriority
Definition: process.c:4649
Definition: st.h:99
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:648
#define p_sys_setrgid
Definition: process.c:5621
#define NUM2INT(x)
Definition: ruby.h:684
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1438
#define NUM2UINT(x)
Definition: ruby.h:685
#define PST2INT(st)
Definition: process.c:518
CONSTFUNC(static timetick_int_t gcd_timetick_int(timetick_int_t, timetick_int_t))
rb_uid_t getuid(void)
Definition: win32.c:2710
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:675
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:2397
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:835
#define RUBY_TIME_BASED_CLOCK_REALTIME
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:5262
unsigned umask_given
Definition: internal.h:1534
#define TIMETICK_INT_MAX
Definition: process.c:6963
#define NUM2PIDT(v)
Definition: ruby.h:326
#define FilePathValue(v)
Definition: ruby.h:594
VALUE rb_mProcGID
Definition: process.c:7584
size_t len
Definition: process.c:2063
#define CLASS_OF(v)
Definition: ruby.h:453
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:257
long tms_stime
Definition: win32.h:713
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
#define WIFEXITED(w)
Definition: process.c:107
#define InitVM(ext)
Definition: ruby.h:2164
#define proc_getgroups
Definition: process.c:5877
#define PIDT2NUM(v)
Definition: ruby.h:323
VALUE rb_f_exit(int argc, const VALUE *argv)
Definition: process.c:3838
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:821
#define st_foreach
Definition: regint.h:186
int rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3021
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2293
#define FINISH_GETPWNAM
Definition: process.c:197
#define Qtrue
Definition: ruby.h:437
VALUE rlimit_limits
Definition: internal.h:1545
#define WIFSTOPPED(w)
Definition: process.c:113
unsigned uid_given
Definition: internal.h:1542
Definition: io.h:62
mode_t perm
Definition: process.c:2321
#define proc_setpgrp
Definition: process.c:4474
#define CLOCK_MONOTONIC
Definition: win32.h:134
int rb_env_path_tainted(void)
Definition: hash.c:3424
Definition: st.h:99
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1183
#define before_fork_ruby()
Definition: process.c:1207
const int id
Definition: nkf.c:209
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Definition: thread.c:1422
unsigned unsetenv_others_given
Definition: internal.h:1535
#define P_NOWAIT
Definition: process.c:1393
int close_others_maxhint
Definition: internal.h:1549
#define rb_check_arity
Definition: intern.h:298
#define UNREACHABLE
Definition: ruby.h:46
VALUE rb_mProcID_Syscall
Definition: process.c:7585
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:3022
VALUE rb_struct_new(VALUE,...)
Definition: struct.c:605
int rb_proc_exec(const char *str)
Definition: process.c:1322
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
int fcntl(int, int,...)
Definition: win32.c:4297
#define RB_SPECIAL_CONST_P(x)
Definition: ruby.h:1241
#define p_sys_setresuid
Definition: process.c:5322
#define redirect_cloexec_dup2(oldfd, newfd)
Definition: process.c:400
struct st_table * rb_hash_tbl_raw(VALUE hash)
Definition: hash.c:482
#define p_sys_seteuid
Definition: process.c:5263
rb_pid_t rb_fork_ruby(int *status)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
rb_pid_t rb_w32_uaspawn_flags(int, const char *, char *const *, DWORD)
Definition: win32.c:1502
void(* sig_t)(int)
Definition: process.c:257
void rb_str_set_len(VALUE, long)
Definition: string.c:2627
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:1471
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
#define Check_Type(v, t)
Definition: ruby.h:562
#define proc_daemon
Definition: process.c:6086
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1210
rb_pid_t rb_waitpid(rb_pid_t pid, int *st, int flags)
Definition: process.c:902
rb_pid_t pid
Definition: process.c:863
#define RB_GC_GUARD(v)
Definition: ruby.h:552
#define rb_f_fork
Definition: process.c:3729
#define T_HASH
Definition: ruby.h:499
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:2121
#define EXPORT_DUP(str)
Definition: process.c:1384
#define after_fork_ruby()
Definition: process.c:1208
#define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
#define DATA_PTR(dta)
Definition: ruby.h:1106
#define proc_initgroups
Definition: process.c:5957
VALUE env_modification
Definition: internal.h:1554
#define MUL_OVERFLOW_TIMETICK_P(a, b)
Definition: process.c:6965
VALUE last_status
Definition: vm_core.h:792
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
int rb_pipe(int *pipes)
Definition: io.c:6009
void rb_gc_mark(VALUE ptr)
Definition: gc.c:4464
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:853
#define T_ARRAY
Definition: ruby.h:498
#define st_delete
Definition: regint.h:182
#define OBJ2GID1(id)
Definition: process.c:241
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1745
time_t tv_sec
Definition: missing.h:54
char * ptr
Definition: process.c:3970
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1035
#define proc_getpgrp
Definition: process.c:4446
#define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
#define FIXNUM_P(f)
Definition: ruby.h:365
#define EXIT_SUCCESS
Definition: process.c:40
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell)
Definition: process.c:2257
VALUE rb_str_tmp_new(long)
Definition: string.c:1310
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1533
#define GetOpenFile(obj, fp)
Definition: io.h:120
VALUE envp_str
Definition: internal.h:1529
VALUE rb_struct_define_under(VALUE, const char *,...)
Definition: struct.c:425
void rb_thread_start_timer_thread(void)
Definition: thread.c:4084
#define p_sys_setegid
Definition: process.c:5643
VALUE rb_thread_local_aref(VALUE, ID)
Definition: thread.c:3013
#define GET_THREAD()
Definition: vm_core.h:1583
VALUE rb_eArgError
Definition: error.c:802
VALUE rb_f_kill(int, const VALUE *)
Definition: signal.c:407
time_t tv_sec
Definition: missing.h:61
VALUE rb_str_buf_cat(VALUE, const char *, long)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1851
unsigned unsetenv_others_do
Definition: internal.h:1536
int clockid_t
Definition: win32.h:132
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1689
#define preserving_errno(stmts)
Definition: process.c:153
rb_gid_t getegid(void)
Definition: win32.c:2731
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
#define fail()
VALUE rb_last_status_get(void)
Definition: process.c:479
#define MEMZERO(p, type, n)
Definition: ruby.h:1660
#define OBJ2UID1(id)
Definition: process.c:198
unsigned long long uint64_t
Definition: sha2.h:102
#define proc_setsid
Definition: process.c:4613
void rb_thread_sleep(int)
Definition: thread.c:1243
int oflags
Definition: process.c:2320
rb_gid_t gid
Definition: internal.h:1548
#define ALWAYS_NEED_ENVP
Definition: process.c:293
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false
Definition: object.c:126
void rb_execarg_parent_start(VALUE execarg_obj)
Definition: process.c:2457
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1616
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2979
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:232
#define val
VALUE rb_f_exec(int argc, const VALUE *argv)
Definition: process.c:2596
long tv_usec
Definition: missing.h:55
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
void rb_async_bug_errno(const char *mesg, int errno_arg)
Definition: error.c:573
IUnknown DWORD
Definition: win32ole.c:32
#define proc_getmaxgroups
Definition: process.c:5977
const char * ruby_signal_name(int)
Definition: signal.c:262
VALUE rb_io_check_io(VALUE io)
Definition: io.c:664
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_ary_new(void)
Definition: array.c:499
VALUE rb_str_buf_cat2(VALUE, const char *)
#define dp(v)
Definition: vm_debug.h:21
struct rb_execarg::@81::@83 cmd
#define p_gid_from_name
Definition: process.c:245
rb_uid_t uid
Definition: internal.h:1547
#define NIL_P(v)
Definition: ruby.h:451
long tv_nsec
Definition: missing.h:62
#define TIMETICK_INT2NUM(v)
Definition: process.c:6964
int fd
Definition: io.h:64
rb_pid_t pgroup_pgid
Definition: internal.h:1544
rb_pid_t rb_fork_async_signal_safe(int *status, int(*chfunc)(void *, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen)
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2691
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:815
#define TOUPPER(c)
Definition: ruby.h:2153
void rb_notimplement(void)
Definition: error.c:2330
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:187
int setegid(pid_t pid)
struct rb_execarg::@81::@82 sh
void rb_thread_stop_timer_thread(void)
Definition: thread.c:4070
#define Qfalse
Definition: ruby.h:436
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1657
mode_t umask(mode_t mask)
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:290
#define proc_getrlimit
Definition: process.c:4937
#define RUBY_UBF_PROCESS
Definition: intern.h:878
void rb_exit(int status)
Definition: process.c:3783
#define T_BIGNUM
Definition: ruby.h:501
int seteuid(pid_t pid)
#define ISUPPER(c)
Definition: ruby.h:2146
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1661
union rb_execarg::@81 invoke
void ruby_stop(int ex)
Calls ruby_cleanup() and exits the process.
Definition: eval.c:256
#define rb_str_new2
Definition: intern.h:835
int err
Definition: win32.c:135
void InitVM_process(void)
Definition: process.c:7594
void rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
Definition: eval_error.c:167
#define ISLOWER(c)
Definition: ruby.h:2147
#define F_GETFD
Definition: win32.h:582
#define ALLOCV_END(v)
Definition: ruby.h:1658
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
int rb_exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3150
#define numberof(array)
Definition: etc.c:618
rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
Definition: process.c:4006
#define WSTOPSIG
Definition: process.c:122
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2644
void rb_sys_fail(const char *mesg)
Definition: error.c:2403
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2292
#define id_status
Definition: process.c:285
VALUE rb_thread_local_aset(VALUE, ID, VALUE)
Definition: thread.c:3148
VALUE rb_clock_gettime(int argc, VALUE *argv)
Definition: process.c:7284
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1758
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:1669
#define RSTRING_LEN(str)
Definition: ruby.h:971
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1731
VALUE rb_yield(VALUE)
Definition: vm_eval.c:973
timetick_int_t giga_count
Definition: process.c:7016
#define proc_getpgid
Definition: process.c:4499
unsigned close_others_given
Definition: internal.h:1537
int rb_during_gc(void)
Definition: gc.c:6735
#define p_sys_setruid
Definition: process.c:5241
int errno
#define TRUE
Definition: nkf.h:175
#define proc_seteuid_m
Definition: process.c:6343
#define CLOCK_REALTIME
Definition: win32.h:133
#define p_sys_setresgid
Definition: process.c:5701
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
#define parent_redirect_close(fd)
Definition: process.c:403
#define proc_setgid
Definition: process.c:5787
#define EXIT_FAILURE
Definition: process.c:43
#define RHASH_SIZE(hsh)
Definition: fbuffer.h:8
VALUE rb_hash_new(void)
Definition: hash.c:424
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2054
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1315
VALUE redirect_fds
Definition: internal.h:1528
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:722
#define ENVMATCH(n1, n2)
Definition: process.c:1942
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
unsigned close_others_do
Definition: internal.h:1538
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:639
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
#define PATH_ENV
Definition: defines.h:306
int setgid(rb_gid_t)
Definition: win32.c:2745
VALUE tied_io_for_writing
Definition: io.h:73
VALUE path_env
Definition: internal.h:1555
#define OBJ2GID(id)
Definition: process.c:242
#define Qnil
Definition: ruby.h:438
unsigned new_pgroup_given
Definition: internal.h:1540
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:615
const char * ptr
Definition: process.c:2062
#define mode_t
Definition: win32.h:119
#define p_sys_setregid
Definition: process.c:5672
unsigned long VALUE
Definition: ruby.h:85
VALUE rb_mProcUID
Definition: process.c:7583
rb_uid_t geteuid(void)
Definition: win32.c:2717
RUBY_EXTERN VALUE rb_cThread
Definition: ruby.h:1930
void rb_execarg_parent_end(VALUE execarg_obj)
Definition: process.c:2496
rb_pid_t rb_w32_uaspawn(int, const char *, char *const *)
Definition: win32.c:1516
VALUE rb_eNotImpError
Definition: error.c:811
VALUE rb_eSecurityError
Definition: error.c:810
#define CHILD_ERRMSG_BUFLEN
const char * rb_class2name(VALUE)
Definition: variable.c:450
char * strchr(char *, char)
#define FIX2INT(x)
Definition: ruby.h:686
VALUE argv_buf
Definition: internal.h:1525
#define NUM2GIDT(v)
Definition: ruby.h:338
VALUE rb_io_puts(int, const VALUE *, VALUE)
Definition: io.c:7399
#define rb_ary_new3
Definition: intern.h:91
int clock_gettime(clockid_t, struct timespec *)
Definition: win32.c:4608
#define p_sys_setgid
Definition: process.c:5599
#define EPERM
Definition: _sdbm.c:93
mode_t umask_mask
Definition: internal.h:1546
unsigned pgroup_given
Definition: internal.h:1533
#define proc_setmaxgroups
Definition: process.c:6009
VALUE rb_str_new_cstr(const char *)
Definition: string.c:771
long tms_utime
Definition: win32.h:712
#define WIFSIGNALED(w)
Definition: process.c:110
VALUE flags
Definition: internal.h:918
#define RARRAY_LENINT(ary)
Definition: ruby.h:1020
#define NSIG
Definition: vm_core.h:94
VALUE fd_dup2_child
Definition: internal.h:1553
VALUE rb_str_dup(VALUE)
Definition: string.c:1488
#define PREPARE_GETGRNAM
Definition: process.c:239
#define proc_setuid
Definition: process.c:5381
int rb_reserved_fd_p(int fd)
#define ERRMSG(str)
Definition: process.c:2621
VALUE rb_mProcess
Definition: process.c:7582
#define my_getcwd()
Definition: util.h:73
register unsigned int len
Definition: zonetab.h:51
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:790
#define StringValueCStr(v)
Definition: ruby.h:571
long tms_cstime
Definition: win32.h:715
Definition: win32.h:711
VALUE fd_open
Definition: internal.h:1552
#define endpwent()
#define RSTRING_PTR(str)
Definition: ruby.h:975
void rb_thread_wait_for(struct timeval)
Definition: thread.c:1205
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:1928
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
Definition: process.c:3900
#define RARRAY_ASET(a, i, v)
Definition: ruby.h:1034
#define try_with_sh(prog, argv, envp)
Definition: process.c:1238
RUBY_EXTERN VALUE rb_stderr
Definition: ruby.h:1971
int size
Definition: encoding.c:57
#define INT2FIX(i)
Definition: ruby.h:232
#define UNLIMITED_ARGUMENTS
Definition: intern.h:44
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:485
int utime(const char *filename, const struct utimbuf *times)
int rb_safe_level(void)
Definition: safe.c:35
VALUE dup2_tmpbuf
Definition: internal.h:1531
RUBY_EXTERN VALUE rb_cStruct
Definition: ruby.h:1928
VALUE fd_close
Definition: internal.h:1551
unsigned gid_given
Definition: internal.h:1543
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
#define redirect_dup2(oldfd, newfd)
Definition: process.c:398
VALUE envp_buf
Definition: internal.h:1530
int getrusage(int who, struct rusage *usage)
VALUE rb_eRuntimeError
Definition: error.c:800
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:651
#define p_sys_setuid
Definition: process.c:5219
rb_pid_t rb_spawn(int argc, const VALUE *argv)
Definition: process.c:4012
#define WEXITSTATUS(w)
Definition: process.c:116
#define RARRAY_PTR(a)
Definition: ruby.h:1041
#define FD_CLOEXEC
Definition: win32.h:589
VALUE rb_eSystemExit
Definition: error.c:795
#define MAXPATHLEN
Definition: process.c:59
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1492
unsigned chdir_given
Definition: internal.h:1539
#define RHASH_TBL_RAW(h)
Definition: internal.h:1268
#define GIDT2NUM(v)
Definition: ruby.h:335
void rb_thread_reset_timer_thread(void)
Definition: thread.c:4078
VALUE rb_check_string_type(VALUE)
Definition: string.c:2246
ID ruby_static_id_status
Definition: eval.c:27
int clock_getres(clockid_t, struct timespec *)
Definition: win32.c:4646
#define LONG2FIX(i)
Definition: ruby.h:234
#define ARGVSTR2ARGV(argv_str)
Definition: internal.h:1564
#define RTEST(v)
Definition: ruby.h:450
void rb_thread_check_ints(void)
Definition: thread.c:1219
#define T_STRING
Definition: ruby.h:496
#define rb_intern(str)
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:2170
VALUE chdir_dir
Definition: internal.h:1556
#define proc_setrlimit
Definition: process.c:5013
size_t rb_str_capacity(VALUE str)
Definition: string.c:675
#define rb_proc_times
Definition: process.c:6951
#define EWOULDBLOCK
Definition: rubysocket.h:128
#define T_FILE
Definition: ruby.h:502
#define RB_BUILTIN_TYPE(x)
Definition: ruby.h:517
#define parent_redirect_open(pathname, flags, perm)
Definition: process.c:402
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1930
void rb_last_status_clear(void)
Definition: process.c:494
#define SafeStringValue(v)
Definition: ruby.h:574
#define TIMETICK_INT_MIN
Definition: process.c:6962
#define st_insert
Definition: regint.h:184
#define DIV(n, d)
Definition: process.c:7063
rb_execution_context_t ec
Definition: vm_core.h:790
const char * name
Definition: nkf.c:208
#define ID2SYM(x)
Definition: ruby.h:383
#define NUM2MODET(v)
Definition: ruby.h:341
#define redirect_dup(oldfd)
Definition: process.c:397
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1158
#define RB_MAX_GROUPS
Definition: internal.h:1514
#define tmpbuf(n, size)
Definition: array.c:5055
#define PREPARE_GETPWNAM
Definition: process.c:196
int rb_cloexec_dup(int oldfd)
Definition: io.c:283
#define UIDT2NUM(v)
Definition: ruby.h:329
unsigned use_shell
Definition: internal.h:1532
VALUE rb_env_clear(void)
Definition: hash.c:4004
rb_gid_t getgid(void)
Definition: win32.c:2724
#define proc_setgroups
Definition: process.c:5926
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1134
void void xfree(void *)
#define proc_getsid
Definition: process.c:4555
long tms_cutime
Definition: win32.h:714
int flags
Definition: process.c:864
#define RHASH_EMPTY_P(h)
Definition: ruby.h:1060
VALUE rb_define_module(const char *name)
Definition: class.c:768
#define p_uid_from_name
Definition: process.c:202
int32_t count
Definition: process.c:7017
#define ARGVSTR2ARGC(argv_str)
Definition: internal.h:1563
VALUE rb_str_buf_new(long)
Definition: string.c:1282
unsigned new_pgroup_flag
Definition: internal.h:1541
#define SYMBOL_P(x)
Definition: ruby.h:382
#define mod(x, y)
Definition: date_strftime.c:28
VALUE rb_detach_process(rb_pid_t pid)
Definition: process.c:1097
#define env
VALUE fname
Definition: process.c:2319
#define NULL
Definition: _sdbm.c:102
#define Qundef
Definition: ruby.h:439
rb_pid_t rb_w32_uspawn(int, const char *, const char *)
Definition: win32.c:1417
#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max)
Definition: bigdecimal.c:35
#define p_sys_issetugid
Definition: process.c:5729
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2409
VALUE rb_execarg_init(int argc, const VALUE *orig_argv, int accept_shell, VALUE execarg_obj)
Definition: process.c:2276
VALUE rb_thread_create(VALUE(*)(ANYARGS), void *)
Definition: thread.c:831
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
void ruby_setenv(const char *name, const char *value)
Definition: hash.c:3497
#define NOFILE
Definition: io.c:75
int setuid(rb_uid_t)
Definition: win32.c:2738
VALUE rb_clock_getres(int argc, VALUE *argv)
Definition: process.c:7479
#define FINISH_GETGRNAM
Definition: process.c:240
rb_pid_t waitpid(rb_pid_t, int *, int)
Definition: win32.c:4480
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3084
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1224
#define redirect_cloexec_dup(oldfd)
Definition: process.c:399
char ** argv
Definition: ruby.c:188
#define DBL2NUM(dbl)
Definition: ruby.h:934
#define StringValue(v)
Definition: ruby.h:569
#define RUBY_UBF_IO
Definition: intern.h:877
void Init_process(void)
Definition: process.c:8012
#define rb_sym2str(sym)
Definition: console.c:107
VALUE rb_f_abort(int argc, const VALUE *argv)
Definition: process.c:3866
void rb_thread_sleep_forever(void)
Definition: thread.c:1160
VALUE rb_str_new(const char *, long)
Definition: string.c:737
#define dln_find_exe_r
Definition: win32.c:82
int * st
Definition: process.c:865