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