Ruby  2.4.2p198(2017-09-14revision59899)
process.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  process.c -
4 
5  $Author: nagachika $
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 
262 #ifdef HAVE_SETPGID
263 static ID id_pgroup;
264 #endif
265 #ifdef _WIN32
266 static ID id_new_pgroup;
267 #endif
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
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
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 
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();
489  rb_ivar_set(th->last_status, id_status, INT2FIX(status));
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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;
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
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
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
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 
1077 
1078 static VALUE
1080 {
1081  return rb_thread_local_aref(thread, id_pid);
1082 }
1083 
1084 static VALUE
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
1155 {
1156  return rb_detach_process(NUM2PIDT(pid));
1157 }
1158 
1159 /* This function should be async-signal-safe. Actually it is. */
1160 static void
1162 {
1163 }
1164 
1165 static 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
1182 {
1185 }
1186 
1187 /* This function should be async-signal-safe. Actually it is. */
1188 static void
1190 {
1191 }
1192 
1193 static void
1195 {
1198 }
1199 
1200 static void
1202 {
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);
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 
1364  "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
1465 {
1466  RBASIC_CLEAR_CLASS(obj);
1467  return obj;
1468 }
1469 
1470 static VALUE
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(v, T_FILE, "IO", "to_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
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
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
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
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
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;
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
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
1974 {
1975  VALUE env[2];
1976 
1977  env[0] = hide_obj(rb_ary_new());
1978  env[1] = Qfalse;
1980  *path = env[1];
1981 
1982  return env[0];
1983 }
1984 
1985 static VALUE
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
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
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
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(envtbl, T_HASH, "Hash", "to_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
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
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
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) {
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)
3637 {
3638  rb_pid_t pid;
3639  int try_gc = 1;
3640 
3641  while (1) {
3642  prefork();
3643  before_fork_ruby();
3644  pid = fork();
3645  if (pid == 0) /* fork succeed, child process */
3646  return pid;
3648  if (0 < pid) /* fork succeed, parent process */
3649  return pid;
3650  /* fork failed */
3651  if (handle_fork_error(status, NULL, &try_gc))
3652  return -1;
3653  }
3654 }
3655 
3656 rb_pid_t
3657 rb_fork_ruby(int *status)
3658 {
3659  rb_pid_t pid;
3660 
3661  if (status) *status = 0;
3662 
3663  pid = retry_fork_ruby(status);
3664  if (pid < 0)
3665  return pid;
3666  if (!pid) {
3667  after_fork_ruby();
3668  }
3669  return pid;
3670 }
3671 
3672 #endif
3673 
3674 #if defined(HAVE_WORKING_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
3675 /*
3676  * call-seq:
3677  * Kernel.fork [{ block }] -> integer or nil
3678  * Process.fork [{ block }] -> integer or nil
3679  *
3680  * Creates a subprocess. If a block is specified, that block is run
3681  * in the subprocess, and the subprocess terminates with a status of
3682  * zero. Otherwise, the +fork+ call returns twice, once in
3683  * the parent, returning the process ID of the child, and once in
3684  * the child, returning _nil_. The child process can exit using
3685  * <code>Kernel.exit!</code> to avoid running any
3686  * <code>at_exit</code> functions. The parent process should
3687  * use <code>Process.wait</code> to collect the termination statuses
3688  * of its children or use <code>Process.detach</code> to register
3689  * disinterest in their status; otherwise, the operating system
3690  * may accumulate zombie processes.
3691  *
3692  * The thread calling fork is the only thread in the created child process.
3693  * fork doesn't copy other threads.
3694  *
3695  * If fork is not usable, Process.respond_to?(:fork) returns false.
3696  *
3697  * Note that fork(2) is not available on some platforms like Windows and NetBSD 4.
3698  * Therefore you should use spawn() instead of fork().
3699  */
3700 
3701 static VALUE
3702 rb_f_fork(VALUE obj)
3703 {
3704  rb_pid_t pid;
3705 
3706  switch (pid = rb_fork_ruby(NULL)) {
3707  case 0:
3708  rb_thread_atfork();
3709  if (rb_block_given_p()) {
3710  int status;
3711  rb_protect(rb_yield, Qundef, &status);
3712  ruby_stop(status);
3713  }
3714  return Qnil;
3715 
3716  case -1:
3717  rb_sys_fail("fork(2)");
3718  return Qnil;
3719 
3720  default:
3721  return PIDT2NUM(pid);
3722  }
3723 }
3724 #else
3725 #define rb_f_fork rb_f_notimplement
3726 #endif
3727 
3728 static int
3730 {
3731  int istatus;
3732 
3733  switch (status) {
3734  case Qtrue:
3735  istatus = EXIT_SUCCESS;
3736  break;
3737  case Qfalse:
3738  istatus = EXIT_FAILURE;
3739  break;
3740  default:
3741  istatus = NUM2INT(status);
3742 #if EXIT_SUCCESS != 0
3743  if (istatus == 0)
3744  istatus = EXIT_SUCCESS;
3745 #endif
3746  break;
3747  }
3748  return istatus;
3749 }
3750 
3751 /*
3752  * call-seq:
3753  * Process.exit!(status=false)
3754  *
3755  * Exits the process immediately. No exit handlers are
3756  * run. <em>status</em> is returned to the underlying system as the
3757  * exit status.
3758  *
3759  * Process.exit!(true)
3760  */
3761 
3762 static VALUE
3764 {
3765  int istatus;
3766 
3767  if (rb_check_arity(argc, 0, 1) == 1) {
3768  istatus = exit_status_code(argv[0]);
3769  }
3770  else {
3771  istatus = EXIT_FAILURE;
3772  }
3773  _exit(istatus);
3774 
3775  UNREACHABLE;
3776 }
3777 
3778 void
3779 rb_exit(int status)
3780 {
3781  if (GET_THREAD()->tag) {
3782  VALUE args[2];
3783 
3784  args[0] = INT2NUM(status);
3785  args[1] = rb_str_new2("exit");
3787  }
3788  ruby_stop(status);
3789 }
3790 
3791 
3792 /*
3793  * call-seq:
3794  * exit(status=true)
3795  * Kernel::exit(status=true)
3796  * Process::exit(status=true)
3797  *
3798  * Initiates the termination of the Ruby script by raising the
3799  * <code>SystemExit</code> exception. This exception may be caught. The
3800  * optional parameter is used to return a status code to the invoking
3801  * environment.
3802  * +true+ and +FALSE+ of _status_ means success and failure
3803  * respectively. The interpretation of other integer values are
3804  * system dependent.
3805  *
3806  * begin
3807  * exit
3808  * puts "never get here"
3809  * rescue SystemExit
3810  * puts "rescued a SystemExit exception"
3811  * end
3812  * puts "after begin block"
3813  *
3814  * <em>produces:</em>
3815  *
3816  * rescued a SystemExit exception
3817  * after begin block
3818  *
3819  * Just prior to termination, Ruby executes any <code>at_exit</code> functions
3820  * (see Kernel::at_exit) and runs any object finalizers (see
3821  * ObjectSpace::define_finalizer).
3822  *
3823  * at_exit { puts "at_exit function" }
3824  * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
3825  * exit
3826  *
3827  * <em>produces:</em>
3828  *
3829  * at_exit function
3830  * in finalizer
3831  */
3832 
3833 VALUE
3834 rb_f_exit(int argc, const VALUE *argv)
3835 {
3836  int istatus;
3837 
3838  if (rb_check_arity(argc, 0, 1) == 1) {
3839  istatus = exit_status_code(argv[0]);
3840  }
3841  else {
3842  istatus = EXIT_SUCCESS;
3843  }
3844  rb_exit(istatus);
3845 
3846  UNREACHABLE;
3847 }
3848 
3849 
3850 /*
3851  * call-seq:
3852  * abort
3853  * Kernel::abort([msg])
3854  * Process.abort([msg])
3855  *
3856  * Terminate execution immediately, effectively by calling
3857  * <code>Kernel.exit(false)</code>. If _msg_ is given, it is written
3858  * to STDERR prior to terminating.
3859  */
3860 
3861 VALUE
3863 {
3864  rb_check_arity(argc, 0, 1);
3865  if (argc == 0) {
3866  if (!NIL_P(GET_THREAD()->errinfo)) {
3867  ruby_error_print();
3868  }
3870  }
3871  else {
3872  VALUE args[2];
3873 
3874  args[1] = args[0] = argv[0];
3875  StringValue(args[0]);
3876  rb_io_puts(1, args, rb_stderr);
3877  args[0] = INT2NUM(EXIT_FAILURE);
3879  }
3880 
3881  UNREACHABLE;
3882 }
3883 
3884 void
3885 rb_syswait(rb_pid_t pid)
3886 {
3887  int status;
3888 
3889  rb_waitpid(pid, &status, 0);
3890 }
3891 
3892 #if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV
3893 char *
3894 rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
3895 {
3896  VALUE cmd = *prog;
3897  if (eargp && !eargp->use_shell) {
3898  VALUE str = eargp->invoke.cmd.argv_str;
3899  VALUE buf = eargp->invoke.cmd.argv_buf;
3900  char *p, **argv = ARGVSTR2ARGV(str);
3901  long i, argc = ARGVSTR2ARGC(str);
3902  const char *start = RSTRING_PTR(buf);
3903  cmd = rb_str_new(start, RSTRING_LEN(buf));
3904  p = RSTRING_PTR(cmd);
3905  for (i = 1; i < argc; ++i) {
3906  p[argv[i] - start - 1] = ' ';
3907  }
3908  *prog = cmd;
3909  return p;
3910  }
3911  return StringValueCStr(*prog);
3912 }
3913 #endif
3914 
3915 static rb_pid_t
3916 rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
3917 {
3918  rb_pid_t pid;
3919 #if !defined HAVE_WORKING_FORK || USE_SPAWNV
3920  VALUE prog;
3921  struct rb_execarg sarg;
3922 # if !defined HAVE_SPAWNV
3923  int status;
3924 # endif
3925 #endif
3926 
3927 #if defined HAVE_WORKING_FORK && !USE_SPAWNV
3928  pid = rb_fork_async_signal_safe(NULL, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen);
3929 #else
3930  prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
3931 
3932  if (rb_execarg_run_options(eargp, &sarg, errmsg, errmsg_buflen) < 0) {
3933  return -1;
3934  }
3935 
3936  if (prog && !eargp->use_shell) {
3937  char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
3938  argv[0] = RSTRING_PTR(prog);
3939  }
3940 # if defined HAVE_SPAWNV
3941  if (eargp->use_shell) {
3942  pid = proc_spawn_sh(RSTRING_PTR(prog));
3943  }
3944  else {
3945  char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
3946  pid = proc_spawn_cmd(argv, prog, eargp);
3947  }
3948  if (pid == -1)
3949  rb_last_status_set(0x7f << 8, 0);
3950 # else
3951  status = system(rb_execarg_commandline(eargp, &prog));
3952  rb_last_status_set((status & 0xff) << 8, 0);
3953  pid = 1; /* dummy */
3954 # endif
3955 
3956  rb_execarg_run_options(&sarg, NULL, errmsg, errmsg_buflen);
3957 #endif
3958  return pid;
3959 }
3960 
3961 struct spawn_args {
3963  struct {
3964  char *ptr;
3965  size_t buflen;
3966  } errmsg;
3967 };
3968 
3969 static VALUE
3971 {
3972  struct spawn_args *argp = (struct spawn_args *)arg;
3974  return (VALUE)rb_spawn_process(DATA_PTR(argp->execarg),
3975  argp->errmsg.ptr, argp->errmsg.buflen);
3976 }
3977 
3978 static rb_pid_t
3979 rb_execarg_spawn(VALUE execarg_obj, char *errmsg, size_t errmsg_buflen)
3980 {
3981  struct spawn_args args;
3982 
3983  args.execarg = execarg_obj;
3984  args.errmsg.ptr = errmsg;
3985  args.errmsg.buflen = errmsg_buflen;
3986  return (rb_pid_t)rb_ensure(do_spawn_process, (VALUE)&args,
3987  execarg_parent_end, execarg_obj);
3988 }
3989 
3990 static rb_pid_t
3991 rb_spawn_internal(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
3992 {
3993  VALUE execarg_obj;
3994 
3995  execarg_obj = rb_execarg_new(argc, argv, TRUE);
3996  return rb_execarg_spawn(execarg_obj, errmsg, errmsg_buflen);
3997 }
3998 
3999 rb_pid_t
4000 rb_spawn_err(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
4001 {
4002  return rb_spawn_internal(argc, argv, errmsg, errmsg_buflen);
4003 }
4004 
4005 rb_pid_t
4006 rb_spawn(int argc, const VALUE *argv)
4007 {
4008  return rb_spawn_internal(argc, argv, NULL, 0);
4009 }
4010 
4011 /*
4012  * call-seq:
4013  * system([env,] command... [,options]) -> true, false or nil
4014  *
4015  * Executes _command..._ in a subshell.
4016  * _command..._ is one of following forms.
4017  *
4018  * commandline : command line string which is passed to the standard shell
4019  * cmdname, arg1, ... : command name and one or more arguments (no shell)
4020  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
4021  *
4022  * system returns +true+ if the command gives zero exit status,
4023  * +false+ for non zero exit status.
4024  * Returns +nil+ if command execution fails.
4025  * An error status is available in <code>$?</code>.
4026  * The arguments are processed in the same way as
4027  * for <code>Kernel.spawn</code>.
4028  *
4029  * The hash arguments, env and options, are same as
4030  * <code>exec</code> and <code>spawn</code>.
4031  * See <code>Kernel.spawn</code> for details.
4032  *
4033  * system("echo *")
4034  * system("echo", "*")
4035  *
4036  * <em>produces:</em>
4037  *
4038  * config.h main.rb
4039  * *
4040  *
4041  * See <code>Kernel.exec</code> for the standard shell.
4042  */
4043 
4044 static VALUE
4046 {
4047  rb_pid_t pid;
4048  int status;
4049 
4050 #if defined(SIGCLD) && !defined(SIGCHLD)
4051 # define SIGCHLD SIGCLD
4052 #endif
4053 
4054 #ifdef SIGCHLD
4055  RETSIGTYPE (*chfunc)(int);
4056 
4058  chfunc = signal(SIGCHLD, SIG_DFL);
4059 #endif
4060  pid = rb_spawn_internal(argc, argv, NULL, 0);
4061 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
4062  if (pid > 0) {
4063  int ret, status;
4064  ret = rb_waitpid(pid, &status, 0);
4065  if (ret == (rb_pid_t)-1)
4066  rb_sys_fail("Another thread waited the process started by system().");
4067  }
4068 #endif
4069 #ifdef SIGCHLD
4070  signal(SIGCHLD, chfunc);
4071 #endif
4072  if (pid < 0) {
4073  return Qnil;
4074  }
4075  status = PST2INT(rb_last_status_get());
4076  if (status == EXIT_SUCCESS) return Qtrue;
4077  return Qfalse;
4078 }
4079 
4080 /*
4081  * call-seq:
4082  * spawn([env,] command... [,options]) -> pid
4083  * Process.spawn([env,] command... [,options]) -> pid
4084  *
4085  * spawn executes specified command and return its pid.
4086  *
4087  * pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
4088  * Process.wait pid
4089  *
4090  * pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
4091  * Process.wait pid
4092  *
4093  * This method is similar to Kernel#system but it doesn't wait for the command
4094  * to finish.
4095  *
4096  * The parent process should
4097  * use <code>Process.wait</code> to collect
4098  * the termination status of its child or
4099  * use <code>Process.detach</code> to register
4100  * disinterest in their status;
4101  * otherwise, the operating system may accumulate zombie processes.
4102  *
4103  * spawn has bunch of options to specify process attributes:
4104  *
4105  * env: hash
4106  * name => val : set the environment variable
4107  * name => nil : unset the environment variable
4108  *
4109  * the keys and the values except for +nil+ must be strings.
4110  * command...:
4111  * commandline : command line string which is passed to the standard shell
4112  * cmdname, arg1, ... : command name and one or more arguments (This form does not use the shell. See below for caveats.)
4113  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
4114  * options: hash
4115  * clearing environment variables:
4116  * :unsetenv_others => true : clear environment variables except specified by env
4117  * :unsetenv_others => false : don't clear (default)
4118  * process group:
4119  * :pgroup => true or 0 : make a new process group
4120  * :pgroup => pgid : join the specified process group
4121  * :pgroup => nil : don't change the process group (default)
4122  * create new process group: Windows only
4123  * :new_pgroup => true : the new process is the root process of a new process group
4124  * :new_pgroup => false : don't create a new process group (default)
4125  * resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
4126  * :rlimit_resourcename => limit
4127  * :rlimit_resourcename => [cur_limit, max_limit]
4128  * umask:
4129  * :umask => int
4130  * redirection:
4131  * key:
4132  * FD : single file descriptor in child process
4133  * [FD, FD, ...] : multiple file descriptor in child process
4134  * value:
4135  * FD : redirect to the file descriptor in parent process
4136  * string : redirect to file with open(string, "r" or "w")
4137  * [string] : redirect to file with open(string, File::RDONLY)
4138  * [string, open_mode] : redirect to file with open(string, open_mode, 0644)
4139  * [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
4140  * [:child, FD] : redirect to the redirected file descriptor
4141  * :close : close the file descriptor in child process
4142  * FD is one of follows
4143  * :in : the file descriptor 0 which is the standard input
4144  * :out : the file descriptor 1 which is the standard output
4145  * :err : the file descriptor 2 which is the standard error
4146  * integer : the file descriptor of specified the integer
4147  * io : the file descriptor specified as io.fileno
4148  * file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
4149  * :close_others => true : don't inherit
4150  * current directory:
4151  * :chdir => str
4152  *
4153  * The 'cmdname, arg1, ...' form does not use the shell. However,
4154  * on different OSes, different things are provided as built-in
4155  * commands. An example of this is 'echo', which is a built-in
4156  * on Windows, but is a normal program on Linux and Mac OS X.
4157  * This means that `Process.spawn 'echo', '%Path%'` will display
4158  * the contents of the `%Path%` environment variable on Windows,
4159  * but `Process.spawn 'echo', '$PATH'` prints the literal '$PATH'.
4160  *
4161  * If a hash is given as +env+, the environment is
4162  * updated by +env+ before <code>exec(2)</code> in the child process.
4163  * If a pair in +env+ has nil as the value, the variable is deleted.
4164  *
4165  * # set FOO as BAR and unset BAZ.
4166  * pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
4167  *
4168  * If a hash is given as +options+,
4169  * it specifies
4170  * process group,
4171  * create new process group,
4172  * resource limit,
4173  * current directory,
4174  * umask and
4175  * redirects for the child process.
4176  * Also, it can be specified to clear environment variables.
4177  *
4178  * The <code>:unsetenv_others</code> key in +options+ specifies
4179  * to clear environment variables, other than specified by +env+.
4180  *
4181  * pid = spawn(command, :unsetenv_others=>true) # no environment variable
4182  * pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
4183  *
4184  * The <code>:pgroup</code> key in +options+ specifies a process group.
4185  * The corresponding value should be true, zero, a positive integer, or nil.
4186  * true and zero cause the process to be a process leader of a new process group.
4187  * A non-zero positive integer causes the process to join the provided process group.
4188  * The default value, nil, causes the process to remain in the same process group.
4189  *
4190  * pid = spawn(command, :pgroup=>true) # process leader
4191  * pid = spawn(command, :pgroup=>10) # belongs to the process group 10
4192  *
4193  * The <code>:new_pgroup</code> key in +options+ specifies to pass
4194  * +CREATE_NEW_PROCESS_GROUP+ flag to <code>CreateProcessW()</code> that is
4195  * Windows API. This option is only for Windows.
4196  * true means the new process is the root process of the new process group.
4197  * The new process has CTRL+C disabled. This flag is necessary for
4198  * <code>Process.kill(:SIGINT, pid)</code> on the subprocess.
4199  * :new_pgroup is false by default.
4200  *
4201  * pid = spawn(command, :new_pgroup=>true) # new process group
4202  * pid = spawn(command, :new_pgroup=>false) # same process group
4203  *
4204  * The <code>:rlimit_</code><em>foo</em> key specifies a resource limit.
4205  * <em>foo</em> should be one of resource types such as <code>core</code>.
4206  * The corresponding value should be an integer or an array which have one or
4207  * two integers: same as cur_limit and max_limit arguments for
4208  * Process.setrlimit.
4209  *
4210  * cur, max = Process.getrlimit(:CORE)
4211  * pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
4212  * pid = spawn(command, :rlimit_core=>max) # enable core dump
4213  * pid = spawn(command, :rlimit_core=>0) # never dump core.
4214  *
4215  * The <code>:umask</code> key in +options+ specifies the umask.
4216  *
4217  * pid = spawn(command, :umask=>077)
4218  *
4219  * The :in, :out, :err, an integer, an IO and an array key specifies a redirection.
4220  * The redirection maps a file descriptor in the child process.
4221  *
4222  * For example, stderr can be merged into stdout as follows:
4223  *
4224  * pid = spawn(command, :err=>:out)
4225  * pid = spawn(command, 2=>1)
4226  * pid = spawn(command, STDERR=>:out)
4227  * pid = spawn(command, STDERR=>STDOUT)
4228  *
4229  * The hash keys specifies a file descriptor
4230  * in the child process started by <code>spawn</code>.
4231  * :err, 2 and STDERR specifies the standard error stream (stderr).
4232  *
4233  * The hash values specifies a file descriptor
4234  * in the parent process which invokes <code>spawn</code>.
4235  * :out, 1 and STDOUT specifies the standard output stream (stdout).
4236  *
4237  * In the above example,
4238  * the standard output in the child process is not specified.
4239  * So it is inherited from the parent process.
4240  *
4241  * The standard input stream (stdin) can be specified by :in, 0 and STDIN.
4242  *
4243  * A filename can be specified as a hash value.
4244  *
4245  * pid = spawn(command, :in=>"/dev/null") # read mode
4246  * pid = spawn(command, :out=>"/dev/null") # write mode
4247  * pid = spawn(command, :err=>"log") # write mode
4248  * pid = spawn(command, [:out, :err]=>"/dev/null") # write mode
4249  * pid = spawn(command, 3=>"/dev/null") # read mode
4250  *
4251  * For stdout and stderr (and combination of them),
4252  * it is opened in write mode.
4253  * Otherwise read mode is used.
4254  *
4255  * For specifying flags and permission of file creation explicitly,
4256  * an array is used instead.
4257  *
4258  * pid = spawn(command, :in=>["file"]) # read mode is assumed
4259  * pid = spawn(command, :in=>["file", "r"])
4260  * pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
4261  * pid = spawn(command, :out=>["log", "w", 0600])
4262  * pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
4263  *
4264  * The array specifies a filename, flags and permission.
4265  * The flags can be a string or an integer.
4266  * If the flags is omitted or nil, File::RDONLY is assumed.
4267  * The permission should be an integer.
4268  * If the permission is omitted or nil, 0644 is assumed.
4269  *
4270  * If an array of IOs and integers are specified as a hash key,
4271  * all the elements are redirected.
4272  *
4273  * # stdout and stderr is redirected to log file.
4274  * # The file "log" is opened just once.
4275  * pid = spawn(command, [:out, :err]=>["log", "w"])
4276  *
4277  * Another way to merge multiple file descriptors is [:child, fd].
4278  * \[:child, fd] means the file descriptor in the child process.
4279  * This is different from fd.
4280  * For example, :err=>:out means redirecting child stderr to parent stdout.
4281  * But :err=>[:child, :out] means redirecting child stderr to child stdout.
4282  * They differ if stdout is redirected in the child process as follows.
4283  *
4284  * # stdout and stderr is redirected to log file.
4285  * # The file "log" is opened just once.
4286  * pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
4287  *
4288  * \[:child, :out] can be used to merge stderr into stdout in IO.popen.
4289  * In this case, IO.popen redirects stdout to a pipe in the child process
4290  * and [:child, :out] refers the redirected stdout.
4291  *
4292  * io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
4293  * p io.read #=> "out\nerr\n"
4294  *
4295  * The <code>:chdir</code> key in +options+ specifies the current directory.
4296  *
4297  * pid = spawn(command, :chdir=>"/var/tmp")
4298  *
4299  * spawn closes all non-standard unspecified descriptors by default.
4300  * The "standard" descriptors are 0, 1 and 2.
4301  * This behavior is specified by :close_others option.
4302  * :close_others doesn't affect the standard descriptors which are
4303  * closed only if :close is specified explicitly.
4304  *
4305  * pid = spawn(command, :close_others=>true) # close 3,4,5,... (default)
4306  * pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
4307  *
4308  * :close_others is true by default for spawn and IO.popen.
4309  *
4310  * Note that fds which close-on-exec flag is already set are closed
4311  * regardless of :close_others option.
4312  *
4313  * So IO.pipe and spawn can be used as IO.popen.
4314  *
4315  * # similar to r = IO.popen(command)
4316  * r, w = IO.pipe
4317  * pid = spawn(command, :out=>w) # r, w is closed in the child process.
4318  * w.close
4319  *
4320  * :close is specified as a hash value to close a fd individually.
4321  *
4322  * f = open(foo)
4323  * system(command, f=>:close) # don't inherit f.
4324  *
4325  * If a file descriptor need to be inherited,
4326  * io=>io can be used.
4327  *
4328  * # valgrind has --log-fd option for log destination.
4329  * # log_w=>log_w indicates log_w.fileno inherits to child process.
4330  * log_r, log_w = IO.pipe
4331  * pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
4332  * log_w.close
4333  * p log_r.read
4334  *
4335  * It is also possible to exchange file descriptors.
4336  *
4337  * pid = spawn(command, :out=>:err, :err=>:out)
4338  *
4339  * The hash keys specify file descriptors in the child process.
4340  * The hash values specifies file descriptors in the parent process.
4341  * So the above specifies exchanging stdout and stderr.
4342  * Internally, +spawn+ uses an extra file descriptor to resolve such cyclic
4343  * file descriptor mapping.
4344  *
4345  * See <code>Kernel.exec</code> for the standard shell.
4346  */
4347 
4348 static VALUE
4350 {
4351  rb_pid_t pid;
4352  char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
4353  VALUE execarg_obj, fail_str;
4354  struct rb_execarg *eargp;
4355 
4356  execarg_obj = rb_execarg_new(argc, argv, TRUE);
4357  eargp = rb_execarg_get(execarg_obj);
4358  fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
4359 
4360  pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));
4361 
4362  if (pid == -1) {
4363  int err = errno;
4364  rb_exec_fail(eargp, err, errmsg);
4365  RB_GC_GUARD(execarg_obj);
4366  rb_syserr_fail_str(err, fail_str);
4367  }
4368 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
4369  return PIDT2NUM(pid);
4370 #else
4371  return Qnil;
4372 #endif
4373 }
4374 
4375 /*
4376  * call-seq:
4377  * sleep([duration]) -> integer
4378  *
4379  * Suspends the current thread for _duration_ seconds (which may be any number,
4380  * including a +Float+ with fractional seconds). Returns the actual number of
4381  * seconds slept (rounded), which may be less than that asked for if another
4382  * thread calls <code>Thread#run</code>. Called without an argument, sleep()
4383  * will sleep forever.
4384  *
4385  * Time.new #=> 2008-03-08 19:56:19 +0900
4386  * sleep 1.2 #=> 1
4387  * Time.new #=> 2008-03-08 19:56:20 +0900
4388  * sleep 1.9 #=> 2
4389  * Time.new #=> 2008-03-08 19:56:22 +0900
4390  */
4391 
4392 static VALUE
4394 {
4395  time_t beg, end;
4396 
4397  beg = time(0);
4398  if (argc == 0) {
4400  }
4401  else {
4402  rb_check_arity(argc, 0, 1);
4404  }
4405 
4406  end = time(0) - beg;
4407 
4408  return INT2FIX(end);
4409 }
4410 
4411 
4412 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
4413 /*
4414  * call-seq:
4415  * Process.getpgrp -> integer
4416  *
4417  * Returns the process group ID for this process. Not available on
4418  * all platforms.
4419  *
4420  * Process.getpgid(0) #=> 25527
4421  * Process.getpgrp #=> 25527
4422  */
4423 
4424 static VALUE
4425 proc_getpgrp(void)
4426 {
4427  rb_pid_t pgrp;
4428 
4429 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
4430  pgrp = getpgrp();
4431  if (pgrp < 0) rb_sys_fail(0);
4432  return PIDT2NUM(pgrp);
4433 #else /* defined(HAVE_GETPGID) */
4434  pgrp = getpgid(0);
4435  if (pgrp < 0) rb_sys_fail(0);
4436  return PIDT2NUM(pgrp);
4437 #endif
4438 }
4439 #else
4440 #define proc_getpgrp rb_f_notimplement
4441 #endif
4442 
4443 
4444 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
4445 /*
4446  * call-seq:
4447  * Process.setpgrp -> 0
4448  *
4449  * Equivalent to <code>setpgid(0,0)</code>. Not available on all
4450  * platforms.
4451  */
4452 
4453 static VALUE
4454 proc_setpgrp(void)
4455 {
4456  /* check for posix setpgid() first; this matches the posix */
4457  /* getpgrp() above. It appears that configure will set SETPGRP_VOID */
4458  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
4459  /* this confusion. */
4460 #ifdef HAVE_SETPGID
4461  if (setpgid(0,0) < 0) rb_sys_fail(0);
4462 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
4463  if (setpgrp() < 0) rb_sys_fail(0);
4464 #endif
4465  return INT2FIX(0);
4466 }
4467 #else
4468 #define proc_setpgrp rb_f_notimplement
4469 #endif
4470 
4471 
4472 #if defined(HAVE_GETPGID)
4473 /*
4474  * call-seq:
4475  * Process.getpgid(pid) -> integer
4476  *
4477  * Returns the process group ID for the given process id. Not
4478  * available on all platforms.
4479  *
4480  * Process.getpgid(Process.ppid()) #=> 25527
4481  */
4482 
4483 static VALUE
4484 proc_getpgid(VALUE obj, VALUE pid)
4485 {
4486  rb_pid_t i;
4487 
4488  i = getpgid(NUM2PIDT(pid));
4489  if (i < 0) rb_sys_fail(0);
4490  return PIDT2NUM(i);
4491 }
4492 #else
4493 #define proc_getpgid rb_f_notimplement
4494 #endif
4495 
4496 
4497 #ifdef HAVE_SETPGID
4498 /*
4499  * call-seq:
4500  * Process.setpgid(pid, integer) -> 0
4501  *
4502  * Sets the process group ID of _pid_ (0 indicates this
4503  * process) to <em>integer</em>. Not available on all platforms.
4504  */
4505 
4506 static VALUE
4507 proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
4508 {
4509  rb_pid_t ipid, ipgrp;
4510 
4511  ipid = NUM2PIDT(pid);
4512  ipgrp = NUM2PIDT(pgrp);
4513 
4514  if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
4515  return INT2FIX(0);
4516 }
4517 #else
4518 #define proc_setpgid rb_f_notimplement
4519 #endif
4520 
4521 
4522 #ifdef HAVE_GETSID
4523 /*
4524  * call-seq:
4525  * Process.getsid() -> integer
4526  * Process.getsid(pid) -> integer
4527  *
4528  * Returns the session ID for the given process id. If not given,
4529  * return current process sid. Not available on all platforms.
4530  *
4531  * Process.getsid() #=> 27422
4532  * Process.getsid(0) #=> 27422
4533  * Process.getsid(Process.pid()) #=> 27422
4534  */
4535 static VALUE
4536 proc_getsid(int argc, VALUE *argv)
4537 {
4538  rb_pid_t sid;
4539  rb_pid_t pid = 0;
4540 
4541  if (rb_check_arity(argc, 0, 1) == 1 && !NIL_P(argv[0]))
4542  pid = NUM2PIDT(argv[0]);
4543 
4544  sid = getsid(pid);
4545  if (sid < 0) rb_sys_fail(0);
4546  return PIDT2NUM(sid);
4547 }
4548 #else
4549 #define proc_getsid rb_f_notimplement
4550 #endif
4551 
4552 
4553 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
4554 #if !defined(HAVE_SETSID)
4555 static rb_pid_t ruby_setsid(void);
4556 #define setsid() ruby_setsid()
4557 #endif
4558 /*
4559  * call-seq:
4560  * Process.setsid -> integer
4561  *
4562  * Establishes this process as a new session and process group
4563  * leader, with no controlling tty. Returns the session id. Not
4564  * available on all platforms.
4565  *
4566  * Process.setsid #=> 27422
4567  */
4568 
4569 static VALUE
4570 proc_setsid(void)
4571 {
4572  rb_pid_t pid;
4573 
4574  pid = setsid();
4575  if (pid < 0) rb_sys_fail(0);
4576  return PIDT2NUM(pid);
4577 }
4578 
4579 #if !defined(HAVE_SETSID)
4580 #define HAVE_SETSID 1
4581 static rb_pid_t
4582 ruby_setsid(void)
4583 {
4584  rb_pid_t pid;
4585  int ret;
4586 
4587  pid = getpid();
4588 #if defined(SETPGRP_VOID)
4589  ret = setpgrp();
4590  /* If `pid_t setpgrp(void)' is equivalent to setsid(),
4591  `ret' will be the same value as `pid', and following open() will fail.
4592  In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
4593 #else
4594  ret = setpgrp(0, pid);
4595 #endif
4596  if (ret == -1) return -1;
4597 
4598  if ((fd = rb_cloexec_open("/dev/tty", O_RDWR, 0)) >= 0) {
4599  rb_update_max_fd(fd);
4600  ioctl(fd, TIOCNOTTY, NULL);
4601  close(fd);
4602  }
4603  return pid;
4604 }
4605 #endif
4606 #else
4607 #define proc_setsid rb_f_notimplement
4608 #endif
4609 
4610 
4611 #ifdef HAVE_GETPRIORITY
4612 /*
4613  * call-seq:
4614  * Process.getpriority(kind, integer) -> integer
4615  *
4616  * Gets the scheduling priority for specified process, process group,
4617  * or user. <em>kind</em> indicates the kind of entity to find: one
4618  * of <code>Process::PRIO_PGRP</code>,
4619  * <code>Process::PRIO_USER</code>, or
4620  * <code>Process::PRIO_PROCESS</code>. _integer_ is an id
4621  * indicating the particular process, process group, or user (an id
4622  * of 0 means _current_). Lower priorities are more favorable
4623  * for scheduling. Not available on all platforms.
4624  *
4625  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
4626  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
4627  */
4628 
4629 static VALUE
4630 proc_getpriority(VALUE obj, VALUE which, VALUE who)
4631 {
4632  int prio, iwhich, iwho;
4633 
4634  iwhich = NUM2INT(which);
4635  iwho = NUM2INT(who);
4636 
4637  errno = 0;
4638  prio = getpriority(iwhich, iwho);
4639  if (errno) rb_sys_fail(0);
4640  return INT2FIX(prio);
4641 }
4642 #else
4643 #define proc_getpriority rb_f_notimplement
4644 #endif
4645 
4646 
4647 #ifdef HAVE_GETPRIORITY
4648 /*
4649  * call-seq:
4650  * Process.setpriority(kind, integer, priority) -> 0
4651  *
4652  * See <code>Process#getpriority</code>.
4653  *
4654  * Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0
4655  * Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0
4656  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
4657  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
4658  */
4659 
4660 static VALUE
4661 proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
4662 {
4663  int iwhich, iwho, iprio;
4664 
4665  iwhich = NUM2INT(which);
4666  iwho = NUM2INT(who);
4667  iprio = NUM2INT(prio);
4668 
4669  if (setpriority(iwhich, iwho, iprio) < 0)
4670  rb_sys_fail(0);
4671  return INT2FIX(0);
4672 }
4673 #else
4674 #define proc_setpriority rb_f_notimplement
4675 #endif
4676 
4677 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
4678 static int
4679 rlimit_resource_name2int(const char *name, long len, int casetype)
4680 {
4681  int resource;
4682  const char *p;
4683 #define RESCHECK(r) \
4684  do { \
4685  if (len == rb_strlen_lit(#r) && STRCASECMP(name, #r) == 0) { \
4686  resource = RLIMIT_##r; \
4687  goto found; \
4688  } \
4689  } while (0)
4690 
4691  switch (TOUPPER(*name)) {
4692  case 'A':
4693 #ifdef RLIMIT_AS
4694  RESCHECK(AS);
4695 #endif
4696  break;
4697 
4698  case 'C':
4699 #ifdef RLIMIT_CORE
4700  RESCHECK(CORE);
4701 #endif
4702 #ifdef RLIMIT_CPU
4703  RESCHECK(CPU);
4704 #endif
4705  break;
4706 
4707  case 'D':
4708 #ifdef RLIMIT_DATA
4709  RESCHECK(DATA);
4710 #endif
4711  break;
4712 
4713  case 'F':
4714 #ifdef RLIMIT_FSIZE
4715  RESCHECK(FSIZE);
4716 #endif
4717  break;
4718 
4719  case 'M':
4720 #ifdef RLIMIT_MEMLOCK
4721  RESCHECK(MEMLOCK);
4722 #endif
4723 #ifdef RLIMIT_MSGQUEUE
4724  RESCHECK(MSGQUEUE);
4725 #endif
4726  break;
4727 
4728  case 'N':
4729 #ifdef RLIMIT_NOFILE
4730  RESCHECK(NOFILE);
4731 #endif
4732 #ifdef RLIMIT_NPROC
4733  RESCHECK(NPROC);
4734 #endif
4735 #ifdef RLIMIT_NICE
4736  RESCHECK(NICE);
4737 #endif
4738  break;
4739 
4740  case 'R':
4741 #ifdef RLIMIT_RSS
4742  RESCHECK(RSS);
4743 #endif
4744 #ifdef RLIMIT_RTPRIO
4745  RESCHECK(RTPRIO);
4746 #endif
4747 #ifdef RLIMIT_RTTIME
4748  RESCHECK(RTTIME);
4749 #endif
4750  break;
4751 
4752  case 'S':
4753 #ifdef RLIMIT_STACK
4754  RESCHECK(STACK);
4755 #endif
4756 #ifdef RLIMIT_SBSIZE
4757  RESCHECK(SBSIZE);
4758 #endif
4759 #ifdef RLIMIT_SIGPENDING
4760  RESCHECK(SIGPENDING);
4761 #endif
4762  break;
4763  }
4764  return -1;
4765 
4766  found:
4767  switch (casetype) {
4768  case 0:
4769  for (p = name; *p; p++)
4770  if (!ISUPPER(*p))
4771  return -1;
4772  break;
4773 
4774  case 1:
4775  for (p = name; *p; p++)
4776  if (!ISLOWER(*p))
4777  return -1;
4778  break;
4779 
4780  default:
4781  rb_bug("unexpected casetype");
4782  }
4783  return resource;
4784 #undef RESCHECK
4785 }
4786 
4787 static int
4788 rlimit_type_by_hname(const char *name, long len)
4789 {
4790  return rlimit_resource_name2int(name, len, 0);
4791 }
4792 
4793 static int
4794 rlimit_type_by_lname(const char *name, long len)
4795 {
4796  return rlimit_resource_name2int(name, len, 1);
4797 }
4798 
4799 static int
4800 rlimit_type_by_sym(VALUE key)
4801 {
4802  VALUE name = rb_sym2str(key);
4803  const char *rname = RSTRING_PTR(name);
4804  long len = RSTRING_LEN(name);
4805  int rtype = -1;
4806  static const char prefix[] = "rlimit_";
4807  enum {prefix_len = sizeof(prefix)-1};
4808 
4809  if (len > prefix_len && strncmp(prefix, rname, prefix_len) == 0) {
4810  rtype = rlimit_type_by_lname(rname + prefix_len, len - prefix_len);
4811  }
4812 
4813  RB_GC_GUARD(key);
4814  return rtype;
4815 }
4816 
4817 static int
4818 rlimit_resource_type(VALUE rtype)
4819 {
4820  const char *name;
4821  long len;
4822  VALUE v;
4823  int r;
4824 
4825  switch (TYPE(rtype)) {
4826  case T_SYMBOL:
4827  v = rb_sym2str(rtype);
4828  name = RSTRING_PTR(v);
4829  len = RSTRING_LEN(v);
4830  break;
4831 
4832  default:
4833  v = rb_check_string_type(rtype);
4834  if (!NIL_P(v)) {
4835  rtype = v;
4836  case T_STRING:
4837  name = StringValueCStr(rtype);
4838  len = RSTRING_LEN(rtype);
4839  break;
4840  }
4841  /* fall through */
4842 
4843  case T_FIXNUM:
4844  case T_BIGNUM:
4845  return NUM2INT(rtype);
4846  }
4847 
4848  r = rlimit_type_by_hname(name, len);
4849  if (r != -1)
4850  return r;
4851 
4852  rb_raise(rb_eArgError, "invalid resource name: % "PRIsVALUE, rtype);
4853 
4854  UNREACHABLE;
4855 }
4856 
4857 static rlim_t
4858 rlimit_resource_value(VALUE rval)
4859 {
4860  const char *name;
4861  VALUE v;
4862 
4863  switch (TYPE(rval)) {
4864  case T_SYMBOL:
4865  v = rb_sym2str(rval);
4866  name = RSTRING_PTR(v);
4867  break;
4868 
4869  default:
4870  v = rb_check_string_type(rval);
4871  if (!NIL_P(v)) {
4872  rval = v;
4873  case T_STRING:
4874  name = StringValueCStr(rval);
4875  break;
4876  }
4877  /* fall through */
4878 
4879  case T_FIXNUM:
4880  case T_BIGNUM:
4881  return NUM2RLIM(rval);
4882  }
4883 
4884 #ifdef RLIM_INFINITY
4885  if (strcmp(name, "INFINITY") == 0) return RLIM_INFINITY;
4886 #endif
4887 #ifdef RLIM_SAVED_MAX
4888  if (strcmp(name, "SAVED_MAX") == 0) return RLIM_SAVED_MAX;
4889 #endif
4890 #ifdef RLIM_SAVED_CUR
4891  if (strcmp(name, "SAVED_CUR") == 0) return RLIM_SAVED_CUR;
4892 #endif
4893  rb_raise(rb_eArgError, "invalid resource value: %"PRIsVALUE, rval);
4894 
4895  UNREACHABLE;
4896 }
4897 #endif
4898 
4899 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
4900 /*
4901  * call-seq:
4902  * Process.getrlimit(resource) -> [cur_limit, max_limit]
4903  *
4904  * Gets the resource limit of the process.
4905  * _cur_limit_ means current (soft) limit and
4906  * _max_limit_ means maximum (hard) limit.
4907  *
4908  * _resource_ indicates the kind of resource to limit.
4909  * It is specified as a symbol such as <code>:CORE</code>,
4910  * a string such as <code>"CORE"</code> or
4911  * a constant such as <code>Process::RLIMIT_CORE</code>.
4912  * See Process.setrlimit for details.
4913  *
4914  * _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
4915  * <code>Process::RLIM_SAVED_MAX</code> or
4916  * <code>Process::RLIM_SAVED_CUR</code>.
4917  * See Process.setrlimit and the system getrlimit(2) manual for details.
4918  */
4919 
4920 static VALUE
4921 proc_getrlimit(VALUE obj, VALUE resource)
4922 {
4923  struct rlimit rlim;
4924 
4925  if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4926  rb_sys_fail("getrlimit");
4927  }
4928  return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
4929 }
4930 #else
4931 #define proc_getrlimit rb_f_notimplement
4932 #endif
4933 
4934 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
4935 /*
4936  * call-seq:
4937  * Process.setrlimit(resource, cur_limit, max_limit) -> nil
4938  * Process.setrlimit(resource, cur_limit) -> nil
4939  *
4940  * Sets the resource limit of the process.
4941  * _cur_limit_ means current (soft) limit and
4942  * _max_limit_ means maximum (hard) limit.
4943  *
4944  * If _max_limit_ is not given, _cur_limit_ is used.
4945  *
4946  * _resource_ indicates the kind of resource to limit.
4947  * It should be a symbol such as <code>:CORE</code>,
4948  * a string such as <code>"CORE"</code> or
4949  * a constant such as <code>Process::RLIMIT_CORE</code>.
4950  * The available resources are OS dependent.
4951  * Ruby may support following resources.
4952  *
4953  * [AS] total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)
4954  * [CORE] core size (bytes) (SUSv3)
4955  * [CPU] CPU time (seconds) (SUSv3)
4956  * [DATA] data segment (bytes) (SUSv3)
4957  * [FSIZE] file size (bytes) (SUSv3)
4958  * [MEMLOCK] total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)
4959  * [MSGQUEUE] allocation for POSIX message queues (bytes) (GNU/Linux)
4960  * [NICE] ceiling on process's nice(2) value (number) (GNU/Linux)
4961  * [NOFILE] file descriptors (number) (SUSv3)
4962  * [NPROC] number of processes for the user (number) (4.4BSD, GNU/Linux)
4963  * [RSS] resident memory size (bytes) (4.2BSD, GNU/Linux)
4964  * [RTPRIO] ceiling on the process's real-time priority (number) (GNU/Linux)
4965  * [RTTIME] CPU time for real-time process (us) (GNU/Linux)
4966  * [SBSIZE] all socket buffers (bytes) (NetBSD, FreeBSD)
4967  * [SIGPENDING] number of queued signals allowed (signals) (GNU/Linux)
4968  * [STACK] stack size (bytes) (SUSv3)
4969  *
4970  * _cur_limit_ and _max_limit_ may be
4971  * <code>:INFINITY</code>, <code>"INFINITY"</code> or
4972  * <code>Process::RLIM_INFINITY</code>,
4973  * which means that the resource is not limited.
4974  * They may be <code>Process::RLIM_SAVED_MAX</code>,
4975  * <code>Process::RLIM_SAVED_CUR</code> and
4976  * corresponding symbols and strings too.
4977  * See system setrlimit(2) manual for details.
4978  *
4979  * The following example raises the soft limit of core size to
4980  * the hard limit to try to make core dump possible.
4981  *
4982  * Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
4983  *
4984  */
4985 
4986 static VALUE
4987 proc_setrlimit(int argc, VALUE *argv, VALUE obj)
4988 {
4989  VALUE resource, rlim_cur, rlim_max;
4990  struct rlimit rlim;
4991 
4992  rb_check_arity(argc, 2, 3);
4993  resource = argv[0];
4994  rlim_cur = argv[1];
4995  if (argc < 3 || NIL_P(rlim_max = argv[2]))
4996  rlim_max = rlim_cur;
4997 
4998  rlim.rlim_cur = rlimit_resource_value(rlim_cur);
4999  rlim.rlim_max = rlimit_resource_value(rlim_max);
5000 
5001  if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
5002  rb_sys_fail("setrlimit");
5003  }
5004  return Qnil;
5005 }
5006 #else
5007 #define proc_setrlimit rb_f_notimplement
5008 #endif
5009 
5010 static int under_uid_switch = 0;
5011 static void
5013 {
5014  if (under_uid_switch) {
5015  rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
5016  }
5017 }
5018 
5019 static int under_gid_switch = 0;
5020 static void
5022 {
5023  if (under_gid_switch) {
5024  rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
5025  }
5026 }
5027 
5028 
5029 /*********************************************************************
5030  * Document-class: Process::Sys
5031  *
5032  * The <code>Process::Sys</code> module contains UID and GID
5033  * functions which provide direct bindings to the system calls of the
5034  * same names instead of the more-portable versions of the same
5035  * functionality found in the <code>Process</code>,
5036  * <code>Process::UID</code>, and <code>Process::GID</code> modules.
5037  */
5038 
5039 #if defined(HAVE_PWD_H)
5040 static rb_uid_t
5041 obj2uid(VALUE id
5042 # ifdef USE_GETPWNAM_R
5043  , VALUE *getpw_tmp
5044 # endif
5045  )
5046 {
5047  rb_uid_t uid;
5048  VALUE tmp;
5049 
5050  if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
5051  uid = NUM2UIDT(id);
5052  }
5053  else {
5054  const char *usrname = StringValueCStr(id);
5055  struct passwd *pwptr;
5056 #ifdef USE_GETPWNAM_R
5057  struct passwd pwbuf;
5058  char *getpw_buf;
5059  long getpw_buf_len;
5060  if (!*getpw_tmp) {
5061  getpw_buf_len = GETPW_R_SIZE_INIT;
5062  if (getpw_buf_len < 0) getpw_buf_len = GETPW_R_SIZE_DEFAULT;
5063  *getpw_tmp = rb_str_tmp_new(getpw_buf_len);
5064  }
5065  getpw_buf = RSTRING_PTR(*getpw_tmp);
5066  getpw_buf_len = rb_str_capacity(*getpw_tmp);
5067  rb_str_set_len(*getpw_tmp, getpw_buf_len);
5068  errno = ERANGE;
5069  /* gepwnam_r() on MacOS X doesn't set errno if buffer size is insufficient */
5070  while (getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) {
5071  int e = errno;
5072  if (e != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) {
5073  rb_str_resize(*getpw_tmp, 0);
5074  rb_syserr_fail(e, "getpwnam_r");
5075  }
5076  rb_str_modify_expand(*getpw_tmp, getpw_buf_len);
5077  getpw_buf = RSTRING_PTR(*getpw_tmp);
5078  getpw_buf_len = rb_str_capacity(*getpw_tmp);
5079  }
5080 #else
5081  pwptr = getpwnam(usrname);
5082 #endif
5083  if (!pwptr) {
5084 #ifndef USE_GETPWNAM_R
5085  endpwent();
5086 #endif
5087  rb_raise(rb_eArgError, "can't find user for %s", usrname);
5088  }
5089  uid = pwptr->pw_uid;
5090 #ifndef USE_GETPWNAM_R
5091  endpwent();
5092 #endif
5093  }
5094  return uid;
5095 }
5096 
5097 # ifdef p_uid_from_name
5098 /*
5099  * call-seq:
5100  * Process::UID.from_name(name) -> uid
5101  *
5102  * Get the user ID by the _name_.
5103  * If the user is not found, +ArgumentError+ will be raised.
5104  *
5105  * Process::UID.from_name("root") #=> 0
5106  * Process::UID.from_name("nosuchuser") #=> can't find user for nosuchuser (ArgumentError)
5107  */
5108 
5109 static VALUE
5110 p_uid_from_name(VALUE self, VALUE id)
5111 {
5112  return UIDT2NUM(OBJ2UID(id));
5113 }
5114 # endif
5115 #endif
5116 
5117 #if defined(HAVE_GRP_H)
5118 static rb_gid_t
5119 obj2gid(VALUE id
5120 # ifdef USE_GETGRNAM_R
5121  , VALUE *getgr_tmp
5122 # endif
5123  )
5124 {
5125  rb_gid_t gid;
5126  VALUE tmp;
5127 
5128  if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
5129  gid = NUM2GIDT(id);
5130  }
5131  else {
5132  const char *grpname = StringValueCStr(id);
5133  struct group *grptr;
5134 #ifdef USE_GETGRNAM_R
5135  struct group grbuf;
5136  char *getgr_buf;
5137  long getgr_buf_len;
5138  if (!*getgr_tmp) {
5139  getgr_buf_len = GETGR_R_SIZE_INIT;
5140  if (getgr_buf_len < 0) getgr_buf_len = GETGR_R_SIZE_DEFAULT;
5141  *getgr_tmp = rb_str_tmp_new(getgr_buf_len);
5142  }
5143  getgr_buf = RSTRING_PTR(*getgr_tmp);
5144  getgr_buf_len = rb_str_capacity(*getgr_tmp);
5145  rb_str_set_len(*getgr_tmp, getgr_buf_len);
5146  errno = ERANGE;
5147  /* gegrnam_r() on MacOS X doesn't set errno if buffer size is insufficient */
5148  while (getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) {
5149  int e = errno;
5150  if (e != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) {
5151  rb_str_resize(*getgr_tmp, 0);
5152  rb_syserr_fail(e, "getgrnam_r");
5153  }
5154  rb_str_modify_expand(*getgr_tmp, getgr_buf_len);
5155  getgr_buf = RSTRING_PTR(*getgr_tmp);
5156  getgr_buf_len = rb_str_capacity(*getgr_tmp);
5157  }
5158 #elif defined(HAVE_GETGRNAM)
5159  grptr = getgrnam(grpname);
5160 #else
5161  grptr = NULL;
5162 #endif
5163  if (!grptr) {
5164 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
5165  endgrent();
5166 #endif
5167  rb_raise(rb_eArgError, "can't find group for %s", grpname);
5168  }
5169  gid = grptr->gr_gid;
5170 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
5171  endgrent();
5172 #endif
5173  }
5174  return gid;
5175 }
5176 
5177 # ifdef p_gid_from_name
5178 /*
5179  * call-seq:
5180  * Process::GID.from_name(name) -> gid
5181  *
5182  * Get the group ID by the _name_.
5183  * If the group is not found, +ArgumentError+ will be raised.
5184  *
5185  * Process::GID.from_name("wheel") #=> 0
5186  * Process::GID.from_name("nosuchgroup") #=> can't find group for nosuchgroup (ArgumentError)
5187  */
5188 
5189 static VALUE
5190 p_gid_from_name(VALUE self, VALUE id)
5191 {
5192  return GIDT2NUM(OBJ2GID(id));
5193 }
5194 # endif
5195 #endif
5196 
5197 #if defined HAVE_SETUID
5198 /*
5199  * call-seq:
5200  * Process::Sys.setuid(user) -> nil
5201  *
5202  * Set the user ID of the current process to _user_. Not
5203  * available on all platforms.
5204  *
5205  */
5206 
5207 static VALUE
5208 p_sys_setuid(VALUE obj, VALUE id)
5209 {
5210  check_uid_switch();
5211  if (setuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
5212  return Qnil;
5213 }
5214 #else
5215 #define p_sys_setuid rb_f_notimplement
5216 #endif
5217 
5218 
5219 #if defined HAVE_SETRUID
5220 /*
5221  * call-seq:
5222  * Process::Sys.setruid(user) -> nil
5223  *
5224  * Set the real user ID of the calling process to _user_.
5225  * Not available on all platforms.
5226  *
5227  */
5228 
5229 static VALUE
5230 p_sys_setruid(VALUE obj, VALUE id)
5231 {
5232  check_uid_switch();
5233  if (setruid(OBJ2UID(id)) != 0) rb_sys_fail(0);
5234  return Qnil;
5235 }
5236 #else
5237 #define p_sys_setruid rb_f_notimplement
5238 #endif
5239 
5240 
5241 #if defined HAVE_SETEUID
5242 /*
5243  * call-seq:
5244  * Process::Sys.seteuid(user) -> nil
5245  *
5246  * Set the effective user ID of the calling process to
5247  * _user_. Not available on all platforms.
5248  *
5249  */
5250 
5251 static VALUE
5252 p_sys_seteuid(VALUE obj, VALUE id)
5253 {
5254  check_uid_switch();
5255  if (seteuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
5256  return Qnil;
5257 }
5258 #else
5259 #define p_sys_seteuid rb_f_notimplement
5260 #endif
5261 
5262 
5263 #if defined HAVE_SETREUID
5264 /*
5265  * call-seq:
5266  * Process::Sys.setreuid(rid, eid) -> nil
5267  *
5268  * Sets the (user) real and/or effective user IDs of the current
5269  * process to _rid_ and _eid_, respectively. A value of
5270  * <code>-1</code> for either means to leave that ID unchanged. Not
5271  * available on all platforms.
5272  *
5273  */
5274 
5275 static VALUE
5276 p_sys_setreuid(VALUE obj, VALUE rid, VALUE eid)
5277 {
5278  rb_uid_t ruid, euid;
5280  check_uid_switch();
5281  ruid = OBJ2UID1(rid);
5282  euid = OBJ2UID1(eid);
5284  if (setreuid(ruid, euid) != 0) rb_sys_fail(0);
5285  return Qnil;
5286 }
5287 #else
5288 #define p_sys_setreuid rb_f_notimplement
5289 #endif
5290 
5291 
5292 #if defined HAVE_SETRESUID
5293 /*
5294  * call-seq:
5295  * Process::Sys.setresuid(rid, eid, sid) -> nil
5296  *
5297  * Sets the (user) real, effective, and saved user IDs of the
5298  * current process to _rid_, _eid_, and _sid_ respectively. A
5299  * value of <code>-1</code> for any value means to
5300  * leave that ID unchanged. Not available on all platforms.
5301  *
5302  */
5303 
5304 static VALUE
5305 p_sys_setresuid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
5306 {
5307  rb_uid_t ruid, euid, suid;
5309  check_uid_switch();
5310  ruid = OBJ2UID1(rid);
5311  euid = OBJ2UID1(eid);
5312  suid = OBJ2UID1(sid);
5314  if (setresuid(ruid, euid, suid) != 0) rb_sys_fail(0);
5315  return Qnil;
5316 }
5317 #else
5318 #define p_sys_setresuid rb_f_notimplement
5319 #endif
5320 
5321 
5322 /*
5323  * call-seq:
5324  * Process.uid -> integer
5325  * Process::UID.rid -> integer
5326  * Process::Sys.getuid -> integer
5327  *
5328  * Returns the (real) user ID of this process.
5329  *
5330  * Process.uid #=> 501
5331  */
5332 
5333 static VALUE
5335 {
5336  rb_uid_t uid = getuid();
5337  return UIDT2NUM(uid);
5338 }
5339 
5340 
5341 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
5342 /*
5343  * call-seq:
5344  * Process.uid= user -> numeric
5345  *
5346  * Sets the (user) user ID for this process. Not available on all
5347  * platforms.
5348  */
5349 
5350 static VALUE
5351 proc_setuid(VALUE obj, VALUE id)
5352 {
5353  rb_uid_t uid;
5354 
5355  check_uid_switch();
5356 
5357  uid = OBJ2UID(id);
5358 #if defined(HAVE_SETRESUID)
5359  if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
5360 #elif defined HAVE_SETREUID
5361  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
5362 #elif defined HAVE_SETRUID
5363  if (setruid(uid) < 0) rb_sys_fail(0);
5364 #elif defined HAVE_SETUID
5365  {
5366  if (geteuid() == uid) {
5367  if (setuid(uid) < 0) rb_sys_fail(0);
5368  }
5369  else {
5370  rb_notimplement();
5371  }
5372  }
5373 #endif
5374  return id;
5375 }
5376 #else
5377 #define proc_setuid rb_f_notimplement
5378 #endif
5379 
5380 
5381 /********************************************************************
5382  *
5383  * Document-class: Process::UID
5384  *
5385  * The <code>Process::UID</code> module contains a collection of
5386  * module functions which can be used to portably get, set, and
5387  * switch the current process's real, effective, and saved user IDs.
5388  *
5389  */
5390 
5391 static rb_uid_t SAVED_USER_ID = -1;
5392 
5393 #ifdef BROKEN_SETREUID
5394 int
5395 setreuid(rb_uid_t ruid, rb_uid_t euid)
5396 {
5397  if (ruid != (rb_uid_t)-1 && ruid != getuid()) {
5398  if (euid == (rb_uid_t)-1) euid = geteuid();
5399  if (setuid(ruid) < 0) return -1;
5400  }
5401  if (euid != (rb_uid_t)-1 && euid != geteuid()) {
5402  if (seteuid(euid) < 0) return -1;
5403  }
5404  return 0;
5405 }
5406 #endif
5407 
5408 /*
5409  * call-seq:
5410  * Process::UID.change_privilege(user) -> integer
5411  *
5412  * Change the current process's real and effective user ID to that
5413  * specified by _user_. Returns the new user ID. Not
5414  * available on all platforms.
5415  *
5416  * [Process.uid, Process.euid] #=> [0, 0]
5417  * Process::UID.change_privilege(31) #=> 31
5418  * [Process.uid, Process.euid] #=> [31, 31]
5419  */
5420 
5421 static VALUE
5423 {
5424  rb_uid_t uid;
5425 
5426  check_uid_switch();
5427 
5428  uid = OBJ2UID(id);
5429 
5430  if (geteuid() == 0) { /* root-user */
5431 #if defined(HAVE_SETRESUID)
5432  if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
5433  SAVED_USER_ID = uid;
5434 #elif defined(HAVE_SETUID)
5435  if (setuid(uid) < 0) rb_sys_fail(0);
5436  SAVED_USER_ID = uid;
5437 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5438  if (getuid() == uid) {
5439  if (SAVED_USER_ID == uid) {
5440  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
5441  }
5442  else {
5443  if (uid == 0) { /* (r,e,s) == (root, root, x) */
5444  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
5445  if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
5446  SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
5447  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
5448  SAVED_USER_ID = uid;
5449  }
5450  else {
5451  if (setreuid(0, -1) < 0) rb_sys_fail(0);
5452  SAVED_USER_ID = 0;
5453  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
5454  SAVED_USER_ID = uid;
5455  }
5456  }
5457  }
5458  else {
5459  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
5460  SAVED_USER_ID = uid;
5461  }
5462 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
5463  if (getuid() == uid) {
5464  if (SAVED_USER_ID == uid) {
5465  if (seteuid(uid) < 0) rb_sys_fail(0);
5466  }
5467  else {
5468  if (uid == 0) {
5469  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
5470  SAVED_USER_ID = 0;
5471  if (setruid(0) < 0) rb_sys_fail(0);
5472  }
5473  else {
5474  if (setruid(0) < 0) rb_sys_fail(0);
5475  SAVED_USER_ID = 0;
5476  if (seteuid(uid) < 0) rb_sys_fail(0);
5477  if (setruid(uid) < 0) rb_sys_fail(0);
5478  SAVED_USER_ID = uid;
5479  }
5480  }
5481  }
5482  else {
5483  if (seteuid(uid) < 0) rb_sys_fail(0);
5484  if (setruid(uid) < 0) rb_sys_fail(0);
5485  SAVED_USER_ID = uid;
5486  }
5487 #else
5488  (void)uid;
5489  rb_notimplement();
5490 #endif
5491  }
5492  else { /* unprivileged user */
5493 #if defined(HAVE_SETRESUID)
5494  if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
5495  (geteuid() == uid)? (rb_uid_t)-1: uid,
5496  (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
5497  SAVED_USER_ID = uid;
5498 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5499  if (SAVED_USER_ID == uid) {
5500  if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
5501  (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5502  rb_sys_fail(0);
5503  }
5504  else if (getuid() != uid) {
5505  if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5506  rb_sys_fail(0);
5507  SAVED_USER_ID = uid;
5508  }
5509  else if (/* getuid() == uid && */ geteuid() != uid) {
5510  if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
5511  SAVED_USER_ID = uid;
5512  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
5513  }
5514  else { /* getuid() == uid && geteuid() == uid */
5515  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
5516  if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
5517  SAVED_USER_ID = uid;
5518  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
5519  }
5520 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
5521  if (SAVED_USER_ID == uid) {
5522  if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
5523  if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
5524  }
5525  else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
5526  if (getuid() != uid) {
5527  if (setruid(uid) < 0) rb_sys_fail(0);
5528  SAVED_USER_ID = uid;
5529  }
5530  else {
5531  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
5532  SAVED_USER_ID = uid;
5533  if (setruid(uid) < 0) rb_sys_fail(0);
5534  }
5535  }
5536  else if (/* geteuid() != uid && */ getuid() == uid) {
5537  if (seteuid(uid) < 0) rb_sys_fail(0);
5538  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
5539  SAVED_USER_ID = uid;
5540  if (setruid(uid) < 0) rb_sys_fail(0);
5541  }
5542  else {
5543  rb_syserr_fail(EPERM, 0);
5544  }
5545 #elif defined HAVE_44BSD_SETUID
5546  if (getuid() == uid) {
5547  /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
5548  if (setuid(uid) < 0) rb_sys_fail(0);
5549  SAVED_USER_ID = uid;
5550  }
5551  else {
5552  rb_syserr_fail(EPERM, 0);
5553  }
5554 #elif defined HAVE_SETEUID
5555  if (getuid() == uid && SAVED_USER_ID == uid) {
5556  if (seteuid(uid) < 0) rb_sys_fail(0);
5557  }
5558  else {
5559  rb_syserr_fail(EPERM, 0);
5560  }
5561 #elif defined HAVE_SETUID
5562  if (getuid() == uid && SAVED_USER_ID == uid) {
5563  if (setuid(uid) < 0) rb_sys_fail(0);
5564  }
5565  else {
5566  rb_syserr_fail(EPERM, 0);
5567  }
5568 #else
5569  rb_notimplement();
5570 #endif
5571  }
5572  return id;
5573 }
5574 
5575 
5576 
5577 #if defined HAVE_SETGID
5578 /*
5579  * call-seq:
5580  * Process::Sys.setgid(group) -> nil
5581  *
5582  * Set the group ID of the current process to _group_. Not
5583  * available on all platforms.
5584  *
5585  */
5586 
5587 static VALUE
5588 p_sys_setgid(VALUE obj, VALUE id)
5589 {
5590  check_gid_switch();
5591  if (setgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
5592  return Qnil;
5593 }
5594 #else
5595 #define p_sys_setgid rb_f_notimplement
5596 #endif
5597 
5598 
5599 #if defined HAVE_SETRGID
5600 /*
5601  * call-seq:
5602  * Process::Sys.setrgid(group) -> nil
5603  *
5604  * Set the real group ID of the calling process to _group_.
5605  * Not available on all platforms.
5606  *
5607  */
5608 
5609 static VALUE
5610 p_sys_setrgid(VALUE obj, VALUE id)
5611 {
5612  check_gid_switch();
5613  if (setrgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
5614  return Qnil;
5615 }
5616 #else
5617 #define p_sys_setrgid rb_f_notimplement
5618 #endif
5619 
5620 
5621 #if defined HAVE_SETEGID
5622 /*
5623  * call-seq:
5624  * Process::Sys.setegid(group) -> nil
5625  *
5626  * Set the effective group ID of the calling process to
5627  * _group_. Not available on all platforms.
5628  *
5629  */
5630 
5631 static VALUE
5632 p_sys_setegid(VALUE obj, VALUE id)
5633 {
5634  check_gid_switch();
5635  if (setegid(OBJ2GID(id)) != 0) rb_sys_fail(0);
5636  return Qnil;
5637 }
5638 #else
5639 #define p_sys_setegid rb_f_notimplement
5640 #endif
5641 
5642 
5643 #if defined HAVE_SETREGID
5644 /*
5645  * call-seq:
5646  * Process::Sys.setregid(rid, eid) -> nil
5647  *
5648  * Sets the (group) real and/or effective group IDs of the current
5649  * process to <em>rid</em> and <em>eid</em>, respectively. A value of
5650  * <code>-1</code> for either means to leave that ID unchanged. Not
5651  * available on all platforms.
5652  *
5653  */
5654 
5655 static VALUE
5656 p_sys_setregid(VALUE obj, VALUE rid, VALUE eid)
5657 {
5658  rb_gid_t rgid, egid;
5660  check_gid_switch();
5661  rgid = OBJ2GID(rid);
5662  egid = OBJ2GID(eid);
5664  if (setregid(rgid, egid) != 0) rb_sys_fail(0);
5665  return Qnil;
5666 }
5667 #else
5668 #define p_sys_setregid rb_f_notimplement
5669 #endif
5670 
5671 #if defined HAVE_SETRESGID
5672 /*
5673  * call-seq:
5674  * Process::Sys.setresgid(rid, eid, sid) -> nil
5675  *
5676  * Sets the (group) real, effective, and saved user IDs of the
5677  * current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
5678  * respectively. A value of <code>-1</code> for any value means to
5679  * leave that ID unchanged. Not available on all platforms.
5680  *
5681  */
5682 
5683 static VALUE
5684 p_sys_setresgid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
5685 {
5686  rb_gid_t rgid, egid, sgid;
5688  check_gid_switch();
5689  rgid = OBJ2GID(rid);
5690  egid = OBJ2GID(eid);
5691  sgid = OBJ2GID(sid);
5693  if (setresgid(rgid, egid, sgid) != 0) rb_sys_fail(0);
5694  return Qnil;
5695 }
5696 #else
5697 #define p_sys_setresgid rb_f_notimplement
5698 #endif
5699 
5700 
5701 #if defined HAVE_ISSETUGID
5702 /*
5703  * call-seq:
5704  * Process::Sys.issetugid -> true or false
5705  *
5706  * Returns +true+ if the process was created as a result
5707  * of an execve(2) system call which had either of the setuid or
5708  * setgid bits set (and extra privileges were given as a result) or
5709  * if it has changed any of its real, effective or saved user or
5710  * group IDs since it began execution.
5711  *
5712  */
5713 
5714 static VALUE
5716 {
5717  if (issetugid()) {
5718  return Qtrue;
5719  }
5720  else {
5721  return Qfalse;
5722  }
5723 }
5724 #else
5725 #define p_sys_issetugid rb_f_notimplement
5726 #endif
5727 
5728 
5729 /*
5730  * call-seq:
5731  * Process.gid -> integer
5732  * Process::GID.rid -> integer
5733  * Process::Sys.getgid -> integer
5734  *
5735  * Returns the (real) group ID for this process.
5736  *
5737  * Process.gid #=> 500
5738  */
5739 
5740 static VALUE
5742 {
5743  rb_gid_t gid = getgid();
5744  return GIDT2NUM(gid);
5745 }
5746 
5747 
5748 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
5749 /*
5750  * call-seq:
5751  * Process.gid= integer -> integer
5752  *
5753  * Sets the group ID for this process.
5754  */
5755 
5756 static VALUE
5757 proc_setgid(VALUE obj, VALUE id)
5758 {
5759  rb_gid_t gid;
5760 
5761  check_gid_switch();
5762 
5763  gid = OBJ2GID(id);
5764 #if defined(HAVE_SETRESGID)
5765  if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
5766 #elif defined HAVE_SETREGID
5767  if (setregid(gid, -1) < 0) rb_sys_fail(0);
5768 #elif defined HAVE_SETRGID
5769  if (setrgid(gid) < 0) rb_sys_fail(0);
5770 #elif defined HAVE_SETGID
5771  {
5772  if (getegid() == gid) {
5773  if (setgid(gid) < 0) rb_sys_fail(0);
5774  }
5775  else {
5776  rb_notimplement();
5777  }
5778  }
5779 #endif
5780  return GIDT2NUM(gid);
5781 }
5782 #else
5783 #define proc_setgid rb_f_notimplement
5784 #endif
5785 
5786 
5787 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
5788 /*
5789  * Maximum supplementary groups are platform dependent.
5790  * FWIW, 65536 is enough big for our supported OSs.
5791  *
5792  * OS Name max groups
5793  * -----------------------------------------------
5794  * Linux Kernel >= 2.6.3 65536
5795  * Linux Kernel < 2.6.3 32
5796  * IBM AIX 5.2 64
5797  * IBM AIX 5.3 ... 6.1 128
5798  * IBM AIX 7.1 128 (can be configured to be up to 2048)
5799  * OpenBSD, NetBSD 16
5800  * FreeBSD < 8.0 16
5801  * FreeBSD >=8.0 1023
5802  * Darwin (Mac OS X) 16
5803  * Sun Solaris 7,8,9,10 16
5804  * Sun Solaris 11 / OpenSolaris 1024
5805  * HP-UX 20
5806  * Windows 1015
5807  */
5808 static int _maxgroups = -1;
5809 static int
5810 get_sc_ngroups_max(void)
5811 {
5812 #ifdef _SC_NGROUPS_MAX
5813  return (int)sysconf(_SC_NGROUPS_MAX);
5814 #elif defined(NGROUPS_MAX)
5815  return (int)NGROUPS_MAX;
5816 #else
5817  return -1;
5818 #endif
5819 }
5820 static int
5821 maxgroups(void)
5822 {
5823  if (_maxgroups < 0) {
5824  _maxgroups = get_sc_ngroups_max();
5825  if (_maxgroups < 0)
5826  _maxgroups = RB_MAX_GROUPS;
5827  }
5828 
5829  return _maxgroups;
5830 }
5831 #endif
5832 
5833 
5834 
5835 #ifdef HAVE_GETGROUPS
5836 /*
5837  * call-seq:
5838  * Process.groups -> array
5839  *
5840  * Get an <code>Array</code> of the gids of groups in the
5841  * supplemental group access list for this process.
5842  *
5843  * Process.groups #=> [27, 6, 10, 11]
5844  *
5845  */
5846 
5847 static VALUE
5848 proc_getgroups(VALUE obj)
5849 {
5850  VALUE ary, tmp;
5851  int i, ngroups;
5852  rb_gid_t *groups;
5853 
5854  ngroups = getgroups(0, NULL);
5855  if (ngroups == -1)
5856  rb_sys_fail(0);
5857 
5858  groups = ALLOCV_N(rb_gid_t, tmp, ngroups);
5859 
5860  ngroups = getgroups(ngroups, groups);
5861  if (ngroups == -1)
5862  rb_sys_fail(0);
5863 
5864  ary = rb_ary_new();
5865  for (i = 0; i < ngroups; i++)
5866  rb_ary_push(ary, GIDT2NUM(groups[i]));
5867 
5868  ALLOCV_END(tmp);
5869 
5870  return ary;
5871 }
5872 #else
5873 #define proc_getgroups rb_f_notimplement
5874 #endif
5875 
5876 
5877 #ifdef HAVE_SETGROUPS
5878 /*
5879  * call-seq:
5880  * Process.groups= array -> array
5881  *
5882  * Set the supplemental group access list to the given
5883  * <code>Array</code> of group IDs.
5884  *
5885  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
5886  * Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11]
5887  * Process.groups #=> [27, 6, 10, 11]
5888  *
5889  */
5890 
5891 static VALUE
5892 proc_setgroups(VALUE obj, VALUE ary)
5893 {
5894  int ngroups, i;
5895  rb_gid_t *groups;
5896  VALUE tmp;
5898 
5899  Check_Type(ary, T_ARRAY);
5900 
5901  ngroups = RARRAY_LENINT(ary);
5902  if (ngroups > maxgroups())
5903  rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());
5904 
5905  groups = ALLOCV_N(rb_gid_t, tmp, ngroups);
5906 
5907  for (i = 0; i < ngroups; i++) {
5908  VALUE g = RARRAY_AREF(ary, i);
5909 
5910  groups[i] = OBJ2GID1(g);
5911  }
5913 
5914  if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
5915  rb_sys_fail(0);
5916 
5917  ALLOCV_END(tmp);
5918 
5919  return proc_getgroups(obj);
5920 }
5921 #else
5922 #define proc_setgroups rb_f_notimplement
5923 #endif
5924 
5925 
5926 #ifdef HAVE_INITGROUPS
5927 /*
5928  * call-seq:
5929  * Process.initgroups(username, gid) -> array
5930  *
5931  * Initializes the supplemental group access list by reading the
5932  * system group database and using all groups of which the given user
5933  * is a member. The group with the specified <em>gid</em> is also
5934  * added to the list. Returns the resulting <code>Array</code> of the
5935  * gids of all the groups in the supplementary group access list. Not
5936  * available on all platforms.
5937  *
5938  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
5939  * Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
5940  * Process.groups #=> [30, 6, 10, 11]
5941  *
5942  */
5943 
5944 static VALUE
5945 proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
5946 {
5947  if (initgroups(StringValuePtr(uname), OBJ2GID(base_grp)) != 0) {
5948  rb_sys_fail(0);
5949  }
5950  return proc_getgroups(obj);
5951 }
5952 #else
5953 #define proc_initgroups rb_f_notimplement
5954 #endif
5955 
5956 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
5957 /*
5958  * call-seq:
5959  * Process.maxgroups -> integer
5960  *
5961  * Returns the maximum number of gids allowed in the supplemental
5962  * group access list.
5963  *
5964  * Process.maxgroups #=> 32
5965  */
5966 
5967 static VALUE
5969 {
5970  return INT2FIX(maxgroups());
5971 }
5972 #else
5973 #define proc_getmaxgroups rb_f_notimplement
5974 #endif
5975 
5976 #ifdef HAVE_SETGROUPS
5977 /*
5978  * call-seq:
5979  * Process.maxgroups= integer -> integer
5980  *
5981  * Sets the maximum number of gids allowed in the supplemental group
5982  * access list.
5983  */
5984 
5985 static VALUE
5987 {
5988  int ngroups = FIX2INT(val);
5989  int ngroups_max = get_sc_ngroups_max();
5990 
5991  if (ngroups <= 0)
5992  rb_raise(rb_eArgError, "maxgroups %d shold be positive", ngroups);
5993 
5994  if (ngroups > RB_MAX_GROUPS)
5995  ngroups = RB_MAX_GROUPS;
5996 
5997  if (ngroups_max > 0 && ngroups > ngroups_max)
5998  ngroups = ngroups_max;
5999 
6000  _maxgroups = ngroups;
6001 
6002  return INT2FIX(_maxgroups);
6003 }
6004 #else
6005 #define proc_setmaxgroups rb_f_notimplement
6006 #endif
6007 
6008 #if defined(HAVE_DAEMON) || (defined(HAVE_WORKING_FORK) && defined(HAVE_SETSID))
6009 static int rb_daemon(int nochdir, int noclose);
6010 
6011 /*
6012  * call-seq:
6013  * Process.daemon() -> 0
6014  * Process.daemon(nochdir=nil,noclose=nil) -> 0
6015  *
6016  * Detach the process from controlling terminal and run in
6017  * the background as system daemon. Unless the argument
6018  * nochdir is true (i.e. non false), it changes the current
6019  * working directory to the root ("/"). Unless the argument
6020  * noclose is true, daemon() will redirect standard input,
6021  * standard output and standard error to /dev/null.
6022  * Return zero on success, or raise one of Errno::*.
6023  */
6024 
6025 static VALUE
6026 proc_daemon(int argc, VALUE *argv)
6027 {
6028  int n, nochdir = FALSE, noclose = FALSE;
6029 
6030  switch (rb_check_arity(argc, 0, 2)) {
6031  case 2: noclose = RTEST(argv[1]);
6032  case 1: nochdir = RTEST(argv[0]);
6033  }
6034 
6035  prefork();
6036  n = rb_daemon(nochdir, noclose);
6037  if (n < 0) rb_sys_fail("daemon");
6038  return INT2FIX(n);
6039 }
6040 
6041 static int
6042 rb_daemon(int nochdir, int noclose)
6043 {
6044  int err = 0;
6045 #ifdef HAVE_DAEMON
6046  before_fork_ruby();
6047  err = daemon(nochdir, noclose);
6048  after_fork_ruby();
6049  rb_thread_atfork();
6050 #else
6051  int n;
6052 
6053 #define fork_daemon() \
6054  switch (rb_fork_ruby(NULL)) { \
6055  case -1: return -1; \
6056  case 0: rb_thread_atfork(); break; \
6057  default: _exit(EXIT_SUCCESS); \
6058  }
6059 
6060  fork_daemon();
6061 
6062  if (setsid() < 0) return -1;
6063 
6064  /* must not be process-leader */
6065  fork_daemon();
6066 
6067  if (!nochdir)
6068  err = chdir("/");
6069 
6070  if (!noclose && (n = rb_cloexec_open("/dev/null", O_RDWR, 0)) != -1) {
6071  rb_update_max_fd(n);
6072  (void)dup2(n, 0);
6073  (void)dup2(n, 1);
6074  (void)dup2(n, 2);
6075  if (n > 2)
6076  (void)close (n);
6077  }
6078 #endif
6079  return err;
6080 }
6081 #else
6082 #define proc_daemon rb_f_notimplement
6083 #endif
6084 
6085 /********************************************************************
6086  *
6087  * Document-class: Process::GID
6088  *
6089  * The <code>Process::GID</code> module contains a collection of
6090  * module functions which can be used to portably get, set, and
6091  * switch the current process's real, effective, and saved group IDs.
6092  *
6093  */
6094 
6095 static rb_gid_t SAVED_GROUP_ID = -1;
6096 
6097 #ifdef BROKEN_SETREGID
6098 int
6099 setregid(rb_gid_t rgid, rb_gid_t egid)
6100 {
6101  if (rgid != (rb_gid_t)-1 && rgid != getgid()) {
6102  if (egid == (rb_gid_t)-1) egid = getegid();
6103  if (setgid(rgid) < 0) return -1;
6104  }
6105  if (egid != (rb_gid_t)-1 && egid != getegid()) {
6106  if (setegid(egid) < 0) return -1;
6107  }
6108  return 0;
6109 }
6110 #endif
6111 
6112 /*
6113  * call-seq:
6114  * Process::GID.change_privilege(group) -> integer
6115  *
6116  * Change the current process's real and effective group ID to that
6117  * specified by _group_. Returns the new group ID. Not
6118  * available on all platforms.
6119  *
6120  * [Process.gid, Process.egid] #=> [0, 0]
6121  * Process::GID.change_privilege(33) #=> 33
6122  * [Process.gid, Process.egid] #=> [33, 33]
6123  */
6124 
6125 static VALUE
6127 {
6128  rb_gid_t gid;
6129 
6130  check_gid_switch();
6131 
6132  gid = OBJ2GID(id);
6133 
6134  if (geteuid() == 0) { /* root-user */
6135 #if defined(HAVE_SETRESGID)
6136  if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
6137  SAVED_GROUP_ID = gid;
6138 #elif defined HAVE_SETGID
6139  if (setgid(gid) < 0) rb_sys_fail(0);
6140  SAVED_GROUP_ID = gid;
6141 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6142  if (getgid() == gid) {
6143  if (SAVED_GROUP_ID == gid) {
6144  if (setregid(-1, gid) < 0) rb_sys_fail(0);
6145  }
6146  else {
6147  if (gid == 0) { /* (r,e,s) == (root, y, x) */
6148  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6149  if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
6150  SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
6151  if (setregid(gid, gid) < 0) rb_sys_fail(0);
6152  SAVED_GROUP_ID = gid;
6153  }
6154  else { /* (r,e,s) == (z, y, x) */
6155  if (setregid(0, 0) < 0) rb_sys_fail(0);
6156  SAVED_GROUP_ID = 0;
6157  if (setregid(gid, gid) < 0) rb_sys_fail(0);
6158  SAVED_GROUP_ID = gid;
6159  }
6160  }
6161  }
6162  else {
6163  if (setregid(gid, gid) < 0) rb_sys_fail(0);
6164  SAVED_GROUP_ID = gid;
6165  }
6166 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
6167  if (getgid() == gid) {
6168  if (SAVED_GROUP_ID == gid) {
6169  if (setegid(gid) < 0) rb_sys_fail(0);
6170  }
6171  else {
6172  if (gid == 0) {
6173  if (setegid(gid) < 0) rb_sys_fail(0);
6174  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6175  SAVED_GROUP_ID = 0;
6176  if (setrgid(0) < 0) rb_sys_fail(0);
6177  }
6178  else {
6179  if (setrgid(0) < 0) rb_sys_fail(0);
6180  SAVED_GROUP_ID = 0;
6181  if (setegid(gid) < 0) rb_sys_fail(0);
6182  if (setrgid(gid) < 0) rb_sys_fail(0);
6183  SAVED_GROUP_ID = gid;
6184  }
6185  }
6186  }
6187  else {
6188  if (setegid(gid) < 0) rb_sys_fail(0);
6189  if (setrgid(gid) < 0) rb_sys_fail(0);
6190  SAVED_GROUP_ID = gid;
6191  }
6192 #else
6193  rb_notimplement();
6194 #endif
6195  }
6196  else { /* unprivileged user */
6197 #if defined(HAVE_SETRESGID)
6198  if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
6199  (getegid() == gid)? (rb_gid_t)-1: gid,
6200  (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
6201  SAVED_GROUP_ID = gid;
6202 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6203  if (SAVED_GROUP_ID == gid) {
6204  if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
6205  (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
6206  rb_sys_fail(0);
6207  }
6208  else if (getgid() != gid) {
6209  if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
6210  rb_sys_fail(0);
6211  SAVED_GROUP_ID = gid;
6212  }
6213  else if (/* getgid() == gid && */ getegid() != gid) {
6214  if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
6215  SAVED_GROUP_ID = gid;
6216  if (setregid(gid, -1) < 0) rb_sys_fail(0);
6217  }
6218  else { /* getgid() == gid && getegid() == gid */
6219  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6220  if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
6221  SAVED_GROUP_ID = gid;
6222  if (setregid(gid, -1) < 0) rb_sys_fail(0);
6223  }
6224 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
6225  if (SAVED_GROUP_ID == gid) {
6226  if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
6227  if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
6228  }
6229  else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
6230  if (getgid() != gid) {
6231  if (setrgid(gid) < 0) rb_sys_fail(0);
6232  SAVED_GROUP_ID = gid;
6233  }
6234  else {
6235  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6236  SAVED_GROUP_ID = gid;
6237  if (setrgid(gid) < 0) rb_sys_fail(0);
6238  }
6239  }
6240  else if (/* getegid() != gid && */ getgid() == gid) {
6241  if (setegid(gid) < 0) rb_sys_fail(0);
6242  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
6243  SAVED_GROUP_ID = gid;
6244  if (setrgid(gid) < 0) rb_sys_fail(0);
6245  }
6246  else {
6247  rb_syserr_fail(EPERM, 0);
6248  }
6249 #elif defined HAVE_44BSD_SETGID
6250  if (getgid() == gid) {
6251  /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
6252  if (setgid(gid) < 0) rb_sys_fail(0);
6253  SAVED_GROUP_ID = gid;
6254  }
6255  else {
6256  rb_syserr_fail(EPERM, 0);
6257  }
6258 #elif defined HAVE_SETEGID
6259  if (getgid() == gid && SAVED_GROUP_ID == gid) {
6260  if (setegid(gid) < 0) rb_sys_fail(0);
6261  }
6262  else {
6263  rb_syserr_fail(EPERM, 0);
6264  }
6265 #elif defined HAVE_SETGID
6266  if (getgid() == gid && SAVED_GROUP_ID == gid) {
6267  if (setgid(gid) < 0) rb_sys_fail(0);
6268  }
6269  else {
6270  rb_syserr_fail(EPERM, 0);
6271  }
6272 #else
6273  (void)gid;
6274  rb_notimplement();
6275 #endif
6276  }
6277  return id;
6278 }
6279 
6280 
6281 /*
6282  * call-seq:
6283  * Process.euid -> integer
6284  * Process::UID.eid -> integer
6285  * Process::Sys.geteuid -> integer
6286  *
6287  * Returns the effective user ID for this process.
6288  *
6289  * Process.euid #=> 501
6290  */
6291 
6292 static VALUE
6294 {
6295  rb_uid_t euid = geteuid();
6296  return UIDT2NUM(euid);
6297 }
6298 
6299 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
6300 static void
6301 proc_seteuid(rb_uid_t uid)
6302 {
6303 #if defined(HAVE_SETRESUID)
6304  if (setresuid(-1, uid, -1) < 0) rb_sys_fail(0);
6305 #elif defined HAVE_SETREUID
6306  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
6307 #elif defined HAVE_SETEUID
6308  if (seteuid(uid) < 0) rb_sys_fail(0);
6309 #elif defined HAVE_SETUID
6310  if (uid == getuid()) {
6311  if (setuid(uid) < 0) rb_sys_fail(0);
6312  }
6313  else {
6314  rb_notimplement();
6315  }
6316 #else
6317  rb_notimplement();
6318 #endif
6319 }
6320 #endif
6321 
6322 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
6323 /*
6324  * call-seq:
6325  * Process.euid= user
6326  *
6327  * Sets the effective user ID for this process. Not available on all
6328  * platforms.
6329  */
6330 
6331 static VALUE
6333 {
6334  check_uid_switch();
6335  proc_seteuid(OBJ2UID(euid));
6336  return euid;
6337 }
6338 #else
6339 #define proc_seteuid_m rb_f_notimplement
6340 #endif
6341 
6342 static rb_uid_t
6343 rb_seteuid_core(rb_uid_t euid)
6344 {
6345 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6346  rb_uid_t uid;
6347 #endif
6348 
6349  check_uid_switch();
6350 
6351 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6352  uid = getuid();
6353 #endif
6354 
6355 #if defined(HAVE_SETRESUID)
6356  if (uid != euid) {
6357  if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
6358  SAVED_USER_ID = euid;
6359  }
6360  else {
6361  if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
6362  }
6363 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6364  if (setreuid(-1, euid) < 0) rb_sys_fail(0);
6365  if (uid != euid) {
6366  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
6367  if (setreuid(uid,euid) < 0) rb_sys_fail(0);
6368  SAVED_USER_ID = euid;
6369  }
6370 #elif defined HAVE_SETEUID
6371  if (seteuid(euid) < 0) rb_sys_fail(0);
6372 #elif defined HAVE_SETUID
6373  if (geteuid() == 0) rb_sys_fail(0);
6374  if (setuid(euid) < 0) rb_sys_fail(0);
6375 #else
6376  rb_notimplement();
6377 #endif
6378  return euid;
6379 }
6380 
6381 
6382 /*
6383  * call-seq:
6384  * Process::UID.grant_privilege(user) -> integer
6385  * Process::UID.eid= user -> integer
6386  *
6387  * Set the effective user ID, and if possible, the saved user ID of
6388  * the process to the given _user_. Returns the new
6389  * effective user ID. Not available on all platforms.
6390  *
6391  * [Process.uid, Process.euid] #=> [0, 0]
6392  * Process::UID.grant_privilege(31) #=> 31
6393  * [Process.uid, Process.euid] #=> [0, 31]
6394  */
6395 
6396 static VALUE
6398 {
6399  rb_seteuid_core(OBJ2UID(id));
6400  return id;
6401 }
6402 
6403 
6404 /*
6405  * call-seq:
6406  * Process.egid -> integer
6407  * Process::GID.eid -> integer
6408  * Process::Sys.geteid -> integer
6409  *
6410  * Returns the effective group ID for this process. Not available on
6411  * all platforms.
6412  *
6413  * Process.egid #=> 500
6414  */
6415 
6416 static VALUE
6418 {
6419  rb_gid_t egid = getegid();
6420 
6421  return GIDT2NUM(egid);
6422 }
6423 
6424 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
6425 /*
6426  * call-seq:
6427  * Process.egid = integer -> integer
6428  *
6429  * Sets the effective group ID for this process. Not available on all
6430  * platforms.
6431  */
6432 
6433 static VALUE
6434 proc_setegid(VALUE obj, VALUE egid)
6435 {
6436 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6437  rb_gid_t gid;
6438 #endif
6439 
6440  check_gid_switch();
6441 
6442 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6443  gid = OBJ2GID(egid);
6444 #endif
6445 
6446 #if defined(HAVE_SETRESGID)
6447  if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
6448 #elif defined HAVE_SETREGID
6449  if (setregid(-1, gid) < 0) rb_sys_fail(0);
6450 #elif defined HAVE_SETEGID
6451  if (setegid(gid) < 0) rb_sys_fail(0);
6452 #elif defined HAVE_SETGID
6453  if (gid == getgid()) {
6454  if (setgid(gid) < 0) rb_sys_fail(0);
6455  }
6456  else {
6457  rb_notimplement();
6458  }
6459 #else
6460  rb_notimplement();
6461 #endif
6462  return egid;
6463 }
6464 #endif
6465 
6466 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6467 #define proc_setegid_m proc_setegid
6468 #else
6469 #define proc_setegid_m rb_f_notimplement
6470 #endif
6471 
6472 static rb_gid_t
6473 rb_setegid_core(rb_gid_t egid)
6474 {
6475 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6476  rb_gid_t gid;
6477 #endif
6478 
6479  check_gid_switch();
6480 
6481 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6482  gid = getgid();
6483 #endif
6484 
6485 #if defined(HAVE_SETRESGID)
6486  if (gid != egid) {
6487  if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
6488  SAVED_GROUP_ID = egid;
6489  }
6490  else {
6491  if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
6492  }
6493 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6494  if (setregid(-1, egid) < 0) rb_sys_fail(0);
6495  if (gid != egid) {
6496  if (setregid(egid,gid) < 0) rb_sys_fail(0);
6497  if (setregid(gid,egid) < 0) rb_sys_fail(0);
6498  SAVED_GROUP_ID = egid;
6499  }
6500 #elif defined HAVE_SETEGID
6501  if (setegid(egid) < 0) rb_sys_fail(0);
6502 #elif defined HAVE_SETGID
6503  if (geteuid() == 0 /* root user */) rb_sys_fail(0);
6504  if (setgid(egid) < 0) rb_sys_fail(0);
6505 #else
6506  rb_notimplement();
6507 #endif
6508  return egid;
6509 }
6510 
6511 
6512 /*
6513  * call-seq:
6514  * Process::GID.grant_privilege(group) -> integer
6515  * Process::GID.eid = group -> integer
6516  *
6517  * Set the effective group ID, and if possible, the saved group ID of
6518  * the process to the given _group_. Returns the new
6519  * effective group ID. Not available on all platforms.
6520  *
6521  * [Process.gid, Process.egid] #=> [0, 0]
6522  * Process::GID.grant_privilege(31) #=> 33
6523  * [Process.gid, Process.egid] #=> [0, 33]
6524  */
6525 
6526 static VALUE
6528 {
6529  rb_setegid_core(OBJ2GID(id));
6530  return id;
6531 }
6532 
6533 
6534 /*
6535  * call-seq:
6536  * Process::UID.re_exchangeable? -> true or false
6537  *
6538  * Returns +true+ if the real and effective user IDs of a
6539  * process may be exchanged on the current platform.
6540  *
6541  */
6542 
6543 static VALUE
6545 {
6546 #if defined(HAVE_SETRESUID)
6547  return Qtrue;
6548 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6549  return Qtrue;
6550 #else
6551  return Qfalse;
6552 #endif
6553 }
6554 
6555 
6556 /*
6557  * call-seq:
6558  * Process::UID.re_exchange -> integer
6559  *
6560  * Exchange real and effective user IDs and return the new effective
6561  * user ID. Not available on all platforms.
6562  *
6563  * [Process.uid, Process.euid] #=> [0, 31]
6564  * Process::UID.re_exchange #=> 0
6565  * [Process.uid, Process.euid] #=> [31, 0]
6566  */
6567 
6568 static VALUE
6570 {
6571  rb_uid_t uid;
6572 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6573  rb_uid_t euid;
6574 #endif
6575 
6576  check_uid_switch();
6577 
6578  uid = getuid();
6579 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6580  euid = geteuid();
6581 #endif
6582 
6583 #if defined(HAVE_SETRESUID)
6584  if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
6585  SAVED_USER_ID = uid;
6586 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6587  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
6588  SAVED_USER_ID = uid;
6589 #else
6590  rb_notimplement();
6591 #endif
6592  return UIDT2NUM(uid);
6593 }
6594 
6595 
6596 /*
6597  * call-seq:
6598  * Process::GID.re_exchangeable? -> true or false
6599  *
6600  * Returns +true+ if the real and effective group IDs of a
6601  * process may be exchanged on the current platform.
6602  *
6603  */
6604 
6605 static VALUE
6607 {
6608 #if defined(HAVE_SETRESGID)
6609  return Qtrue;
6610 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6611  return Qtrue;
6612 #else
6613  return Qfalse;
6614 #endif
6615 }
6616 
6617 
6618 /*
6619  * call-seq:
6620  * Process::GID.re_exchange -> integer
6621  *
6622  * Exchange real and effective group IDs and return the new effective
6623  * group ID. Not available on all platforms.
6624  *
6625  * [Process.gid, Process.egid] #=> [0, 33]
6626  * Process::GID.re_exchange #=> 0
6627  * [Process.gid, Process.egid] #=> [33, 0]
6628  */
6629 
6630 static VALUE
6632 {
6633  rb_gid_t gid;
6634 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6635  rb_gid_t egid;
6636 #endif
6637 
6638  check_gid_switch();
6639 
6640  gid = getgid();
6641 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6642  egid = getegid();
6643 #endif
6644 
6645 #if defined(HAVE_SETRESGID)
6646  if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
6647  SAVED_GROUP_ID = gid;
6648 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6649  if (setregid(egid,gid) < 0) rb_sys_fail(0);
6650  SAVED_GROUP_ID = gid;
6651 #else
6652  rb_notimplement();
6653 #endif
6654  return GIDT2NUM(gid);
6655 }
6656 
6657 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
6658 
6659 /*
6660  * call-seq:
6661  * Process::UID.sid_available? -> true or false
6662  *
6663  * Returns +true+ if the current platform has saved user
6664  * ID functionality.
6665  *
6666  */
6667 
6668 static VALUE
6670 {
6671 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
6672  return Qtrue;
6673 #else
6674  return Qfalse;
6675 #endif
6676 }
6677 
6678 
6679 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
6680 static VALUE
6681 p_uid_sw_ensure(rb_uid_t id)
6682 {
6683  under_uid_switch = 0;
6684  id = rb_seteuid_core(id);
6685  return UIDT2NUM(id);
6686 }
6687 
6688 
6689 /*
6690  * call-seq:
6691  * Process::UID.switch -> integer
6692  * Process::UID.switch {|| block} -> object
6693  *
6694  * Switch the effective and real user IDs of the current process. If
6695  * a <em>block</em> is given, the user IDs will be switched back
6696  * after the block is executed. Returns the new effective user ID if
6697  * called without a block, and the return value of the block if one
6698  * is given.
6699  *
6700  */
6701 
6702 static VALUE
6703 p_uid_switch(VALUE obj)
6704 {
6705  rb_uid_t uid, euid;
6706 
6707  check_uid_switch();
6708 
6709  uid = getuid();
6710  euid = geteuid();
6711 
6712  if (uid != euid) {
6713  proc_seteuid(uid);
6714  if (rb_block_given_p()) {
6715  under_uid_switch = 1;
6716  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
6717  }
6718  else {
6719  return UIDT2NUM(euid);
6720  }
6721  }
6722  else if (euid != SAVED_USER_ID) {
6723  proc_seteuid(SAVED_USER_ID);
6724  if (rb_block_given_p()) {
6725  under_uid_switch = 1;
6726  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
6727  }
6728  else {
6729  return UIDT2NUM(uid);
6730  }
6731  }
6732  else {
6733  rb_syserr_fail(EPERM, 0);
6734  }
6735 
6736  UNREACHABLE;
6737 }
6738 #else
6739 static VALUE
6741 {
6742  under_uid_switch = 0;
6743  return p_uid_exchange(obj);
6744 }
6745 
6746 static VALUE
6748 {
6749  rb_uid_t uid, euid;
6750 
6751  check_uid_switch();
6752 
6753  uid = getuid();
6754  euid = geteuid();
6755 
6756  if (uid == euid) {
6757  rb_syserr_fail(EPERM, 0);
6758  }
6759  p_uid_exchange(obj);
6760  if (rb_block_given_p()) {
6761  under_uid_switch = 1;
6762  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
6763  }
6764  else {
6765  return UIDT2NUM(euid);
6766  }
6767 }
6768 #endif
6769 
6770 
6771 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
6772 
6773 /*
6774  * call-seq:
6775  * Process::GID.sid_available? -> true or false
6776  *
6777  * Returns +true+ if the current platform has saved group
6778  * ID functionality.
6779  *
6780  */
6781 
6782 static VALUE
6784 {
6785 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
6786  return Qtrue;
6787 #else
6788  return Qfalse;
6789 #endif
6790 }
6791 
6792 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
6793 static VALUE
6794 p_gid_sw_ensure(rb_gid_t id)
6795 {
6796  under_gid_switch = 0;
6797  id = rb_setegid_core(id);
6798  return GIDT2NUM(id);
6799 }
6800 
6801 
6802 /*
6803  * call-seq:
6804  * Process::GID.switch -> integer
6805  * Process::GID.switch {|| block} -> object
6806  *
6807  * Switch the effective and real group IDs of the current process. If
6808  * a <em>block</em> is given, the group IDs will be switched back
6809  * after the block is executed. Returns the new effective group ID if
6810  * called without a block, and the return value of the block if one
6811  * is given.
6812  *
6813  */
6814 
6815 static VALUE
6816 p_gid_switch(VALUE obj)
6817 {
6818  rb_gid_t gid, egid;
6819 
6820  check_gid_switch();
6821 
6822  gid = getgid();
6823  egid = getegid();
6824 
6825  if (gid != egid) {
6826  proc_setegid(obj, GIDT2NUM(gid));
6827  if (rb_block_given_p()) {
6828  under_gid_switch = 1;
6829  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
6830  }
6831  else {
6832  return GIDT2NUM(egid);
6833  }
6834  }
6835  else if (egid != SAVED_GROUP_ID) {
6836  proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
6837  if (rb_block_given_p()) {
6838  under_gid_switch = 1;
6839  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
6840  }
6841  else {
6842  return GIDT2NUM(gid);
6843  }
6844  }
6845  else {
6846  rb_syserr_fail(EPERM, 0);
6847  }
6848 
6849  UNREACHABLE;
6850 }
6851 #else
6852 static VALUE
6854 {
6855  under_gid_switch = 0;
6856  return p_gid_exchange(obj);
6857 }
6858 
6859 static VALUE
6861 {
6862  rb_gid_t gid, egid;
6863 
6864  check_gid_switch();
6865 
6866  gid = getgid();
6867  egid = getegid();
6868 
6869  if (gid == egid) {
6870  rb_syserr_fail(EPERM, 0);
6871  }
6872  p_gid_exchange(obj);
6873  if (rb_block_given_p()) {
6874  under_gid_switch = 1;
6875  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
6876  }
6877  else {
6878  return GIDT2NUM(egid);
6879  }
6880 }
6881 #endif
6882 
6883 
6884 #if defined(HAVE_TIMES)
6885 static long
6886 get_clk_tck(void)
6887 {
6888  long hertz =
6889 #ifdef HAVE__SC_CLK_TCK
6890  (double)sysconf(_SC_CLK_TCK);
6891 #else
6892 #ifndef HZ
6893 # ifdef CLK_TCK
6894 # define HZ CLK_TCK
6895 # else
6896 # define HZ 60
6897 # endif
6898 #endif /* HZ */
6899  HZ;
6900 #endif
6901  return hertz;
6902 }
6903 
6904 /*
6905  * call-seq:
6906  * Process.times -> aProcessTms
6907  *
6908  * Returns a <code>Tms</code> structure (see <code>Process::Tms</code>)
6909  * that contains user and system CPU times for this process,
6910  * and also for children processes.
6911  *
6912  * t = Process.times
6913  * [ t.utime, t.stime, t.cutime, t.cstime ] #=> [0.0, 0.02, 0.00, 0.00]
6914  */
6915 
6916 VALUE
6917 rb_proc_times(VALUE obj)
6918 {
6919  const double hertz = get_clk_tck();
6920  struct tms buf;
6921  VALUE utime, stime, cutime, cstime, ret;
6922 
6923  times(&buf);
6924  utime = DBL2NUM(buf.tms_utime / hertz);
6925  stime = DBL2NUM(buf.tms_stime / hertz);
6926  cutime = DBL2NUM(buf.tms_cutime / hertz);
6927  cstime = DBL2NUM(buf.tms_cstime / hertz);
6928  ret = rb_struct_new(rb_cProcessTms, utime, stime, cutime, cstime);
6929  RB_GC_GUARD(utime);
6930  RB_GC_GUARD(stime);
6931  RB_GC_GUARD(cutime);
6932  RB_GC_GUARD(cstime);
6933  return ret;
6934 }
6935 #else
6936 #define rb_proc_times rb_f_notimplement
6937 #endif
6938 
6939 #ifdef HAVE_LONG_LONG
6940 typedef LONG_LONG timetick_int_t;
6941 #define TIMETICK_INT_MIN LLONG_MIN
6942 #define TIMETICK_INT_MAX LLONG_MAX
6943 #define TIMETICK_INT2NUM(v) LL2NUM(v)
6944 #else
6945 typedef long timetick_int_t;
6946 #define TIMETICK_INT_MIN LONG_MIN
6947 #define TIMETICK_INT_MAX LONG_MAX
6948 #define TIMETICK_INT2NUM(v) LONG2NUM(v)
6949 #endif
6950 
6951 CONSTFUNC(static timetick_int_t gcd_timetick_int(timetick_int_t, timetick_int_t));
6952 static timetick_int_t
6953 gcd_timetick_int(timetick_int_t a, timetick_int_t b)
6954 {
6955  timetick_int_t t;
6956 
6957  if (a < b) {
6958  t = a;
6959  a = b;
6960  b = t;
6961  }
6962 
6963  while (1) {
6964  t = a % b;
6965  if (t == 0)
6966  return b;
6967  a = b;
6968  b = t;
6969  }
6970 }
6971 
6972 static void
6973 reduce_fraction(timetick_int_t *np, timetick_int_t *dp)
6974 {
6975  timetick_int_t gcd = gcd_timetick_int(*np, *dp);
6976  if (gcd != 1) {
6977  *np /= gcd;
6978  *dp /= gcd;
6979  }
6980 }
6981 
6982 static void
6983 reduce_factors(timetick_int_t *numerators, int num_numerators,
6984  timetick_int_t *denominators, int num_denominators)
6985 {
6986  int i, j;
6987  for (i = 0; i < num_numerators; i++) {
6988  if (numerators[i] == 1)
6989  continue;
6990  for (j = 0; j < num_denominators; j++) {
6991  if (denominators[j] == 1)
6992  continue;
6993  reduce_fraction(&numerators[i], &denominators[j]);
6994  }
6995  }
6996 }
6997 
6998 struct timetick {
6999  timetick_int_t giga_count;
7000  int32_t count; /* 0 .. 999999999 */
7001 };
7002 
7003 static VALUE
7005  timetick_int_t *numerators, int num_numerators,
7006  timetick_int_t *denominators, int num_denominators)
7007 {
7008  double d;
7009  int i;
7010 
7011  reduce_factors(numerators, num_numerators,
7012  denominators, num_denominators);
7013 
7014  d = ttp->giga_count * 1e9 + ttp->count;
7015 
7016  for (i = 0; i < num_numerators; i++)
7017  d *= numerators[i];
7018  for (i = 0; i < num_denominators; i++)
7019  d /= denominators[i];
7020 
7021  return DBL2NUM(d);
7022 }
7023 
7024 static VALUE
7026  timetick_int_t *numerators, int num_numerators,
7027  timetick_int_t *denominators, int num_denominators)
7028 {
7029  double d;
7030  int i;
7031 
7032  reduce_factors(numerators, num_numerators,
7033  denominators, num_denominators);
7034 
7035  d = 1.0;
7036  for (i = 0; i < num_denominators; i++)
7037  d *= denominators[i];
7038  for (i = 0; i < num_numerators; i++)
7039  d /= numerators[i];
7040  d /= ttp->giga_count * 1e9 + ttp->count;
7041 
7042  return DBL2NUM(d);
7043 }
7044 
7045 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
7046 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
7047 
7048 static VALUE
7050  timetick_int_t *numerators, int num_numerators,
7051  timetick_int_t *denominators, int num_denominators)
7052 {
7053  VALUE v;
7054  int i;
7055 
7056  reduce_factors(numerators, num_numerators,
7057  denominators, num_denominators);
7058 
7059  if (!MUL_OVERFLOW_SIGNED_INTEGER_P(1000000000, ttp->giga_count,
7061  timetick_int_t t = ttp->giga_count * 1000000000 + ttp->count;
7062  for (i = 0; i < num_numerators; i++) {
7063  timetick_int_t factor = numerators[i];
7064  if (MUL_OVERFLOW_SIGNED_INTEGER_P(factor, t,
7066  goto generic;
7067  t *= factor;
7068  }
7069  for (i = 0; i < num_denominators; i++) {
7070  t = DIV(t, denominators[i]);
7071  }
7072  return TIMETICK_INT2NUM(t);
7073  }
7074 
7075  generic:
7076  v = TIMETICK_INT2NUM(ttp->giga_count);
7077  v = rb_funcall(v, '*', 1, LONG2FIX(1000000000));
7078  v = rb_funcall(v, '+', 1, LONG2FIX(ttp->count));
7079  for (i = 0; i < num_numerators; i++) {
7080  timetick_int_t factor = numerators[i];
7081  if (factor == 1)
7082  continue;
7083  v = rb_funcall(v, '*', 1, TIMETICK_INT2NUM(factor));
7084  }
7085  for (i = 0; i < num_denominators; i++) {
7086  v = rb_funcall(v, '/', 1, TIMETICK_INT2NUM(denominators[i])); /* Ruby's '/' is div. */
7087  }
7088  return v;
7089 }
7090 
7091 static VALUE
7093  timetick_int_t *numerators, int num_numerators,
7094  timetick_int_t *denominators, int num_denominators,
7095  VALUE unit)
7096 {
7097  if (unit == ID2SYM(id_nanosecond)) {
7098  numerators[num_numerators++] = 1000000000;
7099  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7100  }
7101  else if (unit == ID2SYM(id_microsecond)) {
7102  numerators[num_numerators++] = 1000000;
7103  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7104  }
7105  else if (unit == ID2SYM(id_millisecond)) {
7106  numerators[num_numerators++] = 1000;
7107  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7108  }
7109  else if (unit == ID2SYM(id_second)) {
7110  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7111  }
7112  else if (unit == ID2SYM(id_float_microsecond)) {
7113  numerators[num_numerators++] = 1000000;
7114  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7115  }
7116  else if (unit == ID2SYM(id_float_millisecond)) {
7117  numerators[num_numerators++] = 1000;
7118  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7119  }
7120  else if (NIL_P(unit) || unit == ID2SYM(id_float_second)) {
7121  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7122  }
7123  else
7124  rb_raise(rb_eArgError, "unexpected unit: %"PRIsVALUE, unit);
7125 }
7126 
7127 #ifdef __APPLE__
7128 static mach_timebase_info_data_t *
7129 get_mach_timebase_info(void)
7130 {
7131  static mach_timebase_info_data_t sTimebaseInfo;
7132 
7133  if ( sTimebaseInfo.denom == 0 ) {
7134  (void) mach_timebase_info(&sTimebaseInfo);
7135  }
7136 
7137  return &sTimebaseInfo;
7138 }
7139 #endif
7140 
7141 /*
7142  * call-seq:
7143  * Process.clock_gettime(clock_id [, unit]) -> number
7144  *
7145  * Returns a time returned by POSIX clock_gettime() function.
7146  *
7147  * p Process.clock_gettime(Process::CLOCK_MONOTONIC)
7148  * #=> 896053.968060096
7149  *
7150  * +clock_id+ specifies a kind of clock.
7151  * It is specified as a constant which begins with <code>Process::CLOCK_</code>
7152  * such as Process::CLOCK_REALTIME and Process::CLOCK_MONOTONIC.
7153  *
7154  * The supported constants depends on OS and version.
7155  * Ruby provides following types of +clock_id+ if available.
7156  *
7157  * [CLOCK_REALTIME] SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12
7158  * [CLOCK_MONOTONIC] SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12
7159  * [CLOCK_PROCESS_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, OpenBSD 5.4, macOS 10.12
7160  * [CLOCK_THREAD_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD 5.4, macOS 10.12
7161  * [CLOCK_VIRTUAL] FreeBSD 3.0, OpenBSD 2.1
7162  * [CLOCK_PROF] FreeBSD 3.0, OpenBSD 2.1
7163  * [CLOCK_REALTIME_FAST] FreeBSD 8.1
7164  * [CLOCK_REALTIME_PRECISE] FreeBSD 8.1
7165  * [CLOCK_REALTIME_COARSE] Linux 2.6.32
7166  * [CLOCK_REALTIME_ALARM] Linux 3.0
7167  * [CLOCK_MONOTONIC_FAST] FreeBSD 8.1
7168  * [CLOCK_MONOTONIC_PRECISE] FreeBSD 8.1
7169  * [CLOCK_MONOTONIC_COARSE] Linux 2.6.32
7170  * [CLOCK_MONOTONIC_RAW] Linux 2.6.28, macOS 10.12
7171  * [CLOCK_MONOTONIC_RAW_APPROX] macOS 10.12
7172  * [CLOCK_BOOTTIME] Linux 2.6.39
7173  * [CLOCK_BOOTTIME_ALARM] Linux 3.0
7174  * [CLOCK_UPTIME] FreeBSD 7.0, OpenBSD 5.5
7175  * [CLOCK_UPTIME_FAST] FreeBSD 8.1
7176  * [CLOCK_UPTIME_RAW] macOS 10.12
7177  * [CLOCK_UPTIME_RAW_APPROX] macOS 10.12
7178  * [CLOCK_UPTIME_PRECISE] FreeBSD 8.1
7179  * [CLOCK_SECOND] FreeBSD 8.1
7180  *
7181  * Note that SUS stands for Single Unix Specification.
7182  * SUS contains POSIX and clock_gettime is defined in the POSIX part.
7183  * SUS defines CLOCK_REALTIME mandatory but
7184  * CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID are optional.
7185  *
7186  * Also, several symbols are accepted as +clock_id+.
7187  * There are emulations for clock_gettime().
7188  *
7189  * For example, Process::CLOCK_REALTIME is defined as
7190  * +:GETTIMEOFDAY_BASED_CLOCK_REALTIME+ when clock_gettime() is not available.
7191  *
7192  * Emulations for +CLOCK_REALTIME+:
7193  * [:GETTIMEOFDAY_BASED_CLOCK_REALTIME]
7194  * Use gettimeofday() defined by SUS.
7195  * (SUSv4 obsoleted it, though.)
7196  * The resolution is 1 microsecond.
7197  * [:TIME_BASED_CLOCK_REALTIME]
7198  * Use time() defined by ISO C.
7199  * The resolution is 1 second.
7200  *
7201  * Emulations for +CLOCK_MONOTONIC+:
7202  * [:MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC]
7203  * Use mach_absolute_time(), available on Darwin.
7204  * The resolution is CPU dependent.
7205  * [:TIMES_BASED_CLOCK_MONOTONIC]
7206  * Use the result value of times() defined by POSIX.
7207  * 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)".
7208  * For example, GNU/Linux returns a value based on jiffies and it is monotonic.
7209  * However, 4.4BSD uses gettimeofday() and it is not monotonic.
7210  * (FreeBSD uses clock_gettime(CLOCK_MONOTONIC) instead, though.)
7211  * The resolution is the clock tick.
7212  * "getconf CLK_TCK" command shows the clock ticks per second.
7213  * (The clock ticks per second is defined by HZ macro in older systems.)
7214  * If it is 100 and clock_t is 32 bits integer type, the resolution is 10 millisecond and
7215  * cannot represent over 497 days.
7216  *
7217  * Emulations for +CLOCK_PROCESS_CPUTIME_ID+:
7218  * [:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID]
7219  * Use getrusage() defined by SUS.
7220  * getrusage() is used with RUSAGE_SELF to obtain the time only for
7221  * the calling process (excluding the time for child processes).
7222  * The result is addition of user time (ru_utime) and system time (ru_stime).
7223  * The resolution is 1 microsecond.
7224  * [:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID]
7225  * Use times() defined by POSIX.
7226  * The result is addition of user time (tms_utime) and system time (tms_stime).
7227  * tms_cutime and tms_cstime are ignored to exclude the time for child processes.
7228  * The resolution is the clock tick.
7229  * "getconf CLK_TCK" command shows the clock ticks per second.
7230  * (The clock ticks per second is defined by HZ macro in older systems.)
7231  * If it is 100, the resolution is 10 millisecond.
7232  * [:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID]
7233  * Use clock() defined by ISO C.
7234  * The resolution is 1/CLOCKS_PER_SEC.
7235  * CLOCKS_PER_SEC is the C-level macro defined by time.h.
7236  * SUS defines CLOCKS_PER_SEC is 1000000.
7237  * Non-Unix systems may define it a different value, though.
7238  * If CLOCKS_PER_SEC is 1000000 as SUS, the resolution is 1 microsecond.
7239  * If CLOCKS_PER_SEC is 1000000 and clock_t is 32 bits integer type, it cannot represent over 72 minutes.
7240  *
7241  * If the given +clock_id+ is not supported, Errno::EINVAL is raised.
7242  *
7243  * +unit+ specifies a type of the return value.
7244  *
7245  * [:float_second] number of seconds as a float (default)
7246  * [:float_millisecond] number of milliseconds as a float
7247  * [:float_microsecond] number of microseconds as a float
7248  * [:second] number of seconds as an integer
7249  * [:millisecond] number of milliseconds as an integer
7250  * [:microsecond] number of microseconds as an integer
7251  * [:nanosecond] number of nanoseconds as an integer
7252  *
7253  * The underlying function, clock_gettime(), returns a number of nanoseconds.
7254  * Float object (IEEE 754 double) is not enough to represent
7255  * the return value for CLOCK_REALTIME.
7256  * If the exact nanoseconds value is required, use +:nanoseconds+ as the +unit+.
7257  *
7258  * The origin (zero) of the returned value varies.
7259  * For example, system start up time, process start up time, the Epoch, etc.
7260  *
7261  * The origin in CLOCK_REALTIME is defined as the Epoch
7262  * (1970-01-01 00:00:00 UTC).
7263  * But some systems count leap seconds and others doesn't.
7264  * So the result can be interpreted differently across systems.
7265  * Time.now is recommended over CLOCK_REALTIME.
7266  */
7267 VALUE
7268 rb_clock_gettime(int argc, VALUE *argv)
7269 {
7270  int ret;
7271 
7272  struct timetick tt;
7273  timetick_int_t numerators[2];
7274  timetick_int_t denominators[2];
7275  int num_numerators = 0;
7276  int num_denominators = 0;
7277 
7278  VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
7279  VALUE clk_id = argv[0];
7280 
7281  if (SYMBOL_P(clk_id)) {
7282  /*
7283  * Non-clock_gettime clocks are provided by symbol clk_id.
7284  *
7285  * gettimeofday is always available on platforms supported by Ruby.
7286  * GETTIMEOFDAY_BASED_CLOCK_REALTIME is used for
7287  * CLOCK_REALTIME if clock_gettime is not available.
7288  */
7289 #define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ID2SYM(id_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
7291  struct timeval tv;
7292  ret = gettimeofday(&tv, 0);
7293  if (ret != 0)
7294  rb_sys_fail("gettimeofday");
7295  tt.giga_count = tv.tv_sec;
7296  tt.count = (int32_t)tv.tv_usec * 1000;
7297  denominators[num_denominators++] = 1000000000;
7298  goto success;
7299  }
7300 
7301 #define RUBY_TIME_BASED_CLOCK_REALTIME ID2SYM(id_TIME_BASED_CLOCK_REALTIME)
7302  if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
7303  time_t t;
7304  t = time(NULL);
7305  if (t == (time_t)-1)
7306  rb_sys_fail("time");
7307  tt.giga_count = t;
7308  tt.count = 0;
7309  denominators[num_denominators++] = 1000000000;
7310  goto success;
7311  }
7312 
7313 #ifdef HAVE_TIMES
7314 #define RUBY_TIMES_BASED_CLOCK_MONOTONIC \
7315  ID2SYM(id_TIMES_BASED_CLOCK_MONOTONIC)
7316  if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
7317  struct tms buf;
7318  clock_t c;
7319  unsigned_clock_t uc;
7320  c = times(&buf);
7321  if (c == (clock_t)-1)
7322  rb_sys_fail("times");
7323  uc = (unsigned_clock_t)c;
7324  tt.count = (int32_t)(uc % 1000000000);
7325  tt.giga_count = (uc / 1000000000);
7326  denominators[num_denominators++] = get_clk_tck();
7327  goto success;
7328  }
7329 #endif
7330 
7331 #ifdef RUSAGE_SELF
7332 #define RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID \
7333  ID2SYM(id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
7334  if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7335  struct rusage usage;
7336  int32_t usec;
7337  ret = getrusage(RUSAGE_SELF, &usage);
7338  if (ret != 0)
7339  rb_sys_fail("getrusage");
7340  tt.giga_count = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
7341  usec = (int32_t)(usage.ru_utime.tv_usec + usage.ru_stime.tv_usec);
7342  if (1000000 <= usec) {
7343  tt.giga_count++;
7344  usec -= 1000000;
7345  }
7346  tt.count = usec * 1000;
7347  denominators[num_denominators++] = 1000000000;
7348  goto success;
7349  }
7350 #endif
7351 
7352 #ifdef HAVE_TIMES
7353 #define RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID \
7354  ID2SYM(id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID)
7355  if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7356  struct tms buf;
7357  unsigned_clock_t utime, stime;
7358  if (times(&buf) == (clock_t)-1)
7359  rb_sys_fail("times");
7360  utime = (unsigned_clock_t)buf.tms_utime;
7361  stime = (unsigned_clock_t)buf.tms_stime;
7362  tt.count = (int32_t)((utime % 1000000000) + (stime % 1000000000));
7363  tt.giga_count = (utime / 1000000000) + (stime / 1000000000);
7364  if (1000000000 <= tt.count) {
7365  tt.count -= 1000000000;
7366  tt.giga_count++;
7367  }
7368  denominators[num_denominators++] = get_clk_tck();
7369  goto success;
7370  }
7371 #endif
7372 
7373 #define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID \
7374  ID2SYM(id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID)
7376  clock_t c;
7377  unsigned_clock_t uc;
7378  errno = 0;
7379  c = clock();
7380  if (c == (clock_t)-1)
7381  rb_sys_fail("clock");
7382  uc = (unsigned_clock_t)c;
7383  tt.count = (int32_t)(uc % 1000000000);
7384  tt.giga_count = uc / 1000000000;
7385  denominators[num_denominators++] = CLOCKS_PER_SEC;
7386  goto success;
7387  }
7388 
7389 #ifdef __APPLE__
7390 #define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
7391  if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
7392  mach_timebase_info_data_t *info = get_mach_timebase_info();
7393  uint64_t t = mach_absolute_time();
7394  tt.count = (int32_t)(t % 1000000000);
7395  tt.giga_count = t / 1000000000;
7396  numerators[num_numerators++] = info->numer;
7397  denominators[num_denominators++] = info->denom;
7398  denominators[num_denominators++] = 1000000000;
7399  goto success;
7400  }
7401 #endif
7402  }
7403  else {
7404 #if defined(HAVE_CLOCK_GETTIME)
7405  struct timespec ts;
7406  clockid_t c;
7407  c = NUM2CLOCKID(clk_id);
7408  ret = clock_gettime(c, &ts);
7409  if (ret == -1)
7410  rb_sys_fail("clock_gettime");
7411  tt.count = (int32_t)ts.tv_nsec;
7412  tt.giga_count = ts.tv_sec;
7413  denominators[num_denominators++] = 1000000000;
7414  goto success;
7415 #endif
7416  }
7417  /* EINVAL emulates clock_gettime behavior when clock_id is invalid. */
7418  rb_syserr_fail(EINVAL, 0);
7419 
7420  success:
7421  return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
7422 }
7423 
7424 /*
7425  * call-seq:
7426  * Process.clock_getres(clock_id [, unit]) -> number
7427  *
7428  * Returns the time resolution returned by POSIX clock_getres() function.
7429  *
7430  * +clock_id+ specifies a kind of clock.
7431  * See the document of +Process.clock_gettime+ for details.
7432  *
7433  * +clock_id+ can be a symbol as +Process.clock_gettime+.
7434  * However the result may not be accurate.
7435  * For example, +Process.clock_getres(:GETTIMEOFDAY_BASED_CLOCK_REALTIME)+
7436  * returns 1.0e-06 which means 1 microsecond, but actual resolution can be more coarse.
7437  *
7438  * If the given +clock_id+ is not supported, Errno::EINVAL is raised.
7439  *
7440  * +unit+ specifies a type of the return value.
7441  * +Process.clock_getres+ accepts +unit+ as +Process.clock_gettime+.
7442  * The default value, +:float_second+, is also same as
7443  * +Process.clock_gettime+.
7444  *
7445  * +Process.clock_getres+ also accepts +:hertz+ as +unit+.
7446  * +:hertz+ means a the reciprocal of +:float_second+.
7447  *
7448  * +:hertz+ can be used to obtain the exact value of
7449  * the clock ticks per second for times() function and
7450  * CLOCKS_PER_SEC for clock() function.
7451  *
7452  * +Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)+
7453  * returns the clock ticks per second.
7454  *
7455  * +Process.clock_getres(:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)+
7456  * returns CLOCKS_PER_SEC.
7457  *
7458  * p Process.clock_getres(Process::CLOCK_MONOTONIC)
7459  * #=> 1.0e-09
7460  *
7461  */
7462 VALUE
7463 rb_clock_getres(int argc, VALUE *argv)
7464 {
7465  struct timetick tt;
7466  timetick_int_t numerators[2];
7467  timetick_int_t denominators[2];
7468  int num_numerators = 0;
7469  int num_denominators = 0;
7470 
7471  VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
7472  VALUE clk_id = argv[0];
7473 
7474  if (SYMBOL_P(clk_id)) {
7475 #ifdef RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
7477  tt.giga_count = 0;
7478  tt.count = 1000;
7479  denominators[num_denominators++] = 1000000000;
7480  goto success;
7481  }
7482 #endif
7483 
7484 #ifdef RUBY_TIME_BASED_CLOCK_REALTIME
7485  if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
7486  tt.giga_count = 1;
7487  tt.count = 0;
7488  denominators[num_denominators++] = 1000000000;
7489  goto success;
7490  }
7491 #endif
7492 
7493 #ifdef RUBY_TIMES_BASED_CLOCK_MONOTONIC
7494  if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
7495  tt.count = 1;
7496  tt.giga_count = 0;
7497  denominators[num_denominators++] = get_clk_tck();
7498  goto success;
7499  }
7500 #endif
7501 
7502 #ifdef RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
7503  if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7504  tt.giga_count = 0;
7505  tt.count = 1000;
7506  denominators[num_denominators++] = 1000000000;
7507  goto success;
7508  }
7509 #endif
7510 
7511 #ifdef RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID
7512  if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7513  tt.count = 1;
7514  tt.giga_count = 0;
7515  denominators[num_denominators++] = get_clk_tck();
7516  goto success;
7517  }
7518 #endif
7519 
7520 #ifdef RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
7522  tt.count = 1;
7523  tt.giga_count = 0;
7524  denominators[num_denominators++] = CLOCKS_PER_SEC;
7525  goto success;
7526  }
7527 #endif
7528 
7529 #ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
7530  if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
7531  mach_timebase_info_data_t *info = get_mach_timebase_info();
7532  tt.count = 1;
7533  tt.giga_count = 0;
7534  numerators[num_numerators++] = info->numer;
7535  denominators[num_denominators++] = info->denom;
7536  denominators[num_denominators++] = 1000000000;
7537  goto success;
7538  }
7539 #endif
7540  }
7541  else {
7542 #if defined(HAVE_CLOCK_GETRES)
7543  struct timespec ts;
7544  clockid_t c = NUM2CLOCKID(clk_id);
7545  int ret = clock_getres(c, &ts);
7546  if (ret == -1)
7547  rb_sys_fail("clock_getres");
7548  tt.count = (int32_t)ts.tv_nsec;
7549  tt.giga_count = ts.tv_sec;
7550  denominators[num_denominators++] = 1000000000;
7551  goto success;
7552 #endif
7553  }
7554  /* EINVAL emulates clock_getres behavior when clock_id is invalid. */
7555  rb_syserr_fail(EINVAL, 0);
7556 
7557  success:
7558  if (unit == ID2SYM(id_hertz)) {
7559  return timetick2dblnum_reciprocal(&tt, numerators, num_numerators, denominators, num_denominators);
7560  }
7561  else {
7562  return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
7563  }
7564 }
7565 
7570 
7571 
7572 /*
7573  * The <code>Process</code> module is a collection of methods used to
7574  * manipulate processes.
7575  */
7576 
7577 void
7579 {
7580 #undef rb_intern
7581 #define rb_intern(str) rb_intern_const(str)
7584  rb_define_global_function("exec", rb_f_exec, -1);
7587  rb_define_global_function("system", rb_f_system, -1);
7588  rb_define_global_function("spawn", rb_f_spawn, -1);
7589  rb_define_global_function("sleep", rb_f_sleep, -1);
7590  rb_define_global_function("exit", rb_f_exit, -1);
7591  rb_define_global_function("abort", rb_f_abort, -1);
7592 
7593  rb_mProcess = rb_define_module("Process");
7594 
7595 #ifdef WNOHANG
7596  /* see Process.wait */
7597  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
7598 #else
7599  /* see Process.wait */
7600  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
7601 #endif
7602 #ifdef WUNTRACED
7603  /* see Process.wait */
7604  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
7605 #else
7606  /* see Process.wait */
7607  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
7608 #endif
7609 
7610  rb_define_singleton_method(rb_mProcess, "exec", rb_f_exec, -1);
7611  rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
7612  rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
7613  rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
7614  rb_define_singleton_method(rb_mProcess, "exit", rb_f_exit, -1);
7615  rb_define_singleton_method(rb_mProcess, "abort", rb_f_abort, -1);
7616 
7617  rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1); /* in signal.c */
7618  rb_define_module_function(rb_mProcess, "wait", proc_wait, -1);
7619  rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
7620  rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
7621  rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
7622  rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
7623  rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
7624 
7625  rb_cWaiter = rb_define_class_under(rb_mProcess, "Waiter", rb_cThread);
7629 
7630  rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
7632 
7639 
7641 
7650 
7651  rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
7652  rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
7653 
7654  rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, 0);
7655  rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, 0);
7656  rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
7657  rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
7658 
7659  rb_define_module_function(rb_mProcess, "getsid", proc_getsid, -1);
7660  rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
7661 
7662  rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
7663  rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
7664 
7665 #ifdef HAVE_GETPRIORITY
7666  /* see Process.setpriority */
7667  rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
7668  /* see Process.setpriority */
7669  rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
7670  /* see Process.setpriority */
7671  rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
7672 #endif
7673 
7674  rb_define_module_function(rb_mProcess, "getrlimit", proc_getrlimit, 1);
7675  rb_define_module_function(rb_mProcess, "setrlimit", proc_setrlimit, -1);
7676 #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
7677  {
7678  VALUE inf = RLIM2NUM(RLIM_INFINITY);
7679 #ifdef RLIM_SAVED_MAX
7680  {
7681  VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
7682  /* see Process.setrlimit */
7683  rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
7684  }
7685 #endif
7686  /* see Process.setrlimit */
7687  rb_define_const(rb_mProcess, "RLIM_INFINITY", inf);
7688 #ifdef RLIM_SAVED_CUR
7689  {
7690  VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
7691  /* see Process.setrlimit */
7692  rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
7693  }
7694 #endif
7695  }
7696 #ifdef RLIMIT_AS
7697  /* Maximum size of the process's virtual memory (address space) in bytes.
7698  *
7699  * see the system getrlimit(2) manual for details.
7700  */
7701  rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
7702 #endif
7703 #ifdef RLIMIT_CORE
7704  /* Maximum size of the core file.
7705  *
7706  * see the system getrlimit(2) manual for details.
7707  */
7708  rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
7709 #endif
7710 #ifdef RLIMIT_CPU
7711  /* CPU time limit in seconds.
7712  *
7713  * see the system getrlimit(2) manual for details.
7714  */
7715  rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
7716 #endif
7717 #ifdef RLIMIT_DATA
7718  /* Maximum size of the process's data segment.
7719  *
7720  * see the system getrlimit(2) manual for details.
7721  */
7722  rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
7723 #endif
7724 #ifdef RLIMIT_FSIZE
7725  /* Maximum size of files that the process may create.
7726  *
7727  * see the system getrlimit(2) manual for details.
7728  */
7729  rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
7730 #endif
7731 #ifdef RLIMIT_MEMLOCK
7732  /* Maximum number of bytes of memory that may be locked into RAM.
7733  *
7734  * see the system getrlimit(2) manual for details.
7735  */
7736  rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
7737 #endif
7738 #ifdef RLIMIT_MSGQUEUE
7739  /* Specifies the limit on the number of bytes that can be allocated
7740  * for POSIX message queues for the real user ID of the calling process.
7741  *
7742  * see the system getrlimit(2) manual for details.
7743  */
7744  rb_define_const(rb_mProcess, "RLIMIT_MSGQUEUE", INT2FIX(RLIMIT_MSGQUEUE));
7745 #endif
7746 #ifdef RLIMIT_NICE
7747  /* Specifies a ceiling to which the process's nice value can be raised.
7748  *
7749  * see the system getrlimit(2) manual for details.
7750  */
7751  rb_define_const(rb_mProcess, "RLIMIT_NICE", INT2FIX(RLIMIT_NICE));
7752 #endif
7753 #ifdef RLIMIT_NOFILE
7754  /* Specifies a value one greater than the maximum file descriptor
7755  * number that can be opened by this process.
7756  *
7757  * see the system getrlimit(2) manual for details.
7758  */
7759  rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
7760 #endif
7761 #ifdef RLIMIT_NPROC
7762  /* The maximum number of processes that can be created for the
7763  * real user ID of the calling process.
7764  *
7765  * see the system getrlimit(2) manual for details.
7766  */
7767  rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
7768 #endif
7769 #ifdef RLIMIT_RSS
7770  /* Specifies the limit (in pages) of the process's resident set.
7771  *
7772  * see the system getrlimit(2) manual for details.
7773  */
7774  rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
7775 #endif
7776 #ifdef RLIMIT_RTPRIO
7777  /* Specifies a ceiling on the real-time priority that may be set for this process.
7778  *
7779  * see the system getrlimit(2) manual for details.
7780  */
7781  rb_define_const(rb_mProcess, "RLIMIT_RTPRIO", INT2FIX(RLIMIT_RTPRIO));
7782 #endif
7783 #ifdef RLIMIT_RTTIME
7784  /* Specifies limit on CPU time this process scheduled under a real-time
7785  * scheduling policy can consume.
7786  *
7787  * see the system getrlimit(2) manual for details.
7788  */
7789  rb_define_const(rb_mProcess, "RLIMIT_RTTIME", INT2FIX(RLIMIT_RTTIME));
7790 #endif
7791 #ifdef RLIMIT_SBSIZE
7792  /* Maximum size of the socket buffer.
7793  */
7794  rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
7795 #endif
7796 #ifdef RLIMIT_SIGPENDING
7797  /* Specifies a limit on the number of signals that may be queued for
7798  * the real user ID of the calling process.
7799  *
7800  * see the system getrlimit(2) manual for details.
7801  */
7802  rb_define_const(rb_mProcess, "RLIMIT_SIGPENDING", INT2FIX(RLIMIT_SIGPENDING));
7803 #endif
7804 #ifdef RLIMIT_STACK
7805  /* Maximum size of the stack, in bytes.
7806  *
7807  * see the system getrlimit(2) manual for details.
7808  */
7809  rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
7810 #endif
7811 #endif
7812 
7813  rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
7814  rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
7815  rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
7816  rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
7817  rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
7818  rb_define_module_function(rb_mProcess, "euid=", proc_seteuid_m, 1);
7819  rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
7820  rb_define_module_function(rb_mProcess, "egid=", proc_setegid_m, 1);
7821  rb_define_module_function(rb_mProcess, "initgroups", proc_initgroups, 2);
7822  rb_define_module_function(rb_mProcess, "groups", proc_getgroups, 0);
7823  rb_define_module_function(rb_mProcess, "groups=", proc_setgroups, 1);
7824  rb_define_module_function(rb_mProcess, "maxgroups", proc_getmaxgroups, 0);
7825  rb_define_module_function(rb_mProcess, "maxgroups=", proc_setmaxgroups, 1);
7826 
7827  rb_define_module_function(rb_mProcess, "daemon", proc_daemon, -1);
7828 
7829  rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
7830 
7831 #ifdef CLOCK_REALTIME
7832  rb_define_const(rb_mProcess, "CLOCK_REALTIME", CLOCKID2NUM(CLOCK_REALTIME));
7833 #elif defined(RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
7834  rb_define_const(rb_mProcess, "CLOCK_REALTIME", RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME);
7835 #endif
7836 #ifdef CLOCK_MONOTONIC
7837  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", CLOCKID2NUM(CLOCK_MONOTONIC));
7838 #elif defined(RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
7839  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC);
7840 #endif
7841 #ifdef CLOCK_PROCESS_CPUTIME_ID
7842  rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", CLOCKID2NUM(CLOCK_PROCESS_CPUTIME_ID));
7843 #elif defined(RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
7844  rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID);
7845 #endif
7846 #ifdef CLOCK_THREAD_CPUTIME_ID
7847  rb_define_const(rb_mProcess, "CLOCK_THREAD_CPUTIME_ID", CLOCKID2NUM(CLOCK_THREAD_CPUTIME_ID));
7848 #endif
7849 #ifdef CLOCK_VIRTUAL
7850  rb_define_const(rb_mProcess, "CLOCK_VIRTUAL", CLOCKID2NUM(CLOCK_VIRTUAL));
7851 #endif
7852 #ifdef CLOCK_PROF
7853  rb_define_const(rb_mProcess, "CLOCK_PROF", CLOCKID2NUM(CLOCK_PROF));
7854 #endif
7855 #ifdef CLOCK_REALTIME_FAST
7856  rb_define_const(rb_mProcess, "CLOCK_REALTIME_FAST", CLOCKID2NUM(CLOCK_REALTIME_FAST));
7857 #endif
7858 #ifdef CLOCK_REALTIME_PRECISE
7859  rb_define_const(rb_mProcess, "CLOCK_REALTIME_PRECISE", CLOCKID2NUM(CLOCK_REALTIME_PRECISE));
7860 #endif
7861 #ifdef CLOCK_REALTIME_COARSE
7862  rb_define_const(rb_mProcess, "CLOCK_REALTIME_COARSE", CLOCKID2NUM(CLOCK_REALTIME_COARSE));
7863 #endif
7864 #ifdef CLOCK_REALTIME_ALARM
7865  rb_define_const(rb_mProcess, "CLOCK_REALTIME_ALARM", CLOCKID2NUM(CLOCK_REALTIME_ALARM));
7866 #endif
7867 #ifdef CLOCK_MONOTONIC_FAST
7868  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_FAST", CLOCKID2NUM(CLOCK_MONOTONIC_FAST));
7869 #endif
7870 #ifdef CLOCK_MONOTONIC_PRECISE
7871  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_PRECISE", CLOCKID2NUM(CLOCK_MONOTONIC_PRECISE));
7872 #endif
7873 #ifdef CLOCK_MONOTONIC_RAW
7874  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_RAW", CLOCKID2NUM(CLOCK_MONOTONIC_RAW));
7875 #endif
7876 #ifdef CLOCK_MONOTONIC_RAW_APPROX
7877  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_RAW_APPROX", CLOCKID2NUM(CLOCK_MONOTONIC_RAW_APPROX));
7878 #endif
7879 #ifdef CLOCK_MONOTONIC_COARSE
7880  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_COARSE", CLOCKID2NUM(CLOCK_MONOTONIC_COARSE));
7881 #endif
7882 #ifdef CLOCK_BOOTTIME
7883  rb_define_const(rb_mProcess, "CLOCK_BOOTTIME", CLOCKID2NUM(CLOCK_BOOTTIME));
7884 #endif
7885 #ifdef CLOCK_BOOTTIME_ALARM
7886  rb_define_const(rb_mProcess, "CLOCK_BOOTTIME_ALARM", CLOCKID2NUM(CLOCK_BOOTTIME_ALARM));
7887 #endif
7888 #ifdef CLOCK_UPTIME
7889  rb_define_const(rb_mProcess, "CLOCK_UPTIME", CLOCKID2NUM(CLOCK_UPTIME));
7890 #endif
7891 #ifdef CLOCK_UPTIME_FAST
7892  rb_define_const(rb_mProcess, "CLOCK_UPTIME_FAST", CLOCKID2NUM(CLOCK_UPTIME_FAST));
7893 #endif
7894 #ifdef CLOCK_UPTIME_PRECISE
7895  rb_define_const(rb_mProcess, "CLOCK_UPTIME_PRECISE", CLOCKID2NUM(CLOCK_UPTIME_PRECISE));
7896 #endif
7897 #ifdef CLOCK_UPTIME_RAW
7898  rb_define_const(rb_mProcess, "CLOCK_UPTIME_RAW", CLOCKID2NUM(CLOCK_UPTIME_RAW));
7899 #endif
7900 #ifdef CLOCK_UPTIME_RAW_APPROX
7901  rb_define_const(rb_mProcess, "CLOCK_UPTIME_RAW_APPROX", CLOCKID2NUM(CLOCK_UPTIME_RAW_APPROX));
7902 #endif
7903 #ifdef CLOCK_SECOND
7904  rb_define_const(rb_mProcess, "CLOCK_SECOND", CLOCKID2NUM(CLOCK_SECOND));
7905 #endif
7906  rb_define_module_function(rb_mProcess, "clock_gettime", rb_clock_gettime, -1);
7907  rb_define_module_function(rb_mProcess, "clock_getres", rb_clock_getres, -1);
7908 
7909 #if defined(HAVE_TIMES) || defined(_WIN32)
7910  rb_cProcessTms = rb_struct_define_under(rb_mProcess, "Tms", "utime", "stime", "cutime", "cstime", NULL);
7911  rb_define_const(rb_cStruct, "Tms", rb_cProcessTms); /* for the backward compatibility */
7912 #endif
7913 
7914  SAVED_USER_ID = geteuid();
7915  SAVED_GROUP_ID = getegid();
7916 
7917  rb_mProcUID = rb_define_module_under(rb_mProcess, "UID");
7918  rb_mProcGID = rb_define_module_under(rb_mProcess, "GID");
7919 
7920  rb_define_module_function(rb_mProcUID, "rid", proc_getuid, 0);
7921  rb_define_module_function(rb_mProcGID, "rid", proc_getgid, 0);
7922  rb_define_module_function(rb_mProcUID, "eid", proc_geteuid, 0);
7923  rb_define_module_function(rb_mProcGID, "eid", proc_getegid, 0);
7924  rb_define_module_function(rb_mProcUID, "change_privilege", p_uid_change_privilege, 1);
7925  rb_define_module_function(rb_mProcGID, "change_privilege", p_gid_change_privilege, 1);
7926  rb_define_module_function(rb_mProcUID, "grant_privilege", p_uid_grant_privilege, 1);
7927  rb_define_module_function(rb_mProcGID, "grant_privilege", p_gid_grant_privilege, 1);
7928  rb_define_alias(rb_singleton_class(rb_mProcUID), "eid=", "grant_privilege");
7929  rb_define_alias(rb_singleton_class(rb_mProcGID), "eid=", "grant_privilege");
7930  rb_define_module_function(rb_mProcUID, "re_exchange", p_uid_exchange, 0);
7931  rb_define_module_function(rb_mProcGID, "re_exchange", p_gid_exchange, 0);
7932  rb_define_module_function(rb_mProcUID, "re_exchangeable?", p_uid_exchangeable, 0);
7933  rb_define_module_function(rb_mProcGID, "re_exchangeable?", p_gid_exchangeable, 0);
7934  rb_define_module_function(rb_mProcUID, "sid_available?", p_uid_have_saved_id, 0);
7935  rb_define_module_function(rb_mProcGID, "sid_available?", p_gid_have_saved_id, 0);
7936  rb_define_module_function(rb_mProcUID, "switch", p_uid_switch, 0);
7937  rb_define_module_function(rb_mProcGID, "switch", p_gid_switch, 0);
7938 #ifdef p_uid_from_name
7939  rb_define_module_function(rb_mProcUID, "from_name", p_uid_from_name, 1);
7940 #endif
7941 #ifdef p_gid_from_name
7942  rb_define_module_function(rb_mProcGID, "from_name", p_gid_from_name, 1);
7943 #endif
7944 
7945  rb_mProcID_Syscall = rb_define_module_under(rb_mProcess, "Sys");
7946 
7947  rb_define_module_function(rb_mProcID_Syscall, "getuid", proc_getuid, 0);
7948  rb_define_module_function(rb_mProcID_Syscall, "geteuid", proc_geteuid, 0);
7949  rb_define_module_function(rb_mProcID_Syscall, "getgid", proc_getgid, 0);
7950  rb_define_module_function(rb_mProcID_Syscall, "getegid", proc_getegid, 0);
7951 
7952  rb_define_module_function(rb_mProcID_Syscall, "setuid", p_sys_setuid, 1);
7953  rb_define_module_function(rb_mProcID_Syscall, "setgid", p_sys_setgid, 1);
7954 
7955  rb_define_module_function(rb_mProcID_Syscall, "setruid", p_sys_setruid, 1);
7956  rb_define_module_function(rb_mProcID_Syscall, "setrgid", p_sys_setrgid, 1);
7957 
7958  rb_define_module_function(rb_mProcID_Syscall, "seteuid", p_sys_seteuid, 1);
7959  rb_define_module_function(rb_mProcID_Syscall, "setegid", p_sys_setegid, 1);
7960 
7961  rb_define_module_function(rb_mProcID_Syscall, "setreuid", p_sys_setreuid, 2);
7962  rb_define_module_function(rb_mProcID_Syscall, "setregid", p_sys_setregid, 2);
7963 
7964  rb_define_module_function(rb_mProcID_Syscall, "setresuid", p_sys_setresuid, 3);
7965  rb_define_module_function(rb_mProcID_Syscall, "setresgid", p_sys_setresgid, 3);
7966  rb_define_module_function(rb_mProcID_Syscall, "issetugid", p_sys_issetugid, 0);
7967 }
7968 
7969 void
7971 {
7972  id_in = rb_intern("in");
7973  id_out = rb_intern("out");
7974  id_err = rb_intern("err");
7975  id_pid = rb_intern("pid");
7976  id_uid = rb_intern("uid");
7977  id_gid = rb_intern("gid");
7978  id_close = rb_intern("close");
7979  id_child = rb_intern("child");
7980 #ifdef HAVE_SETPGID
7981  id_pgroup = rb_intern("pgroup");
7982 #endif
7983 #ifdef _WIN32
7984  id_new_pgroup = rb_intern("new_pgroup");
7985 #endif
7986  id_unsetenv_others = rb_intern("unsetenv_others");
7987  id_chdir = rb_intern("chdir");
7988  id_umask = rb_intern("umask");
7989  id_close_others = rb_intern("close_others");
7990  id_ENV = rb_intern("ENV");
7991  id_nanosecond = rb_intern("nanosecond");
7992  id_microsecond = rb_intern("microsecond");
7993  id_millisecond = rb_intern("millisecond");
7994  id_second = rb_intern("second");
7995  id_float_microsecond = rb_intern("float_microsecond");
7996  id_float_millisecond = rb_intern("float_millisecond");
7997  id_float_second = rb_intern("float_second");
7998  id_GETTIMEOFDAY_BASED_CLOCK_REALTIME = rb_intern("GETTIMEOFDAY_BASED_CLOCK_REALTIME");
7999  id_TIME_BASED_CLOCK_REALTIME = rb_intern("TIME_BASED_CLOCK_REALTIME");
8000 #ifdef HAVE_TIMES
8001  id_TIMES_BASED_CLOCK_MONOTONIC = rb_intern("TIMES_BASED_CLOCK_MONOTONIC");
8002  id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID");
8003 #endif
8004 #ifdef RUSAGE_SELF
8005  id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID");
8006 #endif
8007  id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID");
8008 #ifdef __APPLE__
8009  id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC = rb_intern("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC");
8010 #endif
8011  id_hertz = rb_intern("hertz");
8012 
8013  InitVM(process);
8014 }
VALUE fd_dup2
Definition: internal.h:1392
static VALUE timetick2dblnum(struct timetick *ttp, timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators)
Definition: process.c:7004
#define p_sys_setreuid
Definition: process.c:5288
#define proc_setegid_m
Definition: process.c:6469
static ID id_TIME_BASED_CLOCK_REALTIME
Definition: process.c:271
static VALUE p_uid_have_saved_id(void)
Definition: process.c:6669
static int run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
Definition: process.c:2876
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1312
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2286
void rb_syswait(rb_pid_t pid)
Definition: process.c:3885
void rb_gc(void)
Definition: gc.c:6656
#define WNOHANG
Definition: win32.h:128
#define T_SYMBOL
Definition: ruby.h:508
#define proc_setpgid
Definition: process.c:4518
#define NUM2UIDT(v)
Definition: ruby.h:332
static VALUE rb_cProcessStatus
Definition: process.c:476
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:923
#define RUBY_VM_CHECK_INTS(th)
Definition: vm_core.h:1569
#define EXPORT_STR(str)
Definition: process.c:1383
#define redirect_close(fd)
Definition: process.c:401
static void before_exec_async_signal_safe(void)
Definition: process.c:1161
RUBY_EXTERN VALUE rb_cData
Definition: ruby.h:1881
static VALUE proc_getgid(VALUE obj)
Definition: process.c:5741
static ID id_in
Definition: process.c:260
size_t buflen
Definition: process.c:3965
void rb_thread_atfork(void)
Definition: thread.c:4172
static void check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
Definition: process.c:1534
#define OBJ2UID(id)
Definition: process.c:199
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:360
static VALUE rb_check_argv(int argc, VALUE *argv)
Definition: process.c:1986
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1196
#define F_SETFD
Definition: win32.h:583
VALUE execarg
Definition: process.c:3962
#define RARRAY_LEN(a)
Definition: ruby.h:1026
void rb_bug(const char *fmt,...)
Definition: error.c:482
#define WTERMSIG(w)
Definition: process.c:119
int gettimeofday(struct timeval *, struct timezone *)
Definition: win32.c:4580
#define FALSE
Definition: nkf.h:174
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1145
static VALUE check_exec_fds(struct rb_execarg *eargp)
Definition: process.c:1873
static void rb_check_exec_options(VALUE opthash, VALUE execarg_obj)
Definition: process.c:1920
int ioctl(int, int,...)
Definition: win32.c:2755
#define proc_setpriority
Definition: process.c:4674
static timetick_int_t gcd_timetick_int(timetick_int_t a, timetick_int_t b)
Definition: process.c:6953
size_t strlen(const char *)
#define INT2NUM(x)
Definition: ruby.h:1538
unsigned int unsigned_clock_t
Definition: process.c:250
void rb_update_max_fd(int fd)
Definition: io.c:189
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2268
static ID id_gid
Definition: process.c:260
#define T_FIXNUM
Definition: ruby.h:503
Definition: st.h:79
long timetick_int_t
Definition: process.c:6945
#define proc_getpriority
Definition: process.c:4643
Definition: st.h:99
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:2314
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:647
static VALUE hide_obj(VALUE obj)
Definition: process.c:1464
static VALUE p_uid_exchange(VALUE obj)
Definition: process.c:6569
#define p_sys_setrgid
Definition: process.c:5617
#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
static void after_exec(void)
Definition: process.c:1201
static unsigned int hash(str, len) register const char *str
#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:2709
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:681
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
static VALUE rb_f_system(int argc, VALUE *argv)
Definition: process.c:4045
#define RUBY_TIME_BASED_CLOCK_REALTIME
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:5086
static int under_gid_switch
Definition: process.c:5019
unsigned umask_given
Definition: internal.h:1376
#define TIMETICK_INT_MAX
Definition: process.c:6947
static VALUE pst_bitand(VALUE st1, VALUE st2)
Definition: process.c:660
#define NUM2PIDT(v)
Definition: ruby.h:326
#define FilePathValue(v)
Definition: ruby.h:594
VALUE rb_mProcGID
Definition: process.c:7568
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:255
long tms_stime
Definition: win32.h:713
#define WIFEXITED(w)
Definition: process.c:107
#define InitVM(ext)
Definition: ruby.h:2143
#define proc_getgroups
Definition: process.c:5873
static VALUE p_uid_exchangeable(void)
Definition: process.c:6544
#define PIDT2NUM(v)
Definition: ruby.h:323
VALUE rb_f_exit(int argc, const VALUE *argv)
Definition: process.c:3834
static VALUE pst_to_s(VALUE st)
Definition: process.c:584
#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
static VALUE detach_process_pid(VALUE thread)
Definition: process.c:1079
#define FINISH_GETPWNAM
Definition: process.c:197
#define Qtrue
Definition: ruby.h:437
VALUE rlimit_limits
Definition: internal.h:1387
static void usage(void)
Definition: nkf.c:904
static long run_exec_dup2_tmpbuf_size(long n)
Definition: process.c:2684
#define WIFSTOPPED(w)
Definition: process.c:113
unsigned uid_given
Definition: internal.h:1384
Definition: io.h:62
mode_t perm
Definition: process.c:2321
#define proc_setpgrp
Definition: process.c:4468
#define CLOCK_MONOTONIC
Definition: win32.h:134
int rb_env_path_tainted(void)
Definition: hash.c:3311
Definition: st.h:99
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1190
#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:1420
unsigned unsetenv_others_given
Definition: internal.h:1377
static ID id_float_millisecond
Definition: process.c:270
static int check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
Definition: process.c:1946
#define P_NOWAIT
Definition: process.c:1393
static int check_exec_fds_1(struct rb_execarg *eargp, VALUE h, int maxhint, VALUE ary)
Definition: process.c:1843
static ID id_close
Definition: process.c:261
static rb_gid_t SAVED_GROUP_ID
Definition: process.c:6095
static rb_pid_t do_waitpid(rb_pid_t pid, int *st, int flags)
Definition: process.c:869
static VALUE p_uid_sw_ensure(VALUE obj)
Definition: process.c:6740
static ID id_umask
Definition: process.c:268
int close_others_maxhint
Definition: internal.h:1391
static VALUE proc_waitall(void)
Definition: process.c:1054
#define rb_check_arity
Definition: intern.h:303
static int run_exec_dup2_child(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
Definition: process.c:2895
#define UNREACHABLE
Definition: ruby.h:46
VALUE rb_mProcID_Syscall
Definition: process.c:7569
static ID id_uid
Definition: process.c:260
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:905
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
int fcntl(int, int,...)
Definition: win32.c:4296
#define RB_SPECIAL_CONST_P(x)
Definition: ruby.h:1248
#define p_sys_setresuid
Definition: process.c:5318
static VALUE p_gid_have_saved_id(void)
Definition: process.c:6783
#define redirect_cloexec_dup2(oldfd, newfd)
Definition: process.c:400
static VALUE p_gid_exchangeable(void)
Definition: process.c:6606
struct st_table * rb_hash_tbl_raw(VALUE hash)
Definition: hash.c:490
#define p_sys_seteuid
Definition: process.c:5259
rb_pid_t rb_fork_ruby(int *status)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:821
void rb_async_bug_errno(const char *mesg, int errno_arg)
Definition: error.c:534
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:2545
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:891
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:1314
static VALUE check_hash(VALUE obj)
Definition: process.c:2017
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
VALUE rb_to_int(VALUE)
Definition: object.c:2687
#define Check_Type(v, t)
Definition: ruby.h:562
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2207
struct spawn_args::@151 errmsg
#define proc_daemon
Definition: process.c:6082
static int run_exec_dup2(VALUE ary, VALUE tmpbuf, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
Definition: process.c:2753
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1260
rb_pid_t rb_waitpid(rb_pid_t pid, int *st, int flags)
Definition: process.c:902
static ID id_err
Definition: process.c:260
static void check_gid_switch(void)
Definition: process.c:5021
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2630
rb_pid_t pid
Definition: process.c:863
#define RB_GC_GUARD(v)
Definition: ruby.h:552
#define rb_f_fork
Definition: process.c:3725
#define T_HASH
Definition: ruby.h:499
static VALUE p_gid_change_privilege(VALUE obj, VALUE id)
Definition: process.c:6126
static ID id_pid
Definition: process.c:260
#define EXPORT_DUP(str)
Definition: process.c:1384
static VALUE check_exec_redirect_fd(VALUE v, int iskey)
Definition: process.c:1471
#define after_fork_ruby()
Definition: process.c:1208
#define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
VALUE rb_eSecurityError
Definition: error.c:771
#define DATA_PTR(dta)
Definition: ruby.h:1113
#define proc_initgroups
Definition: process.c:5953
VALUE env_modification
Definition: internal.h:1396
VALUE last_status
Definition: vm_core.h:711
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
int rb_pipe(int *pipes)
Definition: io.c:5822
void rb_gc_mark(VALUE ptr)
Definition: gc.c:4394
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:867
#define T_ARRAY
Definition: ruby.h:498
#define st_delete
Definition: regint.h:182
#define OBJ2GID1(id)
Definition: process.c:241
static VALUE pst_equal(VALUE st1, VALUE st2)
Definition: process.c:640
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:3964
static void rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VALUE execarg_obj)
Definition: process.c:2077
static VALUE pst_success_p(VALUE st)
Definition: process.c:829
static VALUE proc_wait(int argc, VALUE *argv)
Definition: process.c:982
static void * rb_waitpid_blocking(void *data)
Definition: process.c:881
static const rb_data_type_t exec_arg_data_type
Definition: process.c:1363
#define proc_getpgrp
Definition: process.c:4440
#define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
#define FIXNUM_P(f)
Definition: ruby.h:365
static ID id_microsecond
Definition: process.c:269
#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:1275
static VALUE pst_wtermsig(VALUE st)
Definition: process.c:759
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1533
static VALUE rb_cWaiter
Definition: process.c:1076
#define GetOpenFile(obj, fp)
Definition: io.h:120
VALUE envp_str
Definition: internal.h:1371
static void reduce_fraction(timetick_int_t *np, timetick_int_t *dp)
Definition: process.c:6973
VALUE rb_struct_define_under(VALUE, const char *,...)
Definition: struct.c:425
void rb_thread_start_timer_thread(void)
Definition: thread.c:4087
#define p_sys_setegid
Definition: process.c:5639
static VALUE envtbl
Definition: hash.c:83
static VALUE pst_wstopsig(VALUE st)
Definition: process.c:719
static double inf(void)
Definition: isinf.c:53
static ID id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
Definition: process.c:279
VALUE rb_thread_local_aref(VALUE, ID)
Definition: thread.c:3049
#define GET_THREAD()
Definition: vm_core.h:1513
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
static void reduce_factors(timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators)
Definition: process.c:6983
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1830
static VALUE pst_wifsignaled(VALUE st)
Definition: process.c:738
void rb_exc_raise(VALUE mesg)
Definition: eval.c:620
unsigned unsetenv_others_do
Definition: internal.h:1378
int clockid_t
Definition: win32.h:132
static rb_pid_t rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3916
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:2730
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
static ID id_hertz
Definition: process.c:283
#define fail()
VALUE rb_last_status_get(void)
Definition: process.c:479
#define MEMZERO(p, type, n)
Definition: ruby.h:1660
static void before_exec_non_async_signal_safe(void)
Definition: process.c:1166
#define OBJ2UID1(id)
Definition: process.c:198
static VALUE proc_wait2(int argc, VALUE *argv)
Definition: process.c:1025
unsigned long long uint64_t
Definition: sha2.h:102
#define proc_setsid
Definition: process.c:4607
static rb_gid_t rb_setegid_core(rb_gid_t egid)
Definition: process.c:6473
void rb_thread_sleep(int)
Definition: thread.c:1241
static void mark_exec_arg(void *ptr)
Definition: process.c:1332
int oflags
Definition: process.c:2320
rb_gid_t gid
Definition: internal.h:1390
static int fd_get_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
Definition: process.c:2691
#define ALWAYS_NEED_ENVP
Definition: process.c:293
static rb_pid_t rb_execarg_spawn(VALUE execarg_obj, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3979
static VALUE rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
Definition: process.c:3763
void rb_execarg_parent_start(VALUE execarg_obj)
Definition: process.c:2457
int rb_block_given_p(void)
Definition: eval.c:797
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1576
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:223
#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:1872
static VALUE rb_f_spawn(int argc, VALUE *argv)
Definition: process.c:4349
static rb_uid_t SAVED_USER_ID
Definition: process.c:5391
VALUE rb_eRuntimeError
Definition: error.c:761
IUnknown DWORD
Definition: win32ole.c:32
#define proc_getmaxgroups
Definition: process.c:5973
static ID id_ENV
Definition: process.c:268
static VALUE proc_detach(VALUE obj, VALUE pid)
Definition: process.c:1154
const char * ruby_signal_name(int)
Definition: signal.c:262
VALUE rb_io_check_io(VALUE io)
Definition: io.c:662
static void * open_func(void *ptr)
Definition: process.c:2327
static ID id_float_microsecond
Definition: process.c:270
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_ary_new(void)
Definition: array.c:493
VALUE rb_str_buf_cat2(VALUE, const char *)
#define dp(v)
Definition: vm_debug.h:21
static void after_exec_async_signal_safe(void)
Definition: process.c:1189
#define p_gid_from_name
Definition: process.c:245
static VALUE pst_wifexited(VALUE st)
Definition: process.c:779
rb_uid_t uid
Definition: internal.h:1389
#define NIL_P(v)
Definition: ruby.h:451
static void after_exec_non_async_signal_safe(void)
Definition: process.c:1194
long tv_nsec
Definition: missing.h:62
#define TIMETICK_INT2NUM(v)
Definition: process.c:6948
int fd
Definition: io.h:64
rb_pid_t pgroup_pgid
Definition: internal.h:1386
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:2734
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:799
static VALUE pst_rshift(VALUE st1, VALUE st2)
Definition: process.c:681
#define TOUPPER(c)
Definition: ruby.h:2132
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2332
static ID id_close_others
Definition: process.c:268
static rb_pid_t rb_spawn_internal(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3991
static ID id_millisecond
Definition: process.c:269
union rb_execarg::@139 invoke
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:183
int setegid(pid_t pid)
void rb_thread_stop_timer_thread(void)
Definition: thread.c:4073
#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:288
static VALUE execarg_parent_end(VALUE execarg_obj)
Definition: process.c:2468
#define proc_getrlimit
Definition: process.c:4931
#define RUBY_UBF_PROCESS
Definition: intern.h:901
void rb_exit(int status)
Definition: process.c:3779
#define T_BIGNUM
Definition: ruby.h:501
static ID id_nanosecond
Definition: process.c:269
int seteuid(pid_t pid)
#define ISUPPER(c)
Definition: ruby.h:2125
static ID id_child
Definition: process.c:261
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1661
void ruby_stop(int ex)
Calls ruby_cleanup() and exits the process.
Definition: eval.c:254
#define rb_str_new2
Definition: intern.h:857
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1845
int err
Definition: win32.c:135
void InitVM_process(void)
Definition: process.c:7578
static VALUE timetick2dblnum_reciprocal(struct timetick *ttp, timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators)
Definition: process.c:7025
#define ISLOWER(c)
Definition: ruby.h:2126
#define F_GETFD
Definition: win32.h:582
static size_t memsize_exec_arg(const void *ptr)
Definition: process.c:1358
#define ALLOCV_END(v)
Definition: ruby.h:1658
static VALUE make_clock_result(struct timetick *ttp, timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators, VALUE unit)
Definition: process.c:7092
static int save_redirect_fd(int fd, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
Definition: process.c:2630
static VALUE save_env_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
Definition: process.c:2989
static VALUE proc_geteuid(VALUE obj)
Definition: process.c:6293
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Definition: object.c:1891
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:616
rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
Definition: process.c:4000
#define WSTOPSIG
Definition: process.c:122
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2562
static void before_exec(void)
Definition: process.c:1181
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2335
#define id_status
Definition: process.c:285
VALUE rb_thread_local_aset(VALUE, ID, VALUE)
Definition: thread.c:3146
VALUE rb_clock_gettime(int argc, VALUE *argv)
Definition: process.c:7268
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
static ID id_out
Definition: process.c:260
#define RSTRING_LEN(str)
Definition: ruby.h:978
static VALUE rb_check_exec_env(VALUE hash, VALUE *path)
Definition: process.c:1973
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:1020
timetick_int_t giga_count
Definition: process.c:6999
#define proc_getpgid
Definition: process.c:4493
unsigned close_others_given
Definition: internal.h:1379
static int compare_posix_sh(const void *key, const void *el)
Definition: process.c:2067
int rb_during_gc(void)
Definition: gc.c:6664
#define p_sys_setruid
Definition: process.c:5237
int errno
#define TRUE
Definition: nkf.h:175
#define proc_seteuid_m
Definition: process.c:6339
#define CLOCK_REALTIME
Definition: win32.h:133
static VALUE p_uid_switch(VALUE obj)
Definition: process.c:6747
static VALUE pst_wcoredump(VALUE st)
Definition: process.c:848
#define p_sys_setresgid
Definition: process.c:5697
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1440
static int chfunc(void *data, char *errbuf, size_t errbuf_len)
Definition: pty.c:91
static int under_uid_switch
Definition: process.c:5010
#define parent_redirect_close(fd)
Definition: process.c:403
#define proc_setgid
Definition: process.c:5783
static int close_unless_reserved(int fd)
Definition: process.c:297
static int proc_exec_cmd(const char *prog, VALUE argv_str, VALUE envp_str)
Definition: process.c:1243
static ID id_float_second
Definition: process.c:270
#define EXIT_FAILURE
Definition: process.c:43
#define RHASH_SIZE(hsh)
Definition: fbuffer.h:8
VALUE rb_hash_new(void)
Definition: hash.c:441
static void save_env(struct rb_execarg *sargp)
Definition: process.c:2996
static VALUE pst_pid(VALUE st)
Definition: process.c:532
void rb_str_modify_expand(VALUE, long)
Definition: string.c:1988
static void pst_message(VALUE str, rb_pid_t pid, int status)
Definition: process.c:538
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1364
VALUE redirect_fds
Definition: internal.h:1370
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:736
#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:1380
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:623
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
#define PATH_ENV
Definition: defines.h:297
int setgid(rb_gid_t)
Definition: win32.c:2744
VALUE tied_io_for_writing
Definition: io.h:73
VALUE path_env
Definition: internal.h:1397
static VALUE detach_process_watcher(void *arg)
Definition: process.c:1085
#define OBJ2GID(id)
Definition: process.c:242
#define Qnil
Definition: ruby.h:438
unsigned new_pgroup_given
Definition: internal.h:1382
struct rb_execarg::@139::@141 cmd
const char * ptr
Definition: process.c:2062
#define mode_t
Definition: win32.h:119
static VALUE p_gid_switch(VALUE obj)
Definition: process.c:6860
#define p_sys_setregid
Definition: process.c:5668
unsigned long VALUE
Definition: ruby.h:85
VALUE rb_mProcUID
Definition: process.c:7567
rb_uid_t geteuid(void)
Definition: win32.c:2716
static VALUE result
Definition: nkf.c:40
RUBY_EXTERN VALUE rb_cThread
Definition: ruby.h:1909
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
#define CHILD_ERRMSG_BUFLEN
const char * rb_class2name(VALUE)
Definition: variable.c:449
char * strchr(char *, char)
#define FIX2INT(x)
Definition: ruby.h:686
VALUE argv_buf
Definition: internal.h:1367
#define NUM2GIDT(v)
Definition: ruby.h:338
ID ruby_static_id_status
Definition: eval.c:27
VALUE rb_io_puts(int, const VALUE *, VALUE)
Definition: io.c:7212
#define rb_ary_new3
Definition: intern.h:91
int clock_gettime(clockid_t, struct timespec *)
Definition: win32.c:4592
#define p_sys_setgid
Definition: process.c:5595
#define EPERM
Definition: _sdbm.c:93
mode_t umask_mask
Definition: internal.h:1388
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:923
unsigned pgroup_given
Definition: internal.h:1375
#define proc_setmaxgroups
Definition: process.c:6005
VALUE rb_str_new_cstr(const char *)
Definition: string.c:770
static int check_exec_options_i_extract(st_data_t st_key, st_data_t st_val, st_data_t arg)
Definition: process.c:1828
long tms_utime
Definition: win32.h:712
#define WIFSIGNALED(w)
Definition: process.c:110
VALUE flags
Definition: internal.h:801
#define RARRAY_LENINT(ary)
Definition: ruby.h:1027
#define NSIG
Definition: vm_core.h:95
VALUE fd_dup2_child
Definition: internal.h:1395
void rb_sys_fail(const char *mesg)
Definition: error.c:2326
static int intcmp(const void *a, const void *b)
Definition: process.c:2664
void rb_jump_tag(int tag)
Definition: eval.c:788
VALUE rb_str_dup(VALUE)
Definition: string.c:1436
void ruby_error_print(void)
Definition: eval_error.c:185
#define PREPARE_GETGRNAM
Definition: process.c:239
#define proc_setuid
Definition: process.c:5377
int rb_reserved_fd_p(int fd)
#define ERRMSG(str)
Definition: process.c:2621
VALUE rb_mProcess
Definition: process.c:7566
static void security(const char *str)
Definition: process.c:1213
#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:1394
static int check_exec_options_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
Definition: process.c:1813
#define endpwent()
#define RSTRING_PTR(str)
Definition: ruby.h:982
static rb_uid_t rb_seteuid_core(rb_uid_t euid)
Definition: process.c:6343
static ID id_second
Definition: process.c:269
static VALUE p_gid_grant_privilege(VALUE obj, VALUE id)
Definition: process.c:6527
static VALUE do_spawn_process(VALUE arg)
Definition: process.c:3970
void rb_thread_wait_for(struct timeval)
Definition: thread.c:1201
static VALUE timetick2integer(struct timetick *ttp, timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators)
Definition: process.c:7049
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:3894
#define RARRAY_ASET(a, i, v)
Definition: ruby.h:1041
#define try_with_sh(prog, argv, envp)
Definition: process.c:1238
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:86
RUBY_EXTERN VALUE rb_stderr
Definition: ruby.h:1950
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:1373
RUBY_EXTERN VALUE rb_cStruct
Definition: ruby.h:1907
VALUE fd_close
Definition: internal.h:1393
unsigned gid_given
Definition: internal.h:1385
#define RARRAY_AREF(a, i)
Definition: ruby.h:1040
static VALUE pst_wifstopped(VALUE st)
Definition: process.c:699
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2643
#define redirect_dup2(oldfd, newfd)
Definition: process.c:398
static VALUE p_gid_exchange(VALUE obj)
Definition: process.c:6631
static VALUE p_uid_grant_privilege(VALUE obj, VALUE id)
Definition: process.c:6397
VALUE envp_buf
Definition: internal.h:1372
int getrusage(int who, struct rusage *usage)
static VALUE pst_to_i(VALUE st)
Definition: process.c:513
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:635
#define p_sys_setuid
Definition: process.c:5215
static void check_uid_switch(void)
Definition: process.c:5012
rb_pid_t rb_spawn(int argc, const VALUE *argv)
Definition: process.c:4006
#define WEXITSTATUS(w)
Definition: process.c:116
#define RARRAY_PTR(a)
Definition: ruby.h:1048
#define FD_CLOEXEC
Definition: win32.h:589
#define MAXPATHLEN
Definition: process.c:59
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1480
unsigned chdir_given
Definition: internal.h:1381
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:2320
#define RHASH_TBL_RAW(h)
Definition: internal.h:1118
#define GIDT2NUM(v)
Definition: ruby.h:335
void rb_thread_reset_timer_thread(void)
Definition: thread.c:4081
VALUE rb_check_string_type(VALUE)
Definition: string.c:2164
static VALUE proc_getegid(VALUE obj)
Definition: process.c:6417
static rb_pid_t do_waitpid_nonblocking(rb_pid_t pid, int *st, int flags)
Definition: process.c:889
static ID id_chdir
Definition: process.c:268
int clock_getres(clockid_t, struct timespec *)
Definition: win32.c:4630
#define LONG2FIX(i)
Definition: ruby.h:234
static VALUE get_ppid(void)
Definition: process.c:440
#define ARGVSTR2ARGV(argv_str)
Definition: internal.h:1406
static ID id_unsetenv_others
Definition: process.c:268
static int exit_status_code(VALUE status)
Definition: process.c:3729
#define RTEST(v)
Definition: ruby.h:450
void rb_thread_check_ints(void)
Definition: thread.c:1215
#define T_STRING
Definition: ruby.h:496
#define rb_intern(str)
VALUE chdir_dir
Definition: internal.h:1398
#define proc_setrlimit
Definition: process.c:5007
size_t rb_str_capacity(VALUE str)
Definition: string.c:674
#define rb_proc_times
Definition: process.c:6936
#define EWOULDBLOCK
Definition: rubysocket.h:128
#define T_FILE
Definition: ruby.h:502
#define RB_BUILTIN_TYPE(x)
Definition: ruby.h:517
static int fill_envp_buf_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
Definition: process.c:2301
static VALUE p_gid_sw_ensure(VALUE obj)
Definition: process.c:6853
static VALUE pst_inspect(VALUE st)
Definition: process.c:611
#define parent_redirect_open(pathname, flags, perm)
Definition: process.c:402
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1182
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1927
void rb_notimplement(void)
Definition: error.c:2253
void rb_last_status_clear(void)
Definition: process.c:494
#define SafeStringValue(v)
Definition: ruby.h:574
#define TIMETICK_INT_MIN
Definition: process.c:6946
VALUE rb_eNotImpError
Definition: error.c:772
static VALUE rb_f_sleep(int argc, VALUE *argv)
Definition: process.c:4393
#define st_insert
Definition: regint.h:184
static int proc_exec_sh(const char *str, VALUE envp_str)
Definition: process.c:1277
#define DIV(n, d)
Definition: process.c:7046
const char * name
Definition: nkf.c:208
static VALUE p_uid_change_privilege(VALUE obj, VALUE id)
Definition: process.c:5422
#define ID2SYM(x)
Definition: ruby.h:383
#define NUM2MODET(v)
Definition: ruby.h:341
static VALUE rb_exec_getargs(int *argc_p, VALUE **argv_p, int accept_shell, VALUE *env_ret, VALUE *opthash_ret)
Definition: process.c:2029
static ID id_GETTIMEOFDAY_BASED_CLOCK_REALTIME
Definition: process.c:271
#define StringValuePtr(v)
Definition: ruby.h:570
#define redirect_dup(oldfd)
Definition: process.c:397
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
static void rb_exec_fail(struct rb_execarg *eargp, int err, const char *errmsg)
Definition: process.c:2503
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1123
#define RB_MAX_GROUPS
Definition: internal.h:1356
#define tmpbuf(n, size)
Definition: array.c:4954
#define PREPARE_GETPWNAM
Definition: process.c:196
int rb_cloexec_dup(int oldfd)
Definition: io.c:281
#define UIDT2NUM(v)
Definition: ruby.h:329
unsigned use_shell
Definition: internal.h:1374
VALUE rb_env_clear(void)
Definition: hash.c:3891
rb_gid_t getgid(void)
Definition: win32.c:2723
static VALUE proc_getuid(VALUE obj)
Definition: process.c:5334
#define proc_setgroups
Definition: process.c:5922
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1141
void void xfree(void *)
#define proc_getsid
Definition: process.c:4549
long tms_cutime
Definition: win32.h:714
int flags
Definition: process.c:864
#define RHASH_EMPTY_P(h)
Definition: ruby.h:1067
VALUE rb_define_module(const char *name)
Definition: class.c:768
#define p_uid_from_name
Definition: process.c:202
static VALUE check_exec_redirect1(VALUE ary, VALUE key, VALUE param)
Definition: process.c:1512
int32_t count
Definition: process.c:7000
#define ARGVSTR2ARGC(argv_str)
Definition: internal.h:1405
VALUE rb_str_buf_new(long)
Definition: string.c:1247
unsigned new_pgroup_flag
Definition: internal.h:1383
#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
VALUE rb_eSystemExit
Definition: error.c:756
#define NULL
Definition: _sdbm.c:102
static VALUE get_pid(void)
Definition: process.c:417
static VALUE rb_execarg_parent_start1(VALUE execarg_obj)
Definition: process.c:2337
static int fd_set_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
Definition: process.c:2707
#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:5725
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:823
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:3384
#define NOFILE
Definition: io.c:75
int setuid(rb_uid_t)
Definition: win32.c:2737
void rb_warn(const char *fmt,...)
Definition: error.c:221
static VALUE pst_wexitstatus(VALUE st)
Definition: process.c:810
VALUE rb_clock_getres(int argc, VALUE *argv)
Definition: process.c:7463
VALUE rb_eArgError
Definition: error.c:763
static int intrcmp(const void *a, const void *b)
Definition: process.c:2670
#define FINISH_GETGRNAM
Definition: process.c:240
struct rb_execarg::@139::@140 sh
rb_pid_t waitpid(rb_pid_t, int *, int)
Definition: win32.c:4479
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1273
#define redirect_cloexec_dup(oldfd)
Definition: process.c:399
char ** argv
Definition: ruby.c:184
#define DBL2NUM(dbl)
Definition: ruby.h:941
#define StringValue(v)
Definition: ruby.h:569
static int fd_clear_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
Definition: process.c:2730
#define RUBY_UBF_IO
Definition: intern.h:900
void Init_process(void)
Definition: process.c:7970
#define rb_sym2str(sym)
Definition: console.c:107
VALUE rb_f_abort(int argc, const VALUE *argv)
Definition: process.c:3862
void rb_thread_sleep_forever(void)
Definition: thread.c:1156
VALUE rb_str_new(const char *, long)
Definition: string.c:736
#define dln_find_exe_r
Definition: win32.c:82
int * st
Definition: process.c:865