Ruby  1.9.3p392(2013-02-22revision39386)
process.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  process.c -
4 
5  $Author: naruse $
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/util.h"
17 #include "internal.h"
18 #include "vm_core.h"
19 
20 #include <stdio.h>
21 #include <errno.h>
22 #include <signal.h>
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #ifdef HAVE_FCNTL_H
30 #include <fcntl.h>
31 #endif
32 #ifdef HAVE_PROCESS_H
33 #include <process.h>
34 #endif
35 
36 #include <time.h>
37 #include <ctype.h>
38 
39 #ifndef EXIT_SUCCESS
40 #define EXIT_SUCCESS 0
41 #endif
42 #ifndef EXIT_FAILURE
43 #define EXIT_FAILURE 1
44 #endif
45 
46 #ifdef HAVE_SYS_WAIT_H
47 # include <sys/wait.h>
48 #endif
49 #ifdef HAVE_SYS_RESOURCE_H
50 # include <sys/resource.h>
51 #endif
52 #ifdef HAVE_SYS_PARAM_H
53 # include <sys/param.h>
54 #endif
55 #ifndef MAXPATHLEN
56 # define MAXPATHLEN 1024
57 #endif
58 #include "ruby/st.h"
59 
60 #ifdef __EMX__
61 #undef HAVE_GETPGRP
62 #endif
63 
64 #include <sys/stat.h>
65 
66 #ifdef HAVE_SYS_TIMES_H
67 #include <sys/times.h>
68 #endif
69 
70 #ifdef HAVE_GRP_H
71 #include <grp.h>
72 #endif
73 
74 #if defined(HAVE_TIMES) || defined(_WIN32)
75 static VALUE rb_cProcessTms;
76 #endif
77 
78 #ifndef WIFEXITED
79 #define WIFEXITED(w) (((w) & 0xff) == 0)
80 #endif
81 #ifndef WIFSIGNALED
82 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
83 #endif
84 #ifndef WIFSTOPPED
85 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
86 #endif
87 #ifndef WEXITSTATUS
88 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
89 #endif
90 #ifndef WTERMSIG
91 #define WTERMSIG(w) ((w) & 0x7f)
92 #endif
93 #ifndef WSTOPSIG
94 #define WSTOPSIG WEXITSTATUS
95 #endif
96 
97 #if defined(__APPLE__) && ( defined(__MACH__) || defined(__DARWIN__) ) && !defined(__MacOS_X__)
98 #define __MacOS_X__ 1
99 #endif
100 
101 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
102 #define HAVE_44BSD_SETUID 1
103 #define HAVE_44BSD_SETGID 1
104 #endif
105 
106 #ifdef __NetBSD__
107 #undef HAVE_SETRUID
108 #undef HAVE_SETRGID
109 #endif
110 
111 #ifdef BROKEN_SETREUID
112 #define setreuid ruby_setreuid
113 int setreuid(rb_uid_t ruid, rb_uid_t euid);
114 #endif
115 #ifdef BROKEN_SETREGID
116 #define setregid ruby_setregid
117 int setregid(rb_gid_t rgid, rb_gid_t egid);
118 #endif
119 
120 #if defined(HAVE_44BSD_SETUID) || defined(__MacOS_X__)
121 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
122 #define OBSOLETE_SETREUID 1
123 #endif
124 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
125 #define OBSOLETE_SETREGID 1
126 #endif
127 #endif
128 
129 #define preserving_errno(stmts) \
130  do {int saved_errno = errno; stmts; errno = saved_errno;} while (0)
131 
132 
133 /*
134  * call-seq:
135  * Process.pid -> fixnum
136  *
137  * Returns the process id of this process. Not available on all
138  * platforms.
139  *
140  * Process.pid #=> 27415
141  */
142 
143 static VALUE
144 get_pid(void)
145 {
146  rb_secure(2);
147  return PIDT2NUM(getpid());
148 }
149 
150 
151 /*
152  * call-seq:
153  * Process.ppid -> fixnum
154  *
155  * Returns the process id of the parent of this process. Returns
156  * untrustworthy value on Win32/64. Not available on all platforms.
157  *
158  * puts "I am #{Process.pid}"
159  * Process.fork { puts "Dad is #{Process.ppid}" }
160  *
161  * <em>produces:</em>
162  *
163  * I am 27417
164  * Dad is 27417
165  */
166 
167 static VALUE
168 get_ppid(void)
169 {
170  rb_secure(2);
171  return PIDT2NUM(getppid());
172 }
173 
174 
175 /*********************************************************************
176  *
177  * Document-class: Process::Status
178  *
179  * <code>Process::Status</code> encapsulates the information on the
180  * status of a running or terminated system process. The built-in
181  * variable <code>$?</code> is either +nil+ or a
182  * <code>Process::Status</code> object.
183  *
184  * fork { exit 99 } #=> 26557
185  * Process.wait #=> 26557
186  * $?.class #=> Process::Status
187  * $?.to_i #=> 25344
188  * $? >> 8 #=> 99
189  * $?.stopped? #=> false
190  * $?.exited? #=> true
191  * $?.exitstatus #=> 99
192  *
193  * Posix systems record information on processes using a 16-bit
194  * integer. The lower bits record the process status (stopped,
195  * exited, signaled) and the upper bits possibly contain additional
196  * information (for example the program's return code in the case of
197  * exited processes). Pre Ruby 1.8, these bits were exposed directly
198  * to the Ruby program. Ruby now encapsulates these in a
199  * <code>Process::Status</code> object. To maximize compatibility,
200  * however, these objects retain a bit-oriented interface. In the
201  * descriptions that follow, when we talk about the integer value of
202  * _stat_, we're referring to this 16 bit value.
203  */
204 
206 
207 VALUE
209 {
210  return GET_THREAD()->last_status;
211 }
212 
213 void
214 rb_last_status_set(int status, rb_pid_t pid)
215 {
216  rb_thread_t *th = GET_THREAD();
218  rb_iv_set(th->last_status, "status", INT2FIX(status));
219  rb_iv_set(th->last_status, "pid", PIDT2NUM(pid));
220 }
221 
222 static void
224 {
225  GET_THREAD()->last_status = Qnil;
226 }
227 
228 /*
229  * call-seq:
230  * stat.to_i -> fixnum
231  * stat.to_int -> fixnum
232  *
233  * Returns the bits in _stat_ as a <code>Fixnum</code>. Poking
234  * around in these bits is platform dependent.
235  *
236  * fork { exit 0xab } #=> 26566
237  * Process.wait #=> 26566
238  * sprintf('%04x', $?.to_i) #=> "ab00"
239  */
240 
241 static VALUE
243 {
244  return rb_iv_get(st, "status");
245 }
246 
247 #define PST2INT(st) NUM2INT(pst_to_i(st))
248 
249 /*
250  * call-seq:
251  * stat.pid -> fixnum
252  *
253  * Returns the process ID that this status object represents.
254  *
255  * fork { exit } #=> 26569
256  * Process.wait #=> 26569
257  * $?.pid #=> 26569
258  */
259 
260 static VALUE
262 {
263  return rb_attr_get(st, rb_intern("pid"));
264 }
265 
266 static void
267 pst_message(VALUE str, rb_pid_t pid, int status)
268 {
269  rb_str_catf(str, "pid %ld", (long)pid);
270  if (WIFSTOPPED(status)) {
271  int stopsig = WSTOPSIG(status);
272  const char *signame = ruby_signal_name(stopsig);
273  if (signame) {
274  rb_str_catf(str, " stopped SIG%s (signal %d)", signame, stopsig);
275  }
276  else {
277  rb_str_catf(str, " stopped signal %d", stopsig);
278  }
279  }
280  if (WIFSIGNALED(status)) {
281  int termsig = WTERMSIG(status);
282  const char *signame = ruby_signal_name(termsig);
283  if (signame) {
284  rb_str_catf(str, " SIG%s (signal %d)", signame, termsig);
285  }
286  else {
287  rb_str_catf(str, " signal %d", termsig);
288  }
289  }
290  if (WIFEXITED(status)) {
291  rb_str_catf(str, " exit %d", WEXITSTATUS(status));
292  }
293 #ifdef WCOREDUMP
294  if (WCOREDUMP(status)) {
295  rb_str_cat2(str, " (core dumped)");
296  }
297 #endif
298 }
299 
300 
301 /*
302  * call-seq:
303  * stat.to_s -> string
304  *
305  * Show pid and exit status as a string.
306  *
307  * system("false")
308  * p $?.to_s #=> "pid 12766 exit 1"
309  *
310  */
311 
312 static VALUE
314 {
315  rb_pid_t pid;
316  int status;
317  VALUE str;
318 
319  pid = NUM2PIDT(pst_pid(st));
320  status = PST2INT(st);
321 
322  str = rb_str_buf_new(0);
323  pst_message(str, pid, status);
324  return str;
325 }
326 
327 
328 /*
329  * call-seq:
330  * stat.inspect -> string
331  *
332  * Override the inspection method.
333  *
334  * system("false")
335  * p $?.inspect #=> "#<Process::Status: pid 12861 exit 1>"
336  *
337  */
338 
339 static VALUE
341 {
342  rb_pid_t pid;
343  int status;
344  VALUE vpid, str;
345 
346  vpid = pst_pid(st);
347  if (NIL_P(vpid)) {
348  return rb_sprintf("#<%s: uninitialized>", rb_class2name(CLASS_OF(st)));
349  }
350  pid = NUM2PIDT(vpid);
351  status = PST2INT(st);
352 
353  str = rb_sprintf("#<%s: ", rb_class2name(CLASS_OF(st)));
354  pst_message(str, pid, status);
355  rb_str_cat2(str, ">");
356  return str;
357 }
358 
359 
360 /*
361  * call-seq:
362  * stat == other -> true or false
363  *
364  * Returns +true+ if the integer value of _stat_
365  * equals <em>other</em>.
366  */
367 
368 static VALUE
370 {
371  if (st1 == st2) return Qtrue;
372  return rb_equal(pst_to_i(st1), st2);
373 }
374 
375 
376 /*
377  * call-seq:
378  * stat & num -> fixnum
379  *
380  * Logical AND of the bits in _stat_ with <em>num</em>.
381  *
382  * fork { exit 0x37 }
383  * Process.wait
384  * sprintf('%04x', $?.to_i) #=> "3700"
385  * sprintf('%04x', $? & 0x1e00) #=> "1600"
386  */
387 
388 static VALUE
390 {
391  int status = PST2INT(st1) & NUM2INT(st2);
392 
393  return INT2NUM(status);
394 }
395 
396 
397 /*
398  * call-seq:
399  * stat >> num -> fixnum
400  *
401  * Shift the bits in _stat_ right <em>num</em> places.
402  *
403  * fork { exit 99 } #=> 26563
404  * Process.wait #=> 26563
405  * $?.to_i #=> 25344
406  * $? >> 8 #=> 99
407  */
408 
409 static VALUE
411 {
412  int status = PST2INT(st1) >> NUM2INT(st2);
413 
414  return INT2NUM(status);
415 }
416 
417 
418 /*
419  * call-seq:
420  * stat.stopped? -> true or false
421  *
422  * Returns +true+ if this process is stopped. This is only
423  * returned if the corresponding <code>wait</code> call had the
424  * <code>WUNTRACED</code> flag set.
425  */
426 
427 static VALUE
429 {
430  int status = PST2INT(st);
431 
432  if (WIFSTOPPED(status))
433  return Qtrue;
434  else
435  return Qfalse;
436 }
437 
438 
439 /*
440  * call-seq:
441  * stat.stopsig -> fixnum or nil
442  *
443  * Returns the number of the signal that caused _stat_ to stop
444  * (or +nil+ if self is not stopped).
445  */
446 
447 static VALUE
449 {
450  int status = PST2INT(st);
451 
452  if (WIFSTOPPED(status))
453  return INT2NUM(WSTOPSIG(status));
454  return Qnil;
455 }
456 
457 
458 /*
459  * call-seq:
460  * stat.signaled? -> true or false
461  *
462  * Returns +true+ if _stat_ terminated because of
463  * an uncaught signal.
464  */
465 
466 static VALUE
468 {
469  int status = PST2INT(st);
470 
471  if (WIFSIGNALED(status))
472  return Qtrue;
473  else
474  return Qfalse;
475 }
476 
477 
478 /*
479  * call-seq:
480  * stat.termsig -> fixnum or nil
481  *
482  * Returns the number of the signal that caused _stat_ to
483  * terminate (or +nil+ if self was not terminated by an
484  * uncaught signal).
485  */
486 
487 static VALUE
489 {
490  int status = PST2INT(st);
491 
492  if (WIFSIGNALED(status))
493  return INT2NUM(WTERMSIG(status));
494  return Qnil;
495 }
496 
497 
498 /*
499  * call-seq:
500  * stat.exited? -> true or false
501  *
502  * Returns +true+ if _stat_ exited normally (for
503  * example using an <code>exit()</code> call or finishing the
504  * program).
505  */
506 
507 static VALUE
509 {
510  int status = PST2INT(st);
511 
512  if (WIFEXITED(status))
513  return Qtrue;
514  else
515  return Qfalse;
516 }
517 
518 
519 /*
520  * call-seq:
521  * stat.exitstatus -> fixnum or nil
522  *
523  * Returns the least significant eight bits of the return code of
524  * _stat_. Only available if <code>exited?</code> is
525  * +true+.
526  *
527  * fork { } #=> 26572
528  * Process.wait #=> 26572
529  * $?.exited? #=> true
530  * $?.exitstatus #=> 0
531  *
532  * fork { exit 99 } #=> 26573
533  * Process.wait #=> 26573
534  * $?.exited? #=> true
535  * $?.exitstatus #=> 99
536  */
537 
538 static VALUE
540 {
541  int status = PST2INT(st);
542 
543  if (WIFEXITED(status))
544  return INT2NUM(WEXITSTATUS(status));
545  return Qnil;
546 }
547 
548 
549 /*
550  * call-seq:
551  * stat.success? -> true, false or nil
552  *
553  * Returns +true+ if _stat_ is successful, +false+ if not.
554  * Returns +nil+ if <code>exited?</code> is not +true+.
555  */
556 
557 static VALUE
559 {
560  int status = PST2INT(st);
561 
562  if (!WIFEXITED(status))
563  return Qnil;
564  return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
565 }
566 
567 
568 /*
569  * call-seq:
570  * stat.coredump? -> true or false
571  *
572  * Returns +true+ if _stat_ generated a coredump
573  * when it terminated. Not available on all platforms.
574  */
575 
576 static VALUE
578 {
579 #ifdef WCOREDUMP
580  int status = PST2INT(st);
581 
582  if (WCOREDUMP(status))
583  return Qtrue;
584  else
585  return Qfalse;
586 #else
587  return Qfalse;
588 #endif
589 }
590 
591 #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
592 #define NO_WAITPID
594 
595 struct wait_data {
596  rb_pid_t pid;
597  int status;
598 };
599 
600 static int
601 wait_each(rb_pid_t pid, int status, struct wait_data *data)
602 {
603  if (data->status != -1) return ST_STOP;
604 
605  data->pid = pid;
606  data->status = status;
607  return ST_DELETE;
608 }
609 
610 static int
611 waitall_each(rb_pid_t pid, int status, VALUE ary)
612 {
613  rb_last_status_set(status, pid);
615  return ST_DELETE;
616 }
617 #else
618 struct waitpid_arg {
619  rb_pid_t pid;
620  int *st;
621  int flags;
622 };
623 #endif
624 
625 static VALUE
627 {
628  rb_pid_t result;
629 #ifndef NO_WAITPID
630  struct waitpid_arg *arg = data;
631 #endif
632 
633 #if defined NO_WAITPID
634  result = wait(data);
635 #elif defined HAVE_WAITPID
636  result = waitpid(arg->pid, arg->st, arg->flags);
637 #else /* HAVE_WAIT4 */
638  result = wait4(arg->pid, arg->st, arg->flags, NULL);
639 #endif
640 
641  return (VALUE)result;
642 }
643 
644 rb_pid_t
645 rb_waitpid(rb_pid_t pid, int *st, int flags)
646 {
647  rb_pid_t result;
648 #ifndef NO_WAITPID
649  struct waitpid_arg arg;
650 
651  retry:
652  arg.pid = pid;
653  arg.st = st;
654  arg.flags = flags;
655  result = (rb_pid_t)rb_thread_blocking_region(rb_waitpid_blocking, &arg,
656  RUBY_UBF_PROCESS, 0);
657  if (result < 0) {
658  if (errno == EINTR) {
660  goto retry;
661  }
662  return (rb_pid_t)-1;
663  }
664 #else /* NO_WAITPID */
665  if (pid_tbl) {
666  st_data_t status, piddata = (st_data_t)pid;
667  if (pid == (rb_pid_t)-1) {
668  struct wait_data data;
669  data.pid = (rb_pid_t)-1;
670  data.status = -1;
671  st_foreach(pid_tbl, wait_each, (st_data_t)&data);
672  if (data.status != -1) {
673  rb_last_status_set(data.status, data.pid);
674  return data.pid;
675  }
676  }
677  else if (st_delete(pid_tbl, &piddata, &status)) {
678  rb_last_status_set(*st = (int)status, pid);
679  return pid;
680  }
681  }
682 
683  if (flags) {
684  rb_raise(rb_eArgError, "can't do waitpid with flags");
685  }
686 
687  for (;;) {
689  st, RUBY_UBF_PROCESS, 0);
690  if (result < 0) {
691  if (errno == EINTR) {
693  continue;
694  }
695  return (rb_pid_t)-1;
696  }
697  if (result == pid || pid == (rb_pid_t)-1) {
698  break;
699  }
700  if (!pid_tbl)
701  pid_tbl = st_init_numtable();
702  st_insert(pid_tbl, pid, (st_data_t)st);
704  }
705 #endif
706  if (result > 0) {
707  rb_last_status_set(*st, result);
708  }
709  return result;
710 }
711 
712 
713 /* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
714  has historically been documented as if it didn't take any arguments
715  despite the fact that it's just an alias for ::waitpid(). The way I
716  have it below is more truthful, but a little confusing.
717 
718  I also took the liberty of putting in the pid values, as they're
719  pretty useful, and it looked as if the original 'ri' output was
720  supposed to contain them after "[...]depending on the value of
721  aPid:".
722 
723  The 'ansi' and 'bs' formats of the ri output don't display the
724  definition list for some reason, but the plain text one does.
725  */
726 
727 /*
728  * call-seq:
729  * Process.wait() -> fixnum
730  * Process.wait(pid=-1, flags=0) -> fixnum
731  * Process.waitpid(pid=-1, flags=0) -> fixnum
732  *
733  * Waits for a child process to exit, returns its process id, and
734  * sets <code>$?</code> to a <code>Process::Status</code> object
735  * containing information on that process. Which child it waits on
736  * depends on the value of _pid_:
737  *
738  * > 0:: Waits for the child whose process ID equals _pid_.
739  *
740  * 0:: Waits for any child whose process group ID equals that of the
741  * calling process.
742  *
743  * -1:: Waits for any child process (the default if no _pid_ is
744  * given).
745  *
746  * < -1:: Waits for any child whose process group ID equals the absolute
747  * value of _pid_.
748  *
749  * The _flags_ argument may be a logical or of the flag values
750  * <code>Process::WNOHANG</code> (do not block if no child available)
751  * or <code>Process::WUNTRACED</code> (return stopped children that
752  * haven't been reported). Not all flags are available on all
753  * platforms, but a flag value of zero will work on all platforms.
754  *
755  * Calling this method raises a <code>SystemError</code> if there are
756  * no child processes. Not available on all platforms.
757  *
758  * include Process
759  * fork { exit 99 } #=> 27429
760  * wait #=> 27429
761  * $?.exitstatus #=> 99
762  *
763  * pid = fork { sleep 3 } #=> 27440
764  * Time.now #=> 2008-03-08 19:56:16 +0900
765  * waitpid(pid, Process::WNOHANG) #=> nil
766  * Time.now #=> 2008-03-08 19:56:16 +0900
767  * waitpid(pid, 0) #=> 27440
768  * Time.now #=> 2008-03-08 19:56:19 +0900
769  */
770 
771 static VALUE
773 {
774  VALUE vpid, vflags;
775  rb_pid_t pid;
776  int flags, status;
777 
778  rb_secure(2);
779  flags = 0;
780  if (argc == 0) {
781  pid = -1;
782  }
783  else {
784  rb_scan_args(argc, argv, "02", &vpid, &vflags);
785  pid = NUM2PIDT(vpid);
786  if (argc == 2 && !NIL_P(vflags)) {
787  flags = NUM2UINT(vflags);
788  }
789  }
790  if ((pid = rb_waitpid(pid, &status, flags)) < 0)
791  rb_sys_fail(0);
792  if (pid == 0) {
794  return Qnil;
795  }
796  return PIDT2NUM(pid);
797 }
798 
799 
800 /*
801  * call-seq:
802  * Process.wait2(pid=-1, flags=0) -> [pid, status]
803  * Process.waitpid2(pid=-1, flags=0) -> [pid, status]
804  *
805  * Waits for a child process to exit (see Process::waitpid for exact
806  * semantics) and returns an array containing the process id and the
807  * exit status (a <code>Process::Status</code> object) of that
808  * child. Raises a <code>SystemError</code> if there are no child
809  * processes.
810  *
811  * Process.fork { exit 99 } #=> 27437
812  * pid, status = Process.wait2
813  * pid #=> 27437
814  * status.exitstatus #=> 99
815  */
816 
817 static VALUE
819 {
820  VALUE pid = proc_wait(argc, argv);
821  if (NIL_P(pid)) return Qnil;
822  return rb_assoc_new(pid, rb_last_status_get());
823 }
824 
825 
826 /*
827  * call-seq:
828  * Process.waitall -> [ [pid1,status1], ...]
829  *
830  * Waits for all children, returning an array of
831  * _pid_/_status_ pairs (where _status_ is a
832  * <code>Process::Status</code> object).
833  *
834  * fork { sleep 0.2; exit 2 } #=> 27432
835  * fork { sleep 0.1; exit 1 } #=> 27433
836  * fork { exit 0 } #=> 27434
837  * p Process.waitall
838  *
839  * <em>produces</em>:
840  *
841  * [[30982, #<Process::Status: pid 30982 exit 0>],
842  * [30979, #<Process::Status: pid 30979 exit 1>],
843  * [30976, #<Process::Status: pid 30976 exit 2>]]
844  */
845 
846 static VALUE
848 {
849  VALUE result;
850  rb_pid_t pid;
851  int status;
852 
853  rb_secure(2);
854  result = rb_ary_new();
855 #ifdef NO_WAITPID
856  if (pid_tbl) {
857  st_foreach(pid_tbl, waitall_each, result);
858  }
859 #else
861 #endif
862 
863  for (pid = -1;;) {
864 #ifdef NO_WAITPID
865  pid = wait(&status);
866 #else
867  pid = rb_waitpid(-1, &status, 0);
868 #endif
869  if (pid == -1) {
870  if (errno == ECHILD)
871  break;
872 #ifdef NO_WAITPID
873  if (errno == EINTR) {
875  continue;
876  }
877 #endif
878  rb_sys_fail(0);
879  }
880 #ifdef NO_WAITPID
881  rb_last_status_set(status, pid);
882 #endif
884  }
885  return result;
886 }
887 
888 static inline ID
889 id_pid(void)
890 {
891  ID pid;
892  CONST_ID(pid, "pid");
893  return pid;
894 }
895 
896 static VALUE
898 {
899  return rb_thread_local_aref(thread, id_pid());
900 }
901 
902 static VALUE
904 {
905  rb_pid_t cpid, pid = (rb_pid_t)(VALUE)arg;
906  int status;
907 
908  while ((cpid = rb_waitpid(pid, &status, 0)) == 0) {
909  /* wait while alive */
910  }
911  return rb_last_status_get();
912 }
913 
914 VALUE
916 {
917  VALUE watcher = rb_thread_create(detach_process_watcher, (void*)(VALUE)pid);
918  rb_thread_local_aset(watcher, id_pid(), PIDT2NUM(pid));
920  return watcher;
921 }
922 
923 
924 /*
925  * call-seq:
926  * Process.detach(pid) -> thread
927  *
928  * Some operating systems retain the status of terminated child
929  * processes until the parent collects that status (normally using
930  * some variant of <code>wait()</code>. If the parent never collects
931  * this status, the child stays around as a <em>zombie</em> process.
932  * <code>Process::detach</code> prevents this by setting up a
933  * separate Ruby thread whose sole job is to reap the status of the
934  * process _pid_ when it terminates. Use <code>detach</code>
935  * only when you do not intent to explicitly wait for the child to
936  * terminate.
937  *
938  * The waiting thread returns the exit status of the detached process
939  * when it terminates, so you can use <code>Thread#join</code> to
940  * know the result. If specified _pid_ is not a valid child process
941  * ID, the thread returns +nil+ immediately.
942  *
943  * The waiting thread has <code>pid</code> method which returns the pid.
944  *
945  * In this first example, we don't reap the first child process, so
946  * it appears as a zombie in the process status display.
947  *
948  * p1 = fork { sleep 0.1 }
949  * p2 = fork { sleep 0.2 }
950  * Process.waitpid(p2)
951  * sleep 2
952  * system("ps -ho pid,state -p #{p1}")
953  *
954  * <em>produces:</em>
955  *
956  * 27389 Z
957  *
958  * In the next example, <code>Process::detach</code> is used to reap
959  * the child automatically.
960  *
961  * p1 = fork { sleep 0.1 }
962  * p2 = fork { sleep 0.2 }
963  * Process.detach(p1)
964  * Process.waitpid(p2)
965  * sleep 2
966  * system("ps -ho pid,state -p #{p1}")
967  *
968  * <em>(produces no output)</em>
969  */
970 
971 static VALUE
973 {
974  rb_secure(2);
975  return rb_detach_process(NUM2PIDT(pid));
976 }
977 
978 #ifndef HAVE_STRING_H
979 char *strtok();
980 #endif
981 
982 static int forked_child = 0;
983 
984 #ifdef SIGPIPE
985 static RETSIGTYPE (*saved_sigpipe_handler)(int) = 0;
986 #endif
987 
988 #if defined(POSIX_SIGNAL)
989 # define signal(a,b) posix_signal((a),(b))
990 #endif
991 
992 #ifdef SIGPIPE
993 static RETSIGTYPE sig_do_nothing(int sig)
994 {
995 }
996 #endif
997 
998 static void before_exec(void)
999 {
1000  /*
1001  * signalmask is inherited across exec() and almost system commands don't
1002  * work if signalmask is blocked.
1003  */
1005 
1006 #ifdef SIGPIPE
1007  /*
1008  * Some OS commands don't initialize signal handler properly. Thus we have
1009  * to reset signal handler before exec(). Otherwise, system() and similar
1010  * child process interaction might fail. (e.g. ruby -e "system 'yes | ls'")
1011  * [ruby-dev:12261]
1012  */
1013  saved_sigpipe_handler = signal(SIGPIPE, sig_do_nothing);
1014 #endif
1015 
1016  if (!forked_child) {
1017  /*
1018  * On Mac OS X 10.5.x (Leopard) or earlier, exec() may return ENOTSUPP
1019  * if the process have multiple threads. Therefore we have to kill
1020  * internal threads temporary. [ruby-core: 10583]
1021  */
1023  }
1024 }
1025 
1026 static void after_exec(void)
1027 {
1030 
1031 #ifdef SIGPIPE
1032  signal(SIGPIPE, saved_sigpipe_handler);
1033 #endif
1034 
1035  forked_child = 0;
1037 }
1038 
1039 #define before_fork() before_exec()
1040 #define after_fork() (GET_THREAD()->thrown_errinfo = 0, after_exec())
1041 
1042 #include "dln.h"
1043 
1044 static void
1045 security(const char *str)
1046 {
1047  if (rb_env_path_tainted()) {
1048  if (rb_safe_level() > 0) {
1049  rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
1050  }
1051  }
1052 }
1053 
1054 #ifdef HAVE_FORK
1055 #define try_with_sh(prog, argv) ((saved_errno == ENOEXEC) ? exec_with_sh((prog), (argv)) : (void)0)
1056 static void
1057 exec_with_sh(const char *prog, char **argv)
1058 {
1059  *argv = (char *)prog;
1060  *--argv = (char *)"sh";
1061  execv("/bin/sh", argv);
1062 }
1063 #define ARGV_COUNT(n) ((n)+1)
1064 #else
1065 #define try_with_sh(prog, argv) (void)0
1066 #define ARGV_COUNT(n) (n)
1067 #endif
1068 #define ARGV_SIZE(n) (sizeof(char*) * ARGV_COUNT(n))
1069 #define ALLOC_ARGV(n, v) ALLOCV_N(char*, (v), ARGV_COUNT(n))
1070 #define ALLOC_ARGV_WITH_STR(n, v, s, l) \
1071  (char **)(((s) = ALLOCV_N(char, (v), ARGV_SIZE(n) + (l)) + ARGV_SIZE(n)) - ARGV_SIZE(n))
1072 
1073 static int
1074 proc_exec_v(char **argv, const char *prog)
1075 {
1076  char fbuf[MAXPATHLEN];
1077 #if defined(__EMX__) || defined(OS2)
1078  char **new_argv = NULL;
1079 #endif
1080 
1081  if (!prog)
1082  prog = argv[0];
1083  prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
1084  if (!prog) {
1085  errno = ENOENT;
1086  return -1;
1087  }
1088 
1089 #if defined(__EMX__) || defined(OS2)
1090  {
1091 #define COMMAND "cmd.exe"
1092  char *extension;
1093 
1094  if ((extension = strrchr(prog, '.')) != NULL && STRCASECMP(extension, ".bat") == 0) {
1095  char *p;
1096  int n;
1097 
1098  for (n = 0; argv[n]; n++)
1099  /* no-op */;
1100  new_argv = ALLOC_N(char*, n + 2);
1101  for (; n > 0; n--)
1102  new_argv[n + 1] = argv[n];
1103  new_argv[1] = strcpy(ALLOC_N(char, strlen(argv[0]) + 1), argv[0]);
1104  for (p = new_argv[1]; *p != '\0'; p++)
1105  if (*p == '/')
1106  *p = '\\';
1107  new_argv[0] = COMMAND;
1108  argv = new_argv;
1109  prog = dln_find_exe_r(argv[0], 0, fbuf, sizeof(fbuf));
1110  if (!prog) {
1111  errno = ENOENT;
1112  return -1;
1113  }
1114  }
1115  }
1116 #endif /* __EMX__ */
1117  before_exec();
1118  execv(prog, argv);
1119  preserving_errno(try_with_sh(prog, argv); after_exec());
1120 #if defined(__EMX__) || defined(OS2)
1121  if (new_argv) {
1122  xfree(new_argv[0]);
1123  xfree(new_argv);
1124  }
1125 #endif
1126  return -1;
1127 }
1128 
1129 int
1130 rb_proc_exec_n(int argc, VALUE *argv, const char *prog)
1131 {
1132  char **args;
1133  int i;
1134  int ret = -1;
1135  VALUE v;
1136 
1137  args = ALLOC_ARGV(argc+1, v);
1138  for (i=0; i<argc; i++) {
1139  args[i] = RSTRING_PTR(argv[i]);
1140  }
1141  args[i] = 0;
1142  if (args[0]) {
1143  ret = proc_exec_v(args, prog);
1144  }
1145  ALLOCV_END(v);
1146  return -1;
1147 }
1148 
1149 int
1150 rb_proc_exec(const char *str)
1151 {
1152 #ifndef _WIN32
1153  const char *s = str;
1154  char *ss, *t;
1155  char **argv, **a;
1156  VALUE v;
1157  int ret = -1;
1158 #endif
1159 
1160  while (*str && ISSPACE(*str))
1161  str++;
1162 
1163 #ifdef _WIN32
1164  before_exec();
1165  rb_w32_spawn(P_OVERLAY, (char *)str, 0);
1166  after_exec();
1167  return -1;
1168 #else
1169  for (s=str; *s; s++) {
1170  if (ISSPACE(*s)) {
1171  const char *p, *nl = NULL;
1172  for (p = s; ISSPACE(*p); p++) {
1173  if (*p == '\n') nl = p;
1174  }
1175  if (!*p) break;
1176  if (nl) s = nl;
1177  }
1178  if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
1179 #if defined(__CYGWIN32__) || defined(__EMX__)
1180  char fbuf[MAXPATHLEN];
1181  char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
1182  int status = -1;
1183  before_exec();
1184  if (shell)
1185  execl(shell, "sh", "-c", str, (char *) NULL);
1186  else
1187  status = system(str);
1188  after_exec();
1189  if (status != -1)
1190  exit(status);
1191 #else
1192  before_exec();
1193  execl("/bin/sh", "sh", "-c", str, (char *)NULL);
1195 #endif
1196  return -1;
1197  }
1198  }
1199  a = argv = ALLOC_ARGV_WITH_STR((s-str)/2+2, v, ss, s-str+1);
1200  memcpy(ss, str, s-str);
1201  ss[s-str] = '\0';
1202  if ((*a++ = strtok(ss, " \t")) != 0) {
1203  while ((t = strtok(NULL, " \t")) != 0) {
1204  *a++ = t;
1205  }
1206  *a = NULL;
1207  }
1208  if (argv[0]) {
1209  ret = proc_exec_v(argv, 0);
1210  }
1211  else {
1212  errno = ENOENT;
1213  }
1214  ALLOCV_END(v);
1215  return ret;
1216 #endif /* _WIN32 */
1217 }
1218 
1219 enum {
1232 };
1233 
1234 #if defined(_WIN32)
1235 #define HAVE_SPAWNV 1
1236 #endif
1237 
1238 #if !defined(HAVE_FORK) && defined(HAVE_SPAWNV)
1239 # define USE_SPAWNV 1
1240 #else
1241 # define USE_SPAWNV 0
1242 #endif
1243 #ifndef P_NOWAIT
1244 # define P_NOWAIT _P_NOWAIT
1245 #endif
1246 
1247 #if USE_SPAWNV
1248 #if defined(_WIN32)
1249 #define proc_spawn_v(argv, prog) rb_w32_aspawn(P_NOWAIT, (prog), (argv))
1250 #else
1251 static rb_pid_t
1252 proc_spawn_v(char **argv, char *prog)
1253 {
1254  char fbuf[MAXPATHLEN];
1255  rb_pid_t status;
1256 
1257  if (!prog)
1258  prog = argv[0];
1259  security(prog);
1260  prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
1261  if (!prog)
1262  return -1;
1263 
1264  before_exec();
1265  status = spawnv(P_NOWAIT, prog, (const char **)argv);
1266  if (status == -1 && errno == ENOEXEC) {
1267  *argv = (char *)prog;
1268  *--argv = (char *)"sh";
1269  status = spawnv(P_NOWAIT, "/bin/sh", (const char **)argv);
1270  after_exec();
1271  if (status == -1) errno = ENOEXEC;
1272  }
1273  rb_last_status_set(status == -1 ? 127 : status, 0);
1274  return status;
1275 }
1276 #endif
1277 
1278 static rb_pid_t
1279 proc_spawn_n(int argc, VALUE *argv, VALUE prog, VALUE options)
1280 {
1281  char **args;
1282  int i;
1283  VALUE v;
1284  rb_pid_t pid = -1;
1285 
1286  args = ALLOC_ARGV(argc + 1, v);
1287  for (i = 0; i < argc; i++) {
1288  args[i] = RSTRING_PTR(argv[i]);
1289  }
1290  args[i] = (char*) 0;
1291  if (args[0]) {
1292 #if defined(_WIN32)
1293  DWORD flags = 0;
1294  if (RTEST(rb_ary_entry(options, EXEC_OPTION_NEW_PGROUP))) {
1295  flags = CREATE_NEW_PROCESS_GROUP;
1296  }
1297  pid = rb_w32_aspawn_flags(P_NOWAIT, prog ? RSTRING_PTR(prog) : 0, args, flags);
1298 #else
1299  pid = proc_spawn_v(args, prog ? RSTRING_PTR(prog) : 0);
1300 #endif
1301  }
1302  ALLOCV_END(v);
1303  return pid;
1304 }
1305 
1306 #if defined(_WIN32)
1307 #define proc_spawn(str) rb_w32_spawn(P_NOWAIT, (str), 0)
1308 #else
1309 static rb_pid_t
1310 proc_spawn(char *str)
1311 {
1312  char fbuf[MAXPATHLEN];
1313  char *s, *t;
1314  char **argv, **a;
1315  rb_pid_t status;
1316  VALUE v;
1317 
1318  for (s = str; *s; s++) {
1319  if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
1320  char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
1321  before_exec();
1322  status = spawnl(P_NOWAIT, (shell ? shell : "/bin/sh"), "sh", "-c", str, (char*)NULL);
1323  rb_last_status_set(status == -1 ? 127 : status, 0);
1324  after_exec();
1325  return status;
1326  }
1327  }
1328  a = argv = ALLOC_ARGV_WITH_STR((s - str) / 2 + 2, v, s, s - str + 1);
1329  strcpy(s, str);
1330  if (*a++ = strtok(s, " \t")) {
1331  while (t = strtok(NULL, " \t"))
1332  *a++ = t;
1333  *a = NULL;
1334  }
1335  status = argv[0] ? proc_spawn_v(argv, 0) : -1;
1336  ALLOCV_END(v);
1337  return status;
1338 }
1339 #endif
1340 #endif
1341 
1342 static VALUE
1344 {
1345  RBASIC(obj)->klass = 0;
1346  return obj;
1347 }
1348 
1349 static VALUE
1351 {
1352  VALUE tmp;
1353  int fd;
1354  if (FIXNUM_P(v)) {
1355  fd = FIX2INT(v);
1356  }
1357  else if (SYMBOL_P(v)) {
1358  ID id = SYM2ID(v);
1359  if (id == rb_intern("in"))
1360  fd = 0;
1361  else if (id == rb_intern("out"))
1362  fd = 1;
1363  else if (id == rb_intern("err"))
1364  fd = 2;
1365  else
1366  goto wrong;
1367  }
1368  else if (!NIL_P(tmp = rb_check_convert_type(v, T_FILE, "IO", "to_io"))) {
1369  rb_io_t *fptr;
1370  GetOpenFile(tmp, fptr);
1371  if (fptr->tied_io_for_writing)
1372  rb_raise(rb_eArgError, "duplex IO redirection");
1373  fd = fptr->fd;
1374  }
1375  else {
1376  rb_raise(rb_eArgError, "wrong exec redirect");
1377  }
1378  if (fd < 0) {
1379  wrong:
1380  rb_raise(rb_eArgError, "negative file descriptor");
1381  }
1382 #ifdef _WIN32
1383  else if (fd >= 3 && iskey) {
1384  rb_raise(rb_eArgError, "wrong file descriptor (%d)", fd);
1385  }
1386 #endif
1387  return INT2FIX(fd);
1388 }
1389 
1390 static void
1392 {
1393  int index;
1394  VALUE ary, param;
1395  VALUE path, flags, perm;
1396  ID id;
1397 
1398  switch (TYPE(val)) {
1399  case T_SYMBOL:
1400  id = SYM2ID(val);
1401  if (id == rb_intern("close")) {
1402  index = EXEC_OPTION_CLOSE;
1403  param = Qnil;
1404  }
1405  else if (id == rb_intern("in")) {
1406  index = EXEC_OPTION_DUP2;
1407  param = INT2FIX(0);
1408  }
1409  else if (id == rb_intern("out")) {
1410  index = EXEC_OPTION_DUP2;
1411  param = INT2FIX(1);
1412  }
1413  else if (id == rb_intern("err")) {
1414  index = EXEC_OPTION_DUP2;
1415  param = INT2FIX(2);
1416  }
1417  else {
1418  rb_raise(rb_eArgError, "wrong exec redirect symbol: %s",
1419  rb_id2name(id));
1420  }
1421  break;
1422 
1423  case T_FILE:
1424  val = check_exec_redirect_fd(val, 0);
1425  /* fall through */
1426  case T_FIXNUM:
1427  index = EXEC_OPTION_DUP2;
1428  param = val;
1429  break;
1430 
1431  case T_ARRAY:
1432  path = rb_ary_entry(val, 0);
1433  if (RARRAY_LEN(val) == 2 && SYMBOL_P(path) &&
1434  SYM2ID(path) == rb_intern("child")) {
1435  index = EXEC_OPTION_DUP2_CHILD;
1436  param = check_exec_redirect_fd(rb_ary_entry(val, 1), 0);
1437  }
1438  else {
1439  index = EXEC_OPTION_OPEN;
1440  FilePathValue(path);
1441  flags = rb_ary_entry(val, 1);
1442  if (NIL_P(flags))
1443  flags = INT2NUM(O_RDONLY);
1444  else if (TYPE(flags) == T_STRING)
1445  flags = INT2NUM(rb_io_modestr_oflags(StringValueCStr(flags)));
1446  else
1447  flags = rb_to_int(flags);
1448  perm = rb_ary_entry(val, 2);
1449  perm = NIL_P(perm) ? INT2FIX(0644) : rb_to_int(perm);
1450  param = hide_obj(rb_ary_new3(3, hide_obj(rb_str_dup(path)),
1451  flags, perm));
1452  }
1453  break;
1454 
1455  case T_STRING:
1456  index = EXEC_OPTION_OPEN;
1457  path = val;
1458  FilePathValue(path);
1459  if (TYPE(key) == T_FILE)
1460  key = check_exec_redirect_fd(key, 1);
1461  if (FIXNUM_P(key) && (FIX2INT(key) == 1 || FIX2INT(key) == 2))
1462  flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
1463  else
1464  flags = INT2NUM(O_RDONLY);
1465  perm = INT2FIX(0644);
1466  param = hide_obj(rb_ary_new3(3, hide_obj(rb_str_dup(path)),
1467  flags, perm));
1468  break;
1469 
1470  default:
1471  rb_raise(rb_eArgError, "wrong exec redirect action");
1472  }
1473 
1474  ary = rb_ary_entry(options, index);
1475  if (NIL_P(ary)) {
1476  ary = hide_obj(rb_ary_new());
1477  rb_ary_store(options, index, ary);
1478  }
1479  if (TYPE(key) != T_ARRAY) {
1480  VALUE fd = check_exec_redirect_fd(key, !NIL_P(param));
1481  rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
1482  }
1483  else {
1484  int i, n=0;
1485  for (i = 0 ; i < RARRAY_LEN(key); i++) {
1486  VALUE v = RARRAY_PTR(key)[i];
1487  VALUE fd = check_exec_redirect_fd(v, !NIL_P(param));
1488  rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
1489  n++;
1490  }
1491  }
1492 }
1493 
1494 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1495 static int rlimit_type_by_lname(const char *name);
1496 #endif
1497 
1498 int
1500 {
1501  VALUE options = e->options;
1502  ID id;
1503 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1504  int rtype;
1505 #endif
1506 
1507  rb_secure(2);
1508 
1509  switch (TYPE(key)) {
1510  case T_SYMBOL:
1511  id = SYM2ID(key);
1512 #ifdef HAVE_SETPGID
1513  if (id == rb_intern("pgroup")) {
1514  if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_PGROUP))) {
1515  rb_raise(rb_eArgError, "pgroup option specified twice");
1516  }
1517  if (!RTEST(val))
1518  val = Qfalse;
1519  else if (val == Qtrue)
1520  val = INT2FIX(0);
1521  else {
1522  pid_t pgroup = NUM2PIDT(val);
1523  if (pgroup < 0) {
1524  rb_raise(rb_eArgError, "negative process group ID : %ld", (long)pgroup);
1525  }
1526  val = PIDT2NUM(pgroup);
1527  }
1528  rb_ary_store(options, EXEC_OPTION_PGROUP, val);
1529  }
1530  else
1531 #endif
1532 #ifdef _WIN32
1533  if (id == rb_intern("new_pgroup")) {
1534  if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_NEW_PGROUP))) {
1535  rb_raise(rb_eArgError, "new_pgroup option specified twice");
1536  }
1537  val = RTEST(val) ? Qtrue : Qfalse;
1538  rb_ary_store(options, EXEC_OPTION_NEW_PGROUP, val);
1539  }
1540  else
1541 #endif
1542 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1543  if (strncmp("rlimit_", rb_id2name(id), 7) == 0 &&
1544  (rtype = rlimit_type_by_lname(rb_id2name(id)+7)) != -1) {
1545  VALUE ary = rb_ary_entry(options, EXEC_OPTION_RLIMIT);
1546  VALUE tmp, softlim, hardlim;
1547  if (NIL_P(ary)) {
1548  ary = hide_obj(rb_ary_new());
1549  rb_ary_store(options, EXEC_OPTION_RLIMIT, ary);
1550  }
1551  tmp = rb_check_array_type(val);
1552  if (!NIL_P(tmp)) {
1553  if (RARRAY_LEN(tmp) == 1)
1554  softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0));
1555  else if (RARRAY_LEN(tmp) == 2) {
1556  softlim = rb_to_int(rb_ary_entry(tmp, 0));
1557  hardlim = rb_to_int(rb_ary_entry(tmp, 1));
1558  }
1559  else {
1560  rb_raise(rb_eArgError, "wrong exec rlimit option");
1561  }
1562  }
1563  else {
1564  softlim = hardlim = rb_to_int(val);
1565  }
1566  tmp = hide_obj(rb_ary_new3(3, INT2NUM(rtype), softlim, hardlim));
1567  rb_ary_push(ary, tmp);
1568  }
1569  else
1570 #endif
1571  if (id == rb_intern("unsetenv_others")) {
1573  rb_raise(rb_eArgError, "unsetenv_others option specified twice");
1574  }
1575  val = RTEST(val) ? Qtrue : Qfalse;
1577  }
1578  else if (id == rb_intern("chdir")) {
1579  if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_CHDIR))) {
1580  rb_raise(rb_eArgError, "chdir option specified twice");
1581  }
1582  FilePathValue(val);
1584  hide_obj(rb_str_dup(val)));
1585  }
1586  else if (id == rb_intern("umask")) {
1587  mode_t cmask = NUM2MODET(val);
1588  if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_UMASK))) {
1589  rb_raise(rb_eArgError, "umask option specified twice");
1590  }
1591  rb_ary_store(options, EXEC_OPTION_UMASK, LONG2NUM(cmask));
1592  }
1593  else if (id == rb_intern("close_others")) {
1594  if (!NIL_P(rb_ary_entry(options, EXEC_OPTION_CLOSE_OTHERS))) {
1595  rb_raise(rb_eArgError, "close_others option specified twice");
1596  }
1597  val = RTEST(val) ? Qtrue : Qfalse;
1598  rb_ary_store(options, EXEC_OPTION_CLOSE_OTHERS, val);
1599  }
1600  else if (id == rb_intern("in")) {
1601  key = INT2FIX(0);
1602  goto redirect;
1603  }
1604  else if (id == rb_intern("out")) {
1605  key = INT2FIX(1);
1606  goto redirect;
1607  }
1608  else if (id == rb_intern("err")) {
1609  key = INT2FIX(2);
1610  goto redirect;
1611  }
1612  else {
1613  rb_raise(rb_eArgError, "wrong exec option symbol: %s",
1614  rb_id2name(id));
1615  }
1616  break;
1617 
1618  case T_FIXNUM:
1619  case T_FILE:
1620  case T_ARRAY:
1621 redirect:
1622  check_exec_redirect(key, val, options);
1623  break;
1624 
1625  default:
1626  rb_raise(rb_eArgError, "wrong exec option");
1627  }
1628 
1629  return ST_CONTINUE;
1630 }
1631 
1632 static int
1634 {
1635  VALUE key = (VALUE)st_key;
1636  VALUE val = (VALUE)st_val;
1637  struct rb_exec_arg *e = (struct rb_exec_arg *)arg;
1638  return rb_exec_arg_addopt(e, key, val);
1639 }
1640 
1641 static VALUE
1643 {
1644  VALUE h = rb_hash_new();
1645  VALUE ary;
1646  int index, maxhint = -1;
1647  long i;
1648 
1649  for (index = EXEC_OPTION_DUP2; index <= EXEC_OPTION_DUP2_CHILD; index++) {
1650  ary = rb_ary_entry(options, index);
1651  if (NIL_P(ary))
1652  continue;
1653  for (i = 0; i < RARRAY_LEN(ary); i++) {
1654  VALUE elt = RARRAY_PTR(ary)[i];
1655  int fd = FIX2INT(RARRAY_PTR(elt)[0]);
1656  if (RTEST(rb_hash_lookup(h, INT2FIX(fd)))) {
1657  rb_raise(rb_eArgError, "fd %d specified twice", fd);
1658  }
1659  if (index == EXEC_OPTION_OPEN || index == EXEC_OPTION_DUP2)
1660  rb_hash_aset(h, INT2FIX(fd), Qtrue);
1661  else if (index == EXEC_OPTION_DUP2_CHILD)
1662  rb_hash_aset(h, INT2FIX(fd), RARRAY_PTR(elt)[1]);
1663  else /* index == EXEC_OPTION_CLOSE */
1664  rb_hash_aset(h, INT2FIX(fd), INT2FIX(-1));
1665  if (maxhint < fd)
1666  maxhint = fd;
1667  if (index == EXEC_OPTION_DUP2 || index == EXEC_OPTION_DUP2_CHILD) {
1668  fd = FIX2INT(RARRAY_PTR(elt)[1]);
1669  if (maxhint < fd)
1670  maxhint = fd;
1671  }
1672  }
1673  }
1674 
1675  ary = rb_ary_entry(options, EXEC_OPTION_DUP2_CHILD);
1676  if (!NIL_P(ary)) {
1677  for (i = 0; i < RARRAY_LEN(ary); i++) {
1678  VALUE elt = RARRAY_PTR(ary)[i];
1679  int newfd = FIX2INT(RARRAY_PTR(elt)[0]);
1680  int oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
1681  int lastfd = oldfd;
1682  VALUE val = rb_hash_lookup(h, INT2FIX(lastfd));
1683  long depth = 0;
1684  while (FIXNUM_P(val) && 0 <= FIX2INT(val)) {
1685  lastfd = FIX2INT(val);
1686  val = rb_hash_lookup(h, val);
1687  if (RARRAY_LEN(ary) < depth)
1688  rb_raise(rb_eArgError, "cyclic child fd redirection from %d", oldfd);
1689  depth++;
1690  }
1691  if (val != Qtrue)
1692  rb_raise(rb_eArgError, "child fd %d is not redirected", oldfd);
1693  if (oldfd != lastfd) {
1694  VALUE val2;
1695  rb_ary_store(elt, 1, INT2FIX(lastfd));
1696  rb_hash_aset(h, INT2FIX(newfd), INT2FIX(lastfd));
1697  val = INT2FIX(oldfd);
1698  while (FIXNUM_P(val2 = rb_hash_lookup(h, val))) {
1699  rb_hash_aset(h, val, INT2FIX(lastfd));
1700  val = val2;
1701  }
1702  }
1703  }
1704  }
1705 
1706  if (rb_ary_entry(options, EXEC_OPTION_CLOSE_OTHERS) != Qfalse) {
1707  rb_ary_store(options, EXEC_OPTION_CLOSE_OTHERS, INT2FIX(maxhint));
1708  }
1709  return h;
1710 }
1711 
1712 static void
1714 {
1715  if (RHASH_EMPTY_P(opthash))
1716  return;
1718 }
1719 
1720 static int
1722 {
1723  VALUE key = (VALUE)st_key;
1724  VALUE val = (VALUE)st_val;
1725  VALUE env = (VALUE)arg;
1726  char *k;
1727 
1728  k = StringValueCStr(key);
1729  if (strchr(k, '='))
1730  rb_raise(rb_eArgError, "environment name contains a equal : %s", k);
1731 
1732  if (!NIL_P(val))
1733  StringValueCStr(val);
1734 
1735  rb_ary_push(env, hide_obj(rb_assoc_new(key, val)));
1736 
1737  return ST_CONTINUE;
1738 }
1739 
1740 static VALUE
1742 {
1743  VALUE env;
1744 
1745  env = hide_obj(rb_ary_new());
1747 
1748  return env;
1749 }
1750 
1751 static VALUE
1752 rb_check_argv(int argc, VALUE *argv)
1753 {
1754  VALUE tmp, prog;
1755  int i;
1756  const char *name = 0;
1757 
1758  if (argc == 0) {
1759  rb_raise(rb_eArgError, "wrong number of arguments");
1760  }
1761 
1762  prog = 0;
1763  tmp = rb_check_array_type(argv[0]);
1764  if (!NIL_P(tmp)) {
1765  if (RARRAY_LEN(tmp) != 2) {
1766  rb_raise(rb_eArgError, "wrong first argument");
1767  }
1768  prog = RARRAY_PTR(tmp)[0];
1769  argv[0] = RARRAY_PTR(tmp)[1];
1770  SafeStringValue(prog);
1771  StringValueCStr(prog);
1772  prog = rb_str_new4(prog);
1773  name = RSTRING_PTR(prog);
1774  }
1775  for (i = 0; i < argc; i++) {
1776  SafeStringValue(argv[i]);
1777  argv[i] = rb_str_new4(argv[i]);
1778  StringValueCStr(argv[i]);
1779  }
1780  security(name ? name : RSTRING_PTR(argv[0]));
1781  return prog;
1782 }
1783 
1784 static VALUE
1785 rb_exec_getargs(int *argc_p, VALUE **argv_p, int accept_shell, VALUE *env_ret, VALUE *opthash_ret, struct rb_exec_arg *e)
1786 {
1787  VALUE hash, prog;
1788 
1789  if (0 < *argc_p) {
1790  hash = rb_check_convert_type((*argv_p)[*argc_p-1], T_HASH, "Hash", "to_hash");
1791  if (!NIL_P(hash)) {
1792  *opthash_ret = hash;
1793  (*argc_p)--;
1794  }
1795  }
1796 
1797  if (0 < *argc_p) {
1798  hash = rb_check_convert_type((*argv_p)[0], T_HASH, "Hash", "to_hash");
1799  if (!NIL_P(hash)) {
1800  *env_ret = hash;
1801  (*argc_p)--;
1802  (*argv_p)++;
1803  }
1804  }
1805  prog = rb_check_argv(*argc_p, *argv_p);
1806  if (!prog) {
1807  prog = (*argv_p)[0];
1808  if (accept_shell && *argc_p == 1) {
1809  *argc_p = 0;
1810  *argv_p = 0;
1811  }
1812  }
1813  return prog;
1814 }
1815 
1816 static void
1817 rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, struct rb_exec_arg *e)
1818 {
1819  VALUE options;
1820  MEMZERO(e, struct rb_exec_arg, 1);
1821  options = hide_obj(rb_ary_new());
1822  e->options = options;
1823 
1824  if (!NIL_P(opthash)) {
1825  rb_check_exec_options(opthash, e);
1826  }
1827  if (!NIL_P(env)) {
1828  env = rb_check_exec_env(env);
1829  rb_ary_store(options, EXEC_OPTION_ENV, env);
1830  }
1831 
1832  e->argc = argc;
1833  e->argv = argv;
1834  e->prog = prog ? RSTRING_PTR(prog) : 0;
1835 }
1836 
1837 VALUE
1838 rb_exec_arg_init(int argc, VALUE *argv, int accept_shell, struct rb_exec_arg *e)
1839 {
1840  VALUE prog;
1841  VALUE env = Qnil, opthash = Qnil;
1842  prog = rb_exec_getargs(&argc, &argv, accept_shell, &env, &opthash, e);
1843  rb_exec_fillarg(prog, argc, argv, env, opthash, e);
1844  return prog;
1845 }
1846 
1847 void
1849 {
1851 }
1852 
1853 /*
1854  * call-seq:
1855  * exec([env,] command... [,options])
1856  *
1857  * Replaces the current process by running the given external _command_.
1858  * _command..._ is one of following forms.
1859  *
1860  * commandline : command line string which is passed to the standard shell
1861  * cmdname, arg1, ... : command name and one or more arguments (no shell)
1862  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
1863  *
1864  * If single string is given as the command,
1865  * it is taken as a command line that is subject to shell expansion before being executed.
1866  *
1867  * The standard shell means always <code>"/bin/sh"</code> on Unix-like systems,
1868  * <code>ENV["RUBYSHELL"]</code> or <code>ENV["COMSPEC"]</code> on Windows NT series, and
1869  * similar.
1870  *
1871  * If two or more +string+ given,
1872  * the first is taken as a command name and
1873  * the rest are passed as parameters to command with no shell expansion.
1874  *
1875  * If a two-element array at the beginning of the command,
1876  * the first element is the command to be executed,
1877  * and the second argument is used as the <code>argv[0]</code> value,
1878  * which may show up in process listings.
1879  *
1880  * In order to execute the command, one of the <code>exec(2)</code>
1881  * system calls is used, so the running command may inherit some of the environment
1882  * of the original program (including open file descriptors).
1883  * This behavior is modified by env and options.
1884  * See <code>spawn</code> for details.
1885  *
1886  * Raises SystemCallError if the command couldn't execute (typically
1887  * <code>Errno::ENOENT</code> when it was not found).
1888  *
1889  * exec "echo *" # echoes list of files in current directory
1890  * # never get here
1891  *
1892  *
1893  * exec "echo", "*" # echoes an asterisk
1894  * # never get here
1895  */
1896 
1897 VALUE
1898 rb_f_exec(int argc, VALUE *argv)
1899 {
1900  struct rb_exec_arg earg;
1901 #define CHILD_ERRMSG_BUFLEN 80
1902  char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
1903 
1904  rb_exec_arg_init(argc, argv, TRUE, &earg);
1906  rb_exec_arg_addopt(&earg, ID2SYM(rb_intern("close_others")), Qfalse);
1907  rb_exec_arg_fixup(&earg);
1908 
1909  rb_exec_err(&earg, errmsg, sizeof(errmsg));
1910  if (errmsg[0])
1911  rb_sys_fail(errmsg);
1912  rb_sys_fail(earg.prog);
1913  return Qnil; /* dummy */
1914 }
1915 
1916 #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
1917 
1918 /*#define DEBUG_REDIRECT*/
1919 #if defined(DEBUG_REDIRECT)
1920 
1921 #include <stdarg.h>
1922 
1923 static void
1924 ttyprintf(const char *fmt, ...)
1925 {
1926  va_list ap;
1927  FILE *tty;
1928  int save = errno;
1929 #ifdef _WIN32
1930  tty = fopen("con", "w");
1931 #else
1932  tty = fopen("/dev/tty", "w");
1933 #endif
1934  if (!tty)
1935  return;
1936 
1937  va_start(ap, fmt);
1938  vfprintf(tty, fmt, ap);
1939  va_end(ap);
1940  fclose(tty);
1941  errno = save;
1942 }
1943 
1944 static int
1945 redirect_dup(int oldfd)
1946 {
1947  int ret;
1948  ret = dup(oldfd);
1949  ttyprintf("dup(%d) => %d\n", oldfd, ret);
1950  return ret;
1951 }
1952 
1953 static int
1954 redirect_dup2(int oldfd, int newfd)
1955 {
1956  int ret;
1957  ret = dup2(oldfd, newfd);
1958  ttyprintf("dup2(%d, %d)\n", oldfd, newfd);
1959  return ret;
1960 }
1961 
1962 static int
1963 redirect_close(int fd)
1964 {
1965  int ret;
1966  ret = close(fd);
1967  ttyprintf("close(%d)\n", fd);
1968  return ret;
1969 }
1970 
1971 static int
1972 redirect_open(const char *pathname, int flags, mode_t perm)
1973 {
1974  int ret;
1975  ret = open(pathname, flags, perm);
1976  ttyprintf("open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
1977  return ret;
1978 }
1979 
1980 #else
1981 #define redirect_dup(oldfd) dup(oldfd)
1982 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
1983 #define redirect_close(fd) close(fd)
1984 #define redirect_open(pathname, flags, perm) open((pathname), (flags), (perm))
1985 #endif
1986 
1987 static int
1988 save_redirect_fd(int fd, VALUE save, char *errmsg, size_t errmsg_buflen)
1989 {
1990  if (!NIL_P(save)) {
1991  VALUE newary;
1992  int save_fd = redirect_dup(fd);
1993  if (save_fd == -1) {
1994  if (errno == EBADF)
1995  return 0;
1996  ERRMSG("dup");
1997  return -1;
1998  }
1999  rb_update_max_fd(save_fd);
2000  newary = rb_ary_entry(save, EXEC_OPTION_DUP2);
2001  if (NIL_P(newary)) {
2002  newary = hide_obj(rb_ary_new());
2003  rb_ary_store(save, EXEC_OPTION_DUP2, newary);
2004  }
2005  rb_ary_push(newary,
2006  hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd))));
2007 
2008  newary = rb_ary_entry(save, EXEC_OPTION_CLOSE);
2009  if (NIL_P(newary)) {
2010  newary = hide_obj(rb_ary_new());
2011  rb_ary_store(save, EXEC_OPTION_CLOSE, newary);
2012  }
2013  rb_ary_push(newary, hide_obj(rb_assoc_new(INT2FIX(save_fd), Qnil)));
2014  }
2015 
2016  return 0;
2017 }
2018 
2019 static VALUE
2020 save_env_i(VALUE i, VALUE ary, int argc, VALUE *argv)
2021 {
2022  rb_ary_push(ary, hide_obj(rb_ary_dup(argv[0])));
2023  return Qnil;
2024 }
2025 
2026 static void
2028 {
2029  if (!NIL_P(save) && NIL_P(rb_ary_entry(save, EXEC_OPTION_ENV))) {
2031  if (RTEST(env)) {
2032  VALUE ary = hide_obj(rb_ary_new());
2033  rb_block_call(env, rb_intern("each"), 0, 0, save_env_i,
2034  (VALUE)ary);
2035  rb_ary_store(save, EXEC_OPTION_ENV, ary);
2036  }
2038  }
2039 }
2040 
2041 static int
2042 intcmp(const void *a, const void *b)
2043 {
2044  return *(int*)a - *(int*)b;
2045 }
2046 
2047 static int
2048 intrcmp(const void *a, const void *b)
2049 {
2050  return *(int*)b - *(int*)a;
2051 }
2052 
2053 static int
2054 run_exec_dup2(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
2055 {
2056  long n, i;
2057  int ret;
2058  int extra_fd = -1;
2059  struct fd_pair {
2060  int oldfd;
2061  int newfd;
2062  long older_index;
2063  long num_newer;
2064  } *pairs = 0;
2065 
2066  n = RARRAY_LEN(ary);
2067  pairs = (struct fd_pair *)malloc(sizeof(struct fd_pair) * n);
2068  if (pairs == NULL) {
2069  ERRMSG("malloc");
2070  return -1;
2071  }
2072 
2073  /* initialize oldfd and newfd: O(n) */
2074  for (i = 0; i < n; i++) {
2075  VALUE elt = RARRAY_PTR(ary)[i];
2076  pairs[i].oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
2077  pairs[i].newfd = FIX2INT(RARRAY_PTR(elt)[0]); /* unique */
2078  pairs[i].older_index = -1;
2079  }
2080 
2081  /* sort the table by oldfd: O(n log n) */
2082  if (!RTEST(save))
2083  qsort(pairs, n, sizeof(struct fd_pair), intcmp);
2084  else
2085  qsort(pairs, n, sizeof(struct fd_pair), intrcmp);
2086 
2087  /* initialize older_index and num_newer: O(n log n) */
2088  for (i = 0; i < n; i++) {
2089  int newfd = pairs[i].newfd;
2090  struct fd_pair key, *found;
2091  key.oldfd = newfd;
2092  found = bsearch(&key, pairs, n, sizeof(struct fd_pair), intcmp);
2093  pairs[i].num_newer = 0;
2094  if (found) {
2095  while (pairs < found && (found-1)->oldfd == newfd)
2096  found--;
2097  while (found < pairs+n && found->oldfd == newfd) {
2098  pairs[i].num_newer++;
2099  found->older_index = i;
2100  found++;
2101  }
2102  }
2103  }
2104 
2105  /* non-cyclic redirection: O(n) */
2106  for (i = 0; i < n; i++) {
2107  long j = i;
2108  while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
2109  if (save_redirect_fd(pairs[j].newfd, save, errmsg, errmsg_buflen) < 0)
2110  goto fail;
2111  ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
2112  if (ret == -1) {
2113  ERRMSG("dup2");
2114  goto fail;
2115  }
2116  rb_update_max_fd(pairs[j].newfd);
2117  pairs[j].oldfd = -1;
2118  j = pairs[j].older_index;
2119  if (j != -1)
2120  pairs[j].num_newer--;
2121  }
2122  }
2123 
2124  /* cyclic redirection: O(n) */
2125  for (i = 0; i < n; i++) {
2126  long j;
2127  if (pairs[i].oldfd == -1)
2128  continue;
2129  if (pairs[i].oldfd == pairs[i].newfd) { /* self cycle */
2130 #ifdef F_GETFD
2131  int fd = pairs[i].oldfd;
2132  ret = fcntl(fd, F_GETFD);
2133  if (ret == -1) {
2134  ERRMSG("fcntl(F_GETFD)");
2135  goto fail;
2136  }
2137  if (ret & FD_CLOEXEC) {
2138  ret &= ~FD_CLOEXEC;
2139  ret = fcntl(fd, F_SETFD, ret);
2140  if (ret == -1) {
2141  ERRMSG("fcntl(F_SETFD)");
2142  goto fail;
2143  }
2144  }
2145 #endif
2146  pairs[i].oldfd = -1;
2147  continue;
2148  }
2149  if (extra_fd == -1) {
2150  extra_fd = redirect_dup(pairs[i].oldfd);
2151  if (extra_fd == -1) {
2152  ERRMSG("dup");
2153  goto fail;
2154  }
2155  rb_update_max_fd(extra_fd);
2156  }
2157  else {
2158  ret = redirect_dup2(pairs[i].oldfd, extra_fd);
2159  if (ret == -1) {
2160  ERRMSG("dup2");
2161  goto fail;
2162  }
2163  rb_update_max_fd(extra_fd);
2164  }
2165  pairs[i].oldfd = extra_fd;
2166  j = pairs[i].older_index;
2167  pairs[i].older_index = -1;
2168  while (j != -1) {
2169  ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
2170  if (ret == -1) {
2171  ERRMSG("dup2");
2172  goto fail;
2173  }
2174  rb_update_max_fd(ret);
2175  pairs[j].oldfd = -1;
2176  j = pairs[j].older_index;
2177  }
2178  }
2179  if (extra_fd != -1) {
2180  ret = redirect_close(extra_fd);
2181  if (ret == -1) {
2182  ERRMSG("close");
2183  goto fail;
2184  }
2185  }
2186 
2187  xfree(pairs);
2188  return 0;
2189 
2190  fail:
2191  xfree(pairs);
2192  return -1;
2193 }
2194 
2195 static int
2196 run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
2197 {
2198  long i;
2199  int ret;
2200 
2201  for (i = 0; i < RARRAY_LEN(ary); i++) {
2202  VALUE elt = RARRAY_PTR(ary)[i];
2203  int fd = FIX2INT(RARRAY_PTR(elt)[0]);
2204  ret = redirect_close(fd);
2205  if (ret == -1) {
2206  ERRMSG("close");
2207  return -1;
2208  }
2209  }
2210  return 0;
2211 }
2212 
2213 static int
2214 run_exec_open(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
2215 {
2216  long i;
2217  int ret;
2218 
2219  for (i = 0; i < RARRAY_LEN(ary);) {
2220  VALUE elt = RARRAY_PTR(ary)[i];
2221  int fd = FIX2INT(RARRAY_PTR(elt)[0]);
2222  VALUE param = RARRAY_PTR(elt)[1];
2223  char *path = RSTRING_PTR(RARRAY_PTR(param)[0]);
2224  int flags = NUM2INT(RARRAY_PTR(param)[1]);
2225  int perm = NUM2INT(RARRAY_PTR(param)[2]);
2226  int need_close = 1;
2227  int fd2 = redirect_open(path, flags, perm);
2228  if (fd2 == -1) {
2229  ERRMSG("open");
2230  return -1;
2231  }
2232  rb_update_max_fd(fd2);
2233  while (i < RARRAY_LEN(ary) &&
2234  (elt = RARRAY_PTR(ary)[i], RARRAY_PTR(elt)[1] == param)) {
2235  fd = FIX2INT(RARRAY_PTR(elt)[0]);
2236  if (fd == fd2) {
2237  need_close = 0;
2238  }
2239  else {
2240  if (save_redirect_fd(fd, save, errmsg, errmsg_buflen) < 0)
2241  return -1;
2242  ret = redirect_dup2(fd2, fd);
2243  if (ret == -1) {
2244  ERRMSG("dup2");
2245  return -1;
2246  }
2247  rb_update_max_fd(fd);
2248  }
2249  i++;
2250  }
2251  if (need_close) {
2252  ret = redirect_close(fd2);
2253  if (ret == -1) {
2254  ERRMSG("close");
2255  return -1;
2256  }
2257  }
2258  }
2259  return 0;
2260 }
2261 
2262 static int
2263 run_exec_dup2_child(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
2264 {
2265  long i;
2266  int ret;
2267 
2268  for (i = 0; i < RARRAY_LEN(ary); i++) {
2269  VALUE elt = RARRAY_PTR(ary)[i];
2270  int newfd = FIX2INT(RARRAY_PTR(elt)[0]);
2271  int oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
2272 
2273  if (save_redirect_fd(newfd, save, errmsg, errmsg_buflen) < 0)
2274  return -1;
2275  ret = redirect_dup2(oldfd, newfd);
2276  if (ret == -1) {
2277  ERRMSG("dup2");
2278  return -1;
2279  }
2280  rb_update_max_fd(newfd);
2281  }
2282  return 0;
2283 }
2284 
2285 #ifdef HAVE_SETPGID
2286 static int
2287 run_exec_pgroup(VALUE obj, VALUE save, char *errmsg, size_t errmsg_buflen)
2288 {
2289  /*
2290  * If FD_CLOEXEC is available, rb_fork waits the child's execve.
2291  * So setpgid is done in the child when rb_fork is returned in the parent.
2292  * No race condition, even without setpgid from the parent.
2293  * (Is there an environment which has setpgid but FD_CLOEXEC?)
2294  */
2295  int ret;
2296  pid_t pgroup;
2297  if (!NIL_P(save)) {
2298  /* maybe meaningless with no fork environment... */
2299  rb_ary_store(save, EXEC_OPTION_PGROUP, PIDT2NUM(getpgrp()));
2300  }
2301  pgroup = NUM2PIDT(obj);
2302  if (pgroup == 0) {
2303  pgroup = getpid();
2304  }
2305  ret = setpgid(getpid(), pgroup);
2306  if (ret == -1) ERRMSG("setpgid");
2307  return ret;
2308 }
2309 #endif
2310 
2311 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2312 static int
2313 run_exec_rlimit(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
2314 {
2315  long i;
2316  for (i = 0; i < RARRAY_LEN(ary); i++) {
2317  VALUE elt = RARRAY_PTR(ary)[i];
2318  int rtype = NUM2INT(RARRAY_PTR(elt)[0]);
2319  struct rlimit rlim;
2320  if (!NIL_P(save)) {
2321  VALUE tmp, newary;
2322  if (getrlimit(rtype, &rlim) == -1) {
2323  ERRMSG("getrlimit");
2324  return -1;
2325  }
2326  tmp = hide_obj(rb_ary_new3(3, RARRAY_PTR(elt)[0],
2327  RLIM2NUM(rlim.rlim_cur),
2328  RLIM2NUM(rlim.rlim_max)));
2329  newary = rb_ary_entry(save, EXEC_OPTION_RLIMIT);
2330  if (NIL_P(newary)) {
2331  newary = hide_obj(rb_ary_new());
2332  rb_ary_store(save, EXEC_OPTION_RLIMIT, newary);
2333  }
2334  rb_ary_push(newary, tmp);
2335  }
2336  rlim.rlim_cur = NUM2RLIM(RARRAY_PTR(elt)[1]);
2337  rlim.rlim_max = NUM2RLIM(RARRAY_PTR(elt)[2]);
2338  if (setrlimit(rtype, &rlim) == -1) {
2339  ERRMSG("setrlimit");
2340  return -1;
2341  }
2342  }
2343  return 0;
2344 }
2345 #endif
2346 
2347 int
2348 rb_run_exec_options_err(const struct rb_exec_arg *e, struct rb_exec_arg *s, char *errmsg, size_t errmsg_buflen)
2349 {
2350  VALUE options = e->options;
2351  VALUE soptions = Qnil;
2352  VALUE obj;
2353 
2354  if (!RTEST(options))
2355  return 0;
2356 
2357  if (s) {
2358  s->argc = 0;
2359  s->argv = NULL;
2360  s->prog = NULL;
2361  s->options = soptions = hide_obj(rb_ary_new());
2362  s->redirect_fds = Qnil;
2363  }
2364 
2365 #ifdef HAVE_SETPGID
2366  obj = rb_ary_entry(options, EXEC_OPTION_PGROUP);
2367  if (RTEST(obj)) {
2368  if (run_exec_pgroup(obj, soptions, errmsg, errmsg_buflen) == -1)
2369  return -1;
2370  }
2371 #endif
2372 
2373 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2374  obj = rb_ary_entry(options, EXEC_OPTION_RLIMIT);
2375  if (!NIL_P(obj)) {
2376  if (run_exec_rlimit(obj, soptions, errmsg, errmsg_buflen) == -1)
2377  return -1;
2378  }
2379 #endif
2380 
2381  obj = rb_ary_entry(options, EXEC_OPTION_UNSETENV_OTHERS);
2382  if (RTEST(obj)) {
2383  save_env(soptions);
2384  rb_env_clear();
2385  }
2386 
2387  obj = rb_ary_entry(options, EXEC_OPTION_ENV);
2388  if (!NIL_P(obj)) {
2389  long i;
2390  save_env(soptions);
2391  for (i = 0; i < RARRAY_LEN(obj); i++) {
2392  VALUE pair = RARRAY_PTR(obj)[i];
2393  VALUE key = RARRAY_PTR(pair)[0];
2394  VALUE val = RARRAY_PTR(pair)[1];
2395  if (NIL_P(val))
2396  ruby_setenv(StringValueCStr(key), 0);
2397  else
2399  }
2400  }
2401 
2402  obj = rb_ary_entry(options, EXEC_OPTION_CHDIR);
2403  if (!NIL_P(obj)) {
2404  if (!NIL_P(soptions)) {
2405  char *cwd = my_getcwd();
2406  rb_ary_store(soptions, EXEC_OPTION_CHDIR,
2407  hide_obj(rb_str_new2(cwd)));
2408  xfree(cwd);
2409  }
2410  if (chdir(RSTRING_PTR(obj)) == -1) {
2411  ERRMSG("chdir");
2412  return -1;
2413  }
2414  }
2415 
2416  obj = rb_ary_entry(options, EXEC_OPTION_UMASK);
2417  if (!NIL_P(obj)) {
2418  mode_t mask = NUM2MODET(obj);
2419  mode_t oldmask = umask(mask); /* never fail */
2420  if (!NIL_P(soptions))
2421  rb_ary_store(soptions, EXEC_OPTION_UMASK, MODET2NUM(oldmask));
2422  }
2423 
2424  obj = rb_ary_entry(options, EXEC_OPTION_DUP2);
2425  if (!NIL_P(obj)) {
2426  if (run_exec_dup2(obj, soptions, errmsg, errmsg_buflen) == -1)
2427  return -1;
2428  }
2429 
2430  obj = rb_ary_entry(options, EXEC_OPTION_CLOSE);
2431  if (!NIL_P(obj)) {
2432  if (!NIL_P(soptions))
2433  rb_warn("cannot close fd before spawn");
2434  else {
2435  if (run_exec_close(obj, errmsg, errmsg_buflen) == -1)
2436  return -1;
2437  }
2438  }
2439 
2440 #ifdef HAVE_FORK
2441  obj = rb_ary_entry(options, EXEC_OPTION_CLOSE_OTHERS);
2442  if (obj != Qfalse) {
2444  }
2445 #endif
2446 
2447  obj = rb_ary_entry(options, EXEC_OPTION_OPEN);
2448  if (!NIL_P(obj)) {
2449  if (run_exec_open(obj, soptions, errmsg, errmsg_buflen) == -1)
2450  return -1;
2451  }
2452 
2453  obj = rb_ary_entry(options, EXEC_OPTION_DUP2_CHILD);
2454  if (!NIL_P(obj)) {
2455  if (run_exec_dup2_child(obj, soptions, errmsg, errmsg_buflen) == -1)
2456  return -1;
2457  }
2458 
2459  return 0;
2460 }
2461 
2462 int
2463 rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
2464 {
2465  return rb_run_exec_options_err(e, s, NULL, 0);
2466 }
2467 
2468 int
2469 rb_exec_err(const struct rb_exec_arg *e, char *errmsg, size_t errmsg_buflen)
2470 {
2471  int argc = e->argc;
2472  VALUE *argv = e->argv;
2473  const char *prog = e->prog;
2474 
2475  if (rb_run_exec_options_err(e, NULL, errmsg, errmsg_buflen) < 0) {
2476  return -1;
2477  }
2478 
2479  if (argc == 0) {
2480  rb_proc_exec(prog);
2481  }
2482  else {
2483  rb_proc_exec_n(argc, argv, prog);
2484  }
2485  return -1;
2486 }
2487 
2488 int
2489 rb_exec(const struct rb_exec_arg *e)
2490 {
2491 #if !defined FD_CLOEXEC && !defined HAVE_SPAWNV
2492  char errmsg[80] = { '\0' };
2493  int ret = rb_exec_err(e, errmsg, sizeof(errmsg));
2495  if (errmsg[0]) {
2496  fprintf(stderr, "%s\n", errmsg);
2497  }
2498  else {
2499  fprintf(stderr, "%s:%d: command not found: %s\n",
2500  rb_sourcefile(), rb_sourceline(), e->prog);
2501  }
2502  );
2503  return ret;
2504 #else
2505  return rb_exec_err(e, NULL, 0);
2506 #endif
2507 }
2508 
2509 #ifdef HAVE_FORK
2510 static int
2511 rb_exec_atfork(void* arg, char *errmsg, size_t errmsg_buflen)
2512 {
2514  return rb_exec_err(arg, errmsg, errmsg_buflen);
2515 }
2516 #endif
2517 
2518 #ifdef HAVE_FORK
2519 #ifdef FD_CLOEXEC
2520 #if SIZEOF_INT == SIZEOF_LONG
2521 #define proc_syswait (VALUE (*)(VALUE))rb_syswait
2522 #else
2523 static VALUE
2524 proc_syswait(VALUE pid)
2525 {
2526  rb_syswait((int)pid);
2527  return Qnil;
2528 }
2529 #endif
2530 #endif
2531 
2532 static int
2533 move_fds_to_avoid_crash(int *fdp, int n, VALUE fds)
2534 {
2535  long min = 0;
2536  int i;
2537  for (i = 0; i < n; i++) {
2538  int ret;
2539  while (RTEST(rb_hash_lookup(fds, INT2FIX(fdp[i])))) {
2540  if (min <= fdp[i])
2541  min = fdp[i]+1;
2542  while (RTEST(rb_hash_lookup(fds, INT2FIX(min))))
2543  min++;
2544  ret = fcntl(fdp[i], F_DUPFD, min);
2545  if (ret == -1)
2546  return -1;
2547  rb_update_max_fd(ret);
2548  close(fdp[i]);
2549  fdp[i] = ret;
2550  }
2551  }
2552  return 0;
2553 }
2554 
2555 static int
2556 pipe_nocrash(int filedes[2], VALUE fds)
2557 {
2558  int ret;
2559  ret = rb_pipe(filedes);
2560  if (ret == -1)
2561  return -1;
2562  if (RTEST(fds)) {
2563  int save = errno;
2564  if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
2565  close(filedes[0]);
2566  close(filedes[1]);
2567  return -1;
2568  }
2569  errno = save;
2570  }
2571  return ret;
2572 }
2573 
2574 struct chfunc_protect_t {
2575  int (*chfunc)(void*, char *, size_t);
2576  void *arg;
2577  char *errmsg;
2578  size_t buflen;
2579 };
2580 
2581 static VALUE
2582 chfunc_protect(VALUE arg)
2583 {
2584  struct chfunc_protect_t *p = (struct chfunc_protect_t *)arg;
2585 
2586  return (VALUE)(*p->chfunc)(p->arg, p->errmsg, p->buflen);
2587 }
2588 
2589 #ifndef O_BINARY
2590 #define O_BINARY 0
2591 #endif
2592 
2593 /*
2594  * Forks child process, and returns the process ID in the parent
2595  * process.
2596  *
2597  * If +status+ is given, protects from any exceptions and sets the
2598  * jump status to it.
2599  *
2600  * In the child process, just returns 0 if +chfunc+ is +NULL+.
2601  * Otherwise +chfunc+ will be called with +charg+, and then the child
2602  * process exits with +EXIT_SUCCESS+ when it returned zero.
2603  *
2604  * In the case of the function is called and returns non-zero value,
2605  * the child process exits with non-+EXIT_SUCCESS+ value (normally
2606  * 127). And, on the platforms where +FD_CLOEXEC+ is available,
2607  * +errno+ is propagated to the parent process, and this function
2608  * returns -1 in the parent process. On the other platforms, just
2609  * returns pid.
2610  *
2611  * If fds is not Qnil, internal pipe for the errno propagation is
2612  * arranged to avoid conflicts of the hash keys in +fds+.
2613  *
2614  * +chfunc+ must not raise any exceptions.
2615  */
2616 rb_pid_t
2617 rb_fork_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds,
2618  char *errmsg, size_t errmsg_buflen)
2619 {
2620  rb_pid_t pid;
2621  int err, state = 0;
2622 #ifdef FD_CLOEXEC
2623  int ep[2];
2624  VALUE io = Qnil;
2625 #endif
2626 
2627 #define prefork() ( \
2628  rb_io_flush(rb_stdout), \
2629  rb_io_flush(rb_stderr) \
2630  )
2631  prefork();
2632 
2633 #ifdef FD_CLOEXEC
2634  if (chfunc) {
2635  if (pipe_nocrash(ep, fds)) return -1;
2636  if (fcntl(ep[1], F_SETFD, FD_CLOEXEC)) {
2637  preserving_errno((close(ep[0]), close(ep[1])));
2638  return -1;
2639  }
2640  }
2641 #endif
2642  for (; before_fork(), (pid = fork()) < 0; prefork()) {
2643  after_fork();
2644  switch (errno) {
2645  case EAGAIN:
2646 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
2647  case EWOULDBLOCK:
2648 #endif
2649  if (!status && !chfunc) {
2650  rb_thread_sleep(1);
2651  continue;
2652  }
2653  else {
2654  rb_protect((VALUE (*)())rb_thread_sleep, 1, &state);
2655  if (status) *status = state;
2656  if (!state) continue;
2657  }
2658  default:
2659 #ifdef FD_CLOEXEC
2660  if (chfunc) {
2661  preserving_errno((close(ep[0]), close(ep[1])));
2662  }
2663 #endif
2664  if (state && !status) rb_jump_tag(state);
2665  return -1;
2666  }
2667  }
2668  if (!pid) {
2669  forked_child = 1;
2670  if (chfunc) {
2671  struct chfunc_protect_t arg;
2672  arg.chfunc = chfunc;
2673  arg.arg = charg;
2674  arg.errmsg = errmsg;
2675  arg.buflen = errmsg_buflen;
2676 #ifdef FD_CLOEXEC
2677  close(ep[0]);
2678 #endif
2679  if (!(int)rb_protect(chfunc_protect, (VALUE)&arg, &state)) _exit(EXIT_SUCCESS);
2680 #ifdef FD_CLOEXEC
2681  if (write(ep[1], &state, sizeof(state)) == sizeof(state) && state) {
2682  VALUE errinfo = rb_errinfo();
2683  io = rb_io_fdopen(ep[1], O_WRONLY|O_BINARY, NULL);
2684  rb_marshal_dump(errinfo, io);
2685  rb_io_flush(io);
2686  }
2687  err = errno;
2688  if (write(ep[1], &err, sizeof(err)) < 0) err = errno;
2689  if (errmsg && 0 < errmsg_buflen) {
2690  errmsg[errmsg_buflen-1] = '\0';
2691  errmsg_buflen = strlen(errmsg);
2692  if (errmsg_buflen > 0 &&write(ep[1], errmsg, errmsg_buflen) < 0)
2693  err = errno;
2694  }
2695  if (!NIL_P(io)) rb_io_close(io);
2696 #endif
2697 #if EXIT_SUCCESS == 127
2698  _exit(EXIT_FAILURE);
2699 #else
2700  _exit(127);
2701 #endif
2702  }
2703  }
2704  after_fork();
2705 #ifdef FD_CLOEXEC
2706  if (pid && chfunc) {
2707  ssize_t size;
2708  VALUE exc = Qnil;
2709  close(ep[1]);
2710  if ((read(ep[0], &state, sizeof(state))) == sizeof(state) && state) {
2711  io = rb_io_fdopen(ep[0], O_RDONLY|O_BINARY, NULL);
2712  exc = rb_marshal_load(io);
2713  rb_set_errinfo(exc);
2714  }
2715 #define READ_FROM_CHILD(ptr, len) \
2716  (NIL_P(io) ? read(ep[0], (ptr), (len)) : rb_io_bufread(io, (ptr), (len)))
2717  if ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) {
2718  err = errno;
2719  }
2720  if (size == sizeof(err) &&
2721  errmsg && 0 < errmsg_buflen) {
2722  ssize_t ret = READ_FROM_CHILD(errmsg, errmsg_buflen-1);
2723  if (0 <= ret) {
2724  errmsg[ret] = '\0';
2725  }
2726  }
2727  if (NIL_P(io))
2728  close(ep[0]);
2729  else
2730  rb_io_close(io);
2731  if (state || size) {
2732  if (status) {
2733  *status = state;
2734  rb_protect(proc_syswait, (VALUE)pid, status);
2735  }
2736  else {
2737  rb_syswait(pid);
2738  if (state) rb_exc_raise(exc);
2739  }
2740  errno = err;
2741  return -1;
2742  }
2743  }
2744 #endif
2745  return pid;
2746 }
2747 
2748 struct chfunc_wrapper_t {
2749  int (*chfunc)(void*);
2750  void *arg;
2751 };
2752 
2753 static int
2754 chfunc_wrapper(void *arg_, char *errmsg, size_t errmsg_buflen)
2755 {
2756  struct chfunc_wrapper_t *arg = arg_;
2757  return arg->chfunc(arg->arg);
2758 }
2759 
2760 rb_pid_t
2761 rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds)
2762 {
2763  if (chfunc) {
2764  struct chfunc_wrapper_t warg;
2765  warg.chfunc = chfunc;
2766  warg.arg = charg;
2767  return rb_fork_err(status, chfunc_wrapper, &warg, fds, NULL, 0);
2768  }
2769  else {
2770  return rb_fork_err(status, NULL, NULL, fds, NULL, 0);
2771  }
2772 
2773 }
2774 
2775 #endif
2776 
2777 #if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
2778 /*
2779  * call-seq:
2780  * Kernel.fork [{ block }] -> fixnum or nil
2781  * Process.fork [{ block }] -> fixnum or nil
2782  *
2783  * Creates a subprocess. If a block is specified, that block is run
2784  * in the subprocess, and the subprocess terminates with a status of
2785  * zero. Otherwise, the +fork+ call returns twice, once in
2786  * the parent, returning the process ID of the child, and once in
2787  * the child, returning _nil_. The child process can exit using
2788  * <code>Kernel.exit!</code> to avoid running any
2789  * <code>at_exit</code> functions. The parent process should
2790  * use <code>Process.wait</code> to collect the termination statuses
2791  * of its children or use <code>Process.detach</code> to register
2792  * disinterest in their status; otherwise, the operating system
2793  * may accumulate zombie processes.
2794  *
2795  * The thread calling fork is the only thread in the created child process.
2796  * fork doesn't copy other threads.
2797  *
2798  * If fork is not usable, Process.respond_to?(:fork) returns false.
2799  */
2800 
2801 static VALUE
2802 rb_f_fork(VALUE obj)
2803 {
2804  rb_pid_t pid;
2805 
2806  rb_secure(2);
2807 
2808  switch (pid = rb_fork(0, 0, 0, Qnil)) {
2809  case 0:
2810  rb_thread_atfork();
2811  if (rb_block_given_p()) {
2812  int status;
2813 
2814  rb_protect(rb_yield, Qundef, &status);
2815  ruby_stop(status);
2816  }
2817  return Qnil;
2818 
2819  case -1:
2820  rb_sys_fail("fork(2)");
2821  return Qnil;
2822 
2823  default:
2824  return PIDT2NUM(pid);
2825  }
2826 }
2827 #else
2828 #define rb_f_fork rb_f_notimplement
2829 #endif
2830 
2831 /*
2832  * call-seq:
2833  * Process.exit!(status=false)
2834  *
2835  * Exits the process immediately. No exit handlers are
2836  * run. <em>status</em> is returned to the underlying system as the
2837  * exit status.
2838  *
2839  * Process.exit!(true)
2840  */
2841 
2842 static VALUE
2843 rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
2844 {
2845  VALUE status;
2846  int istatus;
2847 
2848  rb_secure(4);
2849  if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
2850  switch (status) {
2851  case Qtrue:
2852  istatus = EXIT_SUCCESS;
2853  break;
2854  case Qfalse:
2855  istatus = EXIT_FAILURE;
2856  break;
2857  default:
2858  istatus = NUM2INT(status);
2859  break;
2860  }
2861  }
2862  else {
2863  istatus = EXIT_FAILURE;
2864  }
2865  _exit(istatus);
2866 
2867  return Qnil; /* not reached */
2868 }
2869 
2870 void
2871 rb_exit(int status)
2872 {
2873  if (GET_THREAD()->tag) {
2874  VALUE args[2];
2875 
2876  args[0] = INT2NUM(status);
2877  args[1] = rb_str_new2("exit");
2879  }
2880  ruby_finalize();
2881  exit(status);
2882 }
2883 
2884 
2885 /*
2886  * call-seq:
2887  * exit(status=true)
2888  * Kernel::exit(status=true)
2889  * Process::exit(status=true)
2890  *
2891  * Initiates the termination of the Ruby script by raising the
2892  * <code>SystemExit</code> exception. This exception may be caught. The
2893  * optional parameter is used to return a status code to the invoking
2894  * environment.
2895  * +true+ and +FALSE+ of _status_ means success and failure
2896  * respectively. The interpretation of other integer values are
2897  * system dependent.
2898  *
2899  * begin
2900  * exit
2901  * puts "never get here"
2902  * rescue SystemExit
2903  * puts "rescued a SystemExit exception"
2904  * end
2905  * puts "after begin block"
2906  *
2907  * <em>produces:</em>
2908  *
2909  * rescued a SystemExit exception
2910  * after begin block
2911  *
2912  * Just prior to termination, Ruby executes any <code>at_exit</code> functions
2913  * (see Kernel::at_exit) and runs any object finalizers (see
2914  * ObjectSpace::define_finalizer).
2915  *
2916  * at_exit { puts "at_exit function" }
2917  * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
2918  * exit
2919  *
2920  * <em>produces:</em>
2921  *
2922  * at_exit function
2923  * in finalizer
2924  */
2925 
2926 VALUE
2927 rb_f_exit(int argc, VALUE *argv)
2928 {
2929  VALUE status;
2930  int istatus;
2931 
2932  rb_secure(4);
2933  if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
2934  switch (status) {
2935  case Qtrue:
2936  istatus = EXIT_SUCCESS;
2937  break;
2938  case Qfalse:
2939  istatus = EXIT_FAILURE;
2940  break;
2941  default:
2942  istatus = NUM2INT(status);
2943 #if EXIT_SUCCESS != 0
2944  if (istatus == 0)
2945  istatus = EXIT_SUCCESS;
2946 #endif
2947  break;
2948  }
2949  }
2950  else {
2951  istatus = EXIT_SUCCESS;
2952  }
2953  rb_exit(istatus);
2954  return Qnil; /* not reached */
2955 }
2956 
2957 
2958 /*
2959  * call-seq:
2960  * abort
2961  * Kernel::abort([msg])
2962  * Process::abort([msg])
2963  *
2964  * Terminate execution immediately, effectively by calling
2965  * <code>Kernel.exit(false)</code>. If _msg_ is given, it is written
2966  * to STDERR prior to terminating.
2967  */
2968 
2969 VALUE
2970 rb_f_abort(int argc, VALUE *argv)
2971 {
2972  rb_secure(4);
2973  if (argc == 0) {
2974  if (!NIL_P(GET_THREAD()->errinfo)) {
2975  ruby_error_print();
2976  }
2978  }
2979  else {
2980  VALUE args[2];
2981 
2982  rb_scan_args(argc, argv, "1", &args[1]);
2983  StringValue(argv[0]);
2984  rb_io_puts(argc, argv, rb_stderr);
2985  args[0] = INT2NUM(EXIT_FAILURE);
2987  }
2988  return Qnil; /* not reached */
2989 }
2990 
2991 void
2992 rb_syswait(rb_pid_t pid)
2993 {
2994  static int overriding;
2995 #ifdef SIGHUP
2996  RETSIGTYPE (*hfunc)(int) = 0;
2997 #endif
2998 #ifdef SIGQUIT
2999  RETSIGTYPE (*qfunc)(int) = 0;
3000 #endif
3001  RETSIGTYPE (*ifunc)(int) = 0;
3002  int status;
3003  int i, hooked = FALSE;
3004 
3005  if (!overriding) {
3006 #ifdef SIGHUP
3007  hfunc = signal(SIGHUP, SIG_IGN);
3008 #endif
3009 #ifdef SIGQUIT
3010  qfunc = signal(SIGQUIT, SIG_IGN);
3011 #endif
3012  ifunc = signal(SIGINT, SIG_IGN);
3013  overriding = TRUE;
3014  hooked = TRUE;
3015  }
3016 
3017  do {
3018  i = rb_waitpid(pid, &status, 0);
3019  } while (i == -1 && errno == EINTR);
3020 
3021  if (hooked) {
3022 #ifdef SIGHUP
3023  signal(SIGHUP, hfunc);
3024 #endif
3025 #ifdef SIGQUIT
3026  signal(SIGQUIT, qfunc);
3027 #endif
3028  signal(SIGINT, ifunc);
3029  overriding = FALSE;
3030  }
3031 }
3032 
3033 static VALUE
3034 rb_exec_arg_prepare(struct rb_exec_arg *earg, int argc, VALUE *argv, int default_close_others)
3035 {
3036  VALUE prog = rb_exec_arg_init(argc, argv, TRUE, earg);
3038  VALUE v = default_close_others ? Qtrue : Qfalse;
3039  rb_exec_arg_addopt(earg, ID2SYM(rb_intern("close_others")), v);
3040  }
3041  rb_exec_arg_fixup(earg);
3042  return prog;
3043 }
3044 
3045 static rb_pid_t
3046 rb_spawn_process(struct rb_exec_arg *earg, VALUE prog, char *errmsg, size_t errmsg_buflen)
3047 {
3048  rb_pid_t pid;
3049 #if !USE_SPAWNV
3050  int status;
3051 #endif
3052 #if !defined HAVE_FORK || USE_SPAWNV
3053  struct rb_exec_arg sarg;
3054  int argc;
3055  VALUE *argv;
3056 #endif
3057 
3058 #if defined HAVE_FORK && !USE_SPAWNV
3059  pid = rb_fork_err(&status, rb_exec_atfork, earg, earg->redirect_fds, errmsg, errmsg_buflen);
3060 #else
3061  if (rb_run_exec_options_err(earg, &sarg, errmsg, errmsg_buflen) < 0) {
3062  return -1;
3063  }
3064 
3065  argc = earg->argc;
3066  argv = earg->argv;
3067  if (prog && argc) argv[0] = prog;
3068 # if defined HAVE_SPAWNV
3069  if (!argc) {
3070  pid = proc_spawn(RSTRING_PTR(prog));
3071  }
3072  else {
3073  pid = proc_spawn_n(argc, argv, prog, earg->options);
3074  }
3075 # if defined(_WIN32)
3076  if (pid == -1)
3077  rb_last_status_set(0x7f << 8, 0);
3078 # endif
3079 # else
3080  if (argc) prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
3081  status = system(StringValuePtr(prog));
3082  rb_last_status_set((status & 0xff) << 8, 0);
3083 # endif
3084 
3085  rb_run_exec_options_err(&sarg, NULL, errmsg, errmsg_buflen);
3086 #endif
3087  return pid;
3088 }
3089 
3090 static rb_pid_t
3091 rb_spawn_internal(int argc, VALUE *argv, int default_close_others,
3092  char *errmsg, size_t errmsg_buflen)
3093 {
3094  struct rb_exec_arg earg;
3095  VALUE prog = rb_exec_arg_prepare(&earg, argc, argv, default_close_others);
3096  return rb_spawn_process(&earg, prog, errmsg, errmsg_buflen);
3097 }
3098 
3099 rb_pid_t
3100 rb_spawn_err(int argc, VALUE *argv, char *errmsg, size_t errmsg_buflen)
3101 {
3102  return rb_spawn_internal(argc, argv, TRUE, errmsg, errmsg_buflen);
3103 }
3104 
3105 rb_pid_t
3106 rb_spawn(int argc, VALUE *argv)
3107 {
3108  return rb_spawn_internal(argc, argv, TRUE, NULL, 0);
3109 }
3110 
3111 /*
3112  * call-seq:
3113  * system([env,] command... [,options]) -> true, false or nil
3114  *
3115  * Executes _command..._ in a subshell.
3116  * _command..._ is one of following forms.
3117  *
3118  * commandline : command line string which is passed to the standard shell
3119  * cmdname, arg1, ... : command name and one or more arguments (no shell)
3120  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
3121  *
3122  * system returns +true+ if the command gives zero exit status,
3123  * +false+ for non zero exit status.
3124  * Returns +nil+ if command execution fails.
3125  * An error status is available in <code>$?</code>.
3126  * The arguments are processed in the same way as
3127  * for <code>Kernel.spawn</code>.
3128  *
3129  * The hash arguments, env and options, are same as
3130  * <code>exec</code> and <code>spawn</code>.
3131  * See <code>Kernel.spawn</code> for details.
3132  *
3133  * system("echo *")
3134  * system("echo", "*")
3135  *
3136  * <em>produces:</em>
3137  *
3138  * config.h main.rb
3139  * *
3140  *
3141  * See <code>Kernel.exec</code> for the standard shell.
3142  */
3143 
3144 static VALUE
3145 rb_f_system(int argc, VALUE *argv)
3146 {
3147  rb_pid_t pid;
3148  int status;
3149 
3150 #if defined(SIGCLD) && !defined(SIGCHLD)
3151 # define SIGCHLD SIGCLD
3152 #endif
3153 
3154 #ifdef SIGCHLD
3155  RETSIGTYPE (*chfunc)(int);
3156 
3157  chfunc = signal(SIGCHLD, SIG_DFL);
3158 #endif
3159  pid = rb_spawn_internal(argc, argv, FALSE, NULL, 0);
3160 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3161  if (pid > 0) {
3162  rb_syswait(pid);
3163  }
3164 #endif
3165 #ifdef SIGCHLD
3166  signal(SIGCHLD, chfunc);
3167 #endif
3168  if (pid < 0) {
3169  return Qnil;
3170  }
3171  status = PST2INT(rb_last_status_get());
3172  if (status == EXIT_SUCCESS) return Qtrue;
3173  return Qfalse;
3174 }
3175 
3176 /*
3177  * call-seq:
3178  * spawn([env,] command... [,options]) -> pid
3179  * Process.spawn([env,] command... [,options]) -> pid
3180  *
3181  * spawn executes specified command and return its pid.
3182  *
3183  * This method doesn't wait for end of the command.
3184  * The parent process should
3185  * use <code>Process.wait</code> to collect
3186  * the termination status of its child or
3187  * use <code>Process.detach</code> to register
3188  * disinterest in their status;
3189  * otherwise, the operating system may accumulate zombie processes.
3190  *
3191  * spawn has bunch of options to specify process attributes:
3192  *
3193  * env: hash
3194  * name => val : set the environment variable
3195  * name => nil : unset the environment variable
3196  * command...:
3197  * commandline : command line string which is passed to the standard shell
3198  * cmdname, arg1, ... : command name and one or more arguments (no shell)
3199  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
3200  * options: hash
3201  * clearing environment variables:
3202  * :unsetenv_others => true : clear environment variables except specified by env
3203  * :unsetenv_others => false : don't clear (default)
3204  * process group:
3205  * :pgroup => true or 0 : make a new process group
3206  * :pgroup => pgid : join to specified process group
3207  * :pgroup => nil : don't change the process group (default)
3208  * create new process group: Windows only
3209  * :new_pgroup => true : the new process is the root process of a new process group
3210  * :new_pgroup => false : don't create a new process group (default)
3211  * resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
3212  * :rlimit_resourcename => limit
3213  * :rlimit_resourcename => [cur_limit, max_limit]
3214  * current directory:
3215  * :chdir => str
3216  * umask:
3217  * :umask => int
3218  * redirection:
3219  * key:
3220  * FD : single file descriptor in child process
3221  * [FD, FD, ...] : multiple file descriptor in child process
3222  * value:
3223  * FD : redirect to the file descriptor in parent process
3224  * string : redirect to file with open(string, "r" or "w")
3225  * [string] : redirect to file with open(string, File::RDONLY)
3226  * [string, open_mode] : redirect to file with open(string, open_mode, 0644)
3227  * [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
3228  * [:child, FD] : redirect to the redirected file descriptor
3229  * :close : close the file descriptor in child process
3230  * FD is one of follows
3231  * :in : the file descriptor 0 which is the standard input
3232  * :out : the file descriptor 1 which is the standard output
3233  * :err : the file descriptor 2 which is the standard error
3234  * integer : the file descriptor of specified the integer
3235  * io : the file descriptor specified as io.fileno
3236  * file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
3237  * :close_others => false : inherit fds (default for system and exec)
3238  * :close_others => true : don't inherit (default for spawn and IO.popen)
3239  *
3240  * If a hash is given as +env+, the environment is
3241  * updated by +env+ before <code>exec(2)</code> in the child process.
3242  * If a pair in +env+ has nil as the value, the variable is deleted.
3243  *
3244  * # set FOO as BAR and unset BAZ.
3245  * pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
3246  *
3247  * If a hash is given as +options+,
3248  * it specifies
3249  * process group,
3250  * create new process group,
3251  * resource limit,
3252  * current directory,
3253  * umask and
3254  * redirects for the child process.
3255  * Also, it can be specified to clear environment variables.
3256  *
3257  * The <code>:unsetenv_others</code> key in +options+ specifies
3258  * to clear environment variables, other than specified by +env+.
3259  *
3260  * pid = spawn(command, :unsetenv_others=>true) # no environment variable
3261  * pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
3262  *
3263  * The <code>:pgroup</code> key in +options+ specifies a process group.
3264  * The corresponding value should be true, zero or positive integer.
3265  * true and zero means the process should be a process leader of a new
3266  * process group.
3267  * Other values specifies a process group to be belongs.
3268  *
3269  * pid = spawn(command, :pgroup=>true) # process leader
3270  * pid = spawn(command, :pgroup=>10) # belongs to the process group 10
3271  *
3272  * The <code>:new_pgroup</code> key in +options+ specifies to pass
3273  * +CREATE_NEW_PROCESS_GROUP+ flag to <code>CreateProcessW()</code> that is
3274  * Windows API. This option is only for Windows.
3275  * true means the new process is the root process of the new process group.
3276  * The new process has CTRL+C disabled. This flag is necessary for
3277  * <code>Process.kill(:SIGINT, pid)</code> on the subprocess.
3278  * :new_pgroup is false by default.
3279  *
3280  * pid = spawn(command, :new_pgroup=>true) # new process group
3281  * pid = spawn(command, :new_pgroup=>false) # same process group
3282  *
3283  * The <code>:rlimit_</code><em>foo</em> key specifies a resource limit.
3284  * <em>foo</em> should be one of resource types such as <code>core</code>.
3285  * The corresponding value should be an integer or an array which have one or
3286  * two integers: same as cur_limit and max_limit arguments for
3287  * Process.setrlimit.
3288  *
3289  * cur, max = Process.getrlimit(:CORE)
3290  * pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
3291  * pid = spawn(command, :rlimit_core=>max) # enable core dump
3292  * pid = spawn(command, :rlimit_core=>0) # never dump core.
3293  *
3294  * The <code>:chdir</code> key in +options+ specifies the current directory.
3295  *
3296  * pid = spawn(command, :chdir=>"/var/tmp")
3297  *
3298  * The <code>:umask</code> key in +options+ specifies the umask.
3299  *
3300  * pid = spawn(command, :umask=>077)
3301  *
3302  * The :in, :out, :err, a fixnum, an IO and an array key specifies a redirection.
3303  * The redirection maps a file descriptor in the child process.
3304  *
3305  * For example, stderr can be merged into stdout as follows:
3306  *
3307  * pid = spawn(command, :err=>:out)
3308  * pid = spawn(command, 2=>1)
3309  * pid = spawn(command, STDERR=>:out)
3310  * pid = spawn(command, STDERR=>STDOUT)
3311  *
3312  * The hash keys specifies a file descriptor
3313  * in the child process started by <code>spawn</code>.
3314  * :err, 2 and STDERR specifies the standard error stream (stderr).
3315  *
3316  * The hash values specifies a file descriptor
3317  * in the parent process which invokes <code>spawn</code>.
3318  * :out, 1 and STDOUT specifies the standard output stream (stdout).
3319  *
3320  * In the above example,
3321  * the standard output in the child process is not specified.
3322  * So it is inherited from the parent process.
3323  *
3324  * The standard input stream (stdin) can be specified by :in, 0 and STDIN.
3325  *
3326  * A filename can be specified as a hash value.
3327  *
3328  * pid = spawn(command, :in=>"/dev/null") # read mode
3329  * pid = spawn(command, :out=>"/dev/null") # write mode
3330  * pid = spawn(command, :err=>"log") # write mode
3331  * pid = spawn(command, 3=>"/dev/null") # read mode
3332  *
3333  * For stdout and stderr,
3334  * it is opened in write mode.
3335  * Otherwise read mode is used.
3336  *
3337  * For specifying flags and permission of file creation explicitly,
3338  * an array is used instead.
3339  *
3340  * pid = spawn(command, :in=>["file"]) # read mode is assumed
3341  * pid = spawn(command, :in=>["file", "r"])
3342  * pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
3343  * pid = spawn(command, :out=>["log", "w", 0600])
3344  * pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
3345  *
3346  * The array specifies a filename, flags and permission.
3347  * The flags can be a string or an integer.
3348  * If the flags is omitted or nil, File::RDONLY is assumed.
3349  * The permission should be an integer.
3350  * If the permission is omitted or nil, 0644 is assumed.
3351  *
3352  * If an array of IOs and integers are specified as a hash key,
3353  * all the elements are redirected.
3354  *
3355  * # stdout and stderr is redirected to log file.
3356  * # The file "log" is opened just once.
3357  * pid = spawn(command, [:out, :err]=>["log", "w"])
3358  *
3359  * Another way to merge multiple file descriptors is [:child, fd].
3360  * \[:child, fd] means the file descriptor in the child process.
3361  * This is different from fd.
3362  * For example, :err=>:out means redirecting child stderr to parent stdout.
3363  * But :err=>[:child, :out] means redirecting child stderr to child stdout.
3364  * They differs if stdout is redirected in the child process as follows.
3365  *
3366  * # stdout and stderr is redirected to log file.
3367  * # The file "log" is opened just once.
3368  * pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
3369  *
3370  * \[:child, :out] can be used to merge stderr into stdout in IO.popen.
3371  * In this case, IO.popen redirects stdout to a pipe in the child process
3372  * and [:child, :out] refers the redirected stdout.
3373  *
3374  * io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
3375  * p io.read #=> "out\nerr\n"
3376  *
3377  * spawn closes all non-standard unspecified descriptors by default.
3378  * The "standard" descriptors are 0, 1 and 2.
3379  * This behavior is specified by :close_others option.
3380  * :close_others doesn't affect the standard descriptors which are
3381  * closed only if :close is specified explicitly.
3382  *
3383  * pid = spawn(command, :close_others=>true) # close 3,4,5,... (default)
3384  * pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
3385  *
3386  * :close_others is true by default for spawn and IO.popen.
3387  *
3388  * So IO.pipe and spawn can be used as IO.popen.
3389  *
3390  * # similar to r = IO.popen(command)
3391  * r, w = IO.pipe
3392  * pid = spawn(command, :out=>w) # r, w is closed in the child process.
3393  * w.close
3394  *
3395  * :close is specified as a hash value to close a fd individually.
3396  *
3397  * f = open(foo)
3398  * system(command, f=>:close) # don't inherit f.
3399  *
3400  * If a file descriptor need to be inherited,
3401  * io=>io can be used.
3402  *
3403  * # valgrind has --log-fd option for log destination.
3404  * # log_w=>log_w indicates log_w.fileno inherits to child process.
3405  * log_r, log_w = IO.pipe
3406  * pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
3407  * log_w.close
3408  * p log_r.read
3409  *
3410  * It is also possible to exchange file descriptors.
3411  *
3412  * pid = spawn(command, :out=>:err, :err=>:out)
3413  *
3414  * The hash keys specify file descriptors in the child process.
3415  * The hash values specifies file descriptors in the parent process.
3416  * So the above specifies exchanging stdout and stderr.
3417  * Internally, +spawn+ uses an extra file descriptor to resolve such cyclic
3418  * file descriptor mapping.
3419  *
3420  * See <code>Kernel.exec</code> for the standard shell.
3421  */
3422 
3423 static VALUE
3424 rb_f_spawn(int argc, VALUE *argv)
3425 {
3426  rb_pid_t pid;
3427  char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
3428  struct rb_exec_arg earg;
3429 
3430  pid = rb_spawn_process(&earg, rb_exec_arg_prepare(&earg, argc, argv, TRUE), errmsg, sizeof(errmsg));
3431  if (pid == -1) {
3432  const char *prog = errmsg;
3433  if (!prog[0] && !(prog = earg.prog) && earg.argc) {
3434  prog = RSTRING_PTR(earg.argv[0]);
3435  }
3436  rb_sys_fail(prog);
3437  }
3438 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3439  return PIDT2NUM(pid);
3440 #else
3441  return Qnil;
3442 #endif
3443 }
3444 
3445 /*
3446  * call-seq:
3447  * sleep([duration]) -> fixnum
3448  *
3449  * Suspends the current thread for _duration_ seconds (which may be any number,
3450  * including a +Float+ with fractional seconds). Returns the actual number of
3451  * seconds slept (rounded), which may be less than that asked for if another
3452  * thread calls <code>Thread#run</code>. Called without an argument, sleep()
3453  * will sleep forever.
3454  *
3455  * Time.new #=> 2008-03-08 19:56:19 +0900
3456  * sleep 1.2 #=> 1
3457  * Time.new #=> 2008-03-08 19:56:20 +0900
3458  * sleep 1.9 #=> 2
3459  * Time.new #=> 2008-03-08 19:56:22 +0900
3460  */
3461 
3462 static VALUE
3463 rb_f_sleep(int argc, VALUE *argv)
3464 {
3465  time_t beg, end;
3466 
3467  beg = time(0);
3468  if (argc == 0) {
3470  }
3471  else if (argc == 1) {
3473  }
3474  else {
3475  rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
3476  }
3477 
3478  end = time(0) - beg;
3479 
3480  return INT2FIX(end);
3481 }
3482 
3483 
3484 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
3485 /*
3486  * call-seq:
3487  * Process.getpgrp -> integer
3488  *
3489  * Returns the process group ID for this process. Not available on
3490  * all platforms.
3491  *
3492  * Process.getpgid(0) #=> 25527
3493  * Process.getpgrp #=> 25527
3494  */
3495 
3496 static VALUE
3497 proc_getpgrp(void)
3498 {
3499  rb_pid_t pgrp;
3500 
3501  rb_secure(2);
3502 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
3503  pgrp = getpgrp();
3504  if (pgrp < 0) rb_sys_fail(0);
3505  return PIDT2NUM(pgrp);
3506 #else /* defined(HAVE_GETPGID) */
3507  pgrp = getpgid(0);
3508  if (pgrp < 0) rb_sys_fail(0);
3509  return PIDT2NUM(pgrp);
3510 #endif
3511 }
3512 #else
3513 #define proc_getpgrp rb_f_notimplement
3514 #endif
3515 
3516 
3517 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
3518 /*
3519  * call-seq:
3520  * Process.setpgrp -> 0
3521  *
3522  * Equivalent to <code>setpgid(0,0)</code>. Not available on all
3523  * platforms.
3524  */
3525 
3526 static VALUE
3527 proc_setpgrp(void)
3528 {
3529  rb_secure(2);
3530  /* check for posix setpgid() first; this matches the posix */
3531  /* getpgrp() above. It appears that configure will set SETPGRP_VOID */
3532  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
3533  /* this confusion. */
3534 #ifdef HAVE_SETPGID
3535  if (setpgid(0,0) < 0) rb_sys_fail(0);
3536 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
3537  if (setpgrp() < 0) rb_sys_fail(0);
3538 #endif
3539  return INT2FIX(0);
3540 }
3541 #else
3542 #define proc_setpgrp rb_f_notimplement
3543 #endif
3544 
3545 
3546 #if defined(HAVE_GETPGID)
3547 /*
3548  * call-seq:
3549  * Process.getpgid(pid) -> integer
3550  *
3551  * Returns the process group ID for the given process id. Not
3552  * available on all platforms.
3553  *
3554  * Process.getpgid(Process.ppid()) #=> 25527
3555  */
3556 
3557 static VALUE
3558 proc_getpgid(VALUE obj, VALUE pid)
3559 {
3560  rb_pid_t i;
3561 
3562  rb_secure(2);
3563  i = getpgid(NUM2PIDT(pid));
3564  if (i < 0) rb_sys_fail(0);
3565  return PIDT2NUM(i);
3566 }
3567 #else
3568 #define proc_getpgid rb_f_notimplement
3569 #endif
3570 
3571 
3572 #ifdef HAVE_SETPGID
3573 /*
3574  * call-seq:
3575  * Process.setpgid(pid, integer) -> 0
3576  *
3577  * Sets the process group ID of _pid_ (0 indicates this
3578  * process) to <em>integer</em>. Not available on all platforms.
3579  */
3580 
3581 static VALUE
3582 proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
3583 {
3584  rb_pid_t ipid, ipgrp;
3585 
3586  rb_secure(2);
3587  ipid = NUM2PIDT(pid);
3588  ipgrp = NUM2PIDT(pgrp);
3589 
3590  if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
3591  return INT2FIX(0);
3592 }
3593 #else
3594 #define proc_setpgid rb_f_notimplement
3595 #endif
3596 
3597 
3598 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
3599 #if !defined(HAVE_SETSID)
3600 static rb_pid_t ruby_setsid(void);
3601 #define setsid() ruby_setsid()
3602 #endif
3603 /*
3604  * call-seq:
3605  * Process.setsid -> fixnum
3606  *
3607  * Establishes this process as a new session and process group
3608  * leader, with no controlling tty. Returns the session id. Not
3609  * available on all platforms.
3610  *
3611  * Process.setsid #=> 27422
3612  */
3613 
3614 static VALUE
3615 proc_setsid(void)
3616 {
3617  rb_pid_t pid;
3618 
3619  rb_secure(2);
3620  pid = setsid();
3621  if (pid < 0) rb_sys_fail(0);
3622  return PIDT2NUM(pid);
3623 }
3624 
3625 #if !defined(HAVE_SETSID)
3626 #define HAVE_SETSID 1
3627 static rb_pid_t
3628 ruby_setsid(void)
3629 {
3630  rb_pid_t pid;
3631  int ret;
3632 
3633  pid = getpid();
3634 #if defined(SETPGRP_VOID)
3635  ret = setpgrp();
3636  /* If `pid_t setpgrp(void)' is equivalent to setsid(),
3637  `ret' will be the same value as `pid', and following open() will fail.
3638  In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
3639 #else
3640  ret = setpgrp(0, pid);
3641 #endif
3642  if (ret == -1) return -1;
3643 
3644  if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
3645  rb_update_max_fd(fd);
3646  ioctl(fd, TIOCNOTTY, NULL);
3647  close(fd);
3648  }
3649  return pid;
3650 }
3651 #endif
3652 #else
3653 #define proc_setsid rb_f_notimplement
3654 #endif
3655 
3656 
3657 #ifdef HAVE_GETPRIORITY
3658 /*
3659  * call-seq:
3660  * Process.getpriority(kind, integer) -> fixnum
3661  *
3662  * Gets the scheduling priority for specified process, process group,
3663  * or user. <em>kind</em> indicates the kind of entity to find: one
3664  * of <code>Process::PRIO_PGRP</code>,
3665  * <code>Process::PRIO_USER</code>, or
3666  * <code>Process::PRIO_PROCESS</code>. _integer_ is an id
3667  * indicating the particular process, process group, or user (an id
3668  * of 0 means _current_). Lower priorities are more favorable
3669  * for scheduling. Not available on all platforms.
3670  *
3671  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
3672  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
3673  */
3674 
3675 static VALUE
3676 proc_getpriority(VALUE obj, VALUE which, VALUE who)
3677 {
3678  int prio, iwhich, iwho;
3679 
3680  rb_secure(2);
3681  iwhich = NUM2INT(which);
3682  iwho = NUM2INT(who);
3683 
3684  errno = 0;
3685  prio = getpriority(iwhich, iwho);
3686  if (errno) rb_sys_fail(0);
3687  return INT2FIX(prio);
3688 }
3689 #else
3690 #define proc_getpriority rb_f_notimplement
3691 #endif
3692 
3693 
3694 #ifdef HAVE_GETPRIORITY
3695 /*
3696  * call-seq:
3697  * Process.setpriority(kind, integer, priority) -> 0
3698  *
3699  * See <code>Process#getpriority</code>.
3700  *
3701  * Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0
3702  * Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0
3703  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
3704  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
3705  */
3706 
3707 static VALUE
3708 proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
3709 {
3710  int iwhich, iwho, iprio;
3711 
3712  rb_secure(2);
3713  iwhich = NUM2INT(which);
3714  iwho = NUM2INT(who);
3715  iprio = NUM2INT(prio);
3716 
3717  if (setpriority(iwhich, iwho, iprio) < 0)
3718  rb_sys_fail(0);
3719  return INT2FIX(0);
3720 }
3721 #else
3722 #define proc_setpriority rb_f_notimplement
3723 #endif
3724 
3725 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
3726 static int
3727 rlimit_resource_name2int(const char *name, int casetype)
3728 {
3729  int resource;
3730  const char *p;
3731 #define RESCHECK(r) \
3732  do { \
3733  if (STRCASECMP(name, #r) == 0) { \
3734  resource = RLIMIT_##r; \
3735  goto found; \
3736  } \
3737  } while (0)
3738 
3739  switch (TOUPPER(*name)) {
3740  case 'A':
3741 #ifdef RLIMIT_AS
3742  RESCHECK(AS);
3743 #endif
3744  break;
3745 
3746  case 'C':
3747 #ifdef RLIMIT_CORE
3748  RESCHECK(CORE);
3749 #endif
3750 #ifdef RLIMIT_CPU
3751  RESCHECK(CPU);
3752 #endif
3753  break;
3754 
3755  case 'D':
3756 #ifdef RLIMIT_DATA
3757  RESCHECK(DATA);
3758 #endif
3759  break;
3760 
3761  case 'F':
3762 #ifdef RLIMIT_FSIZE
3763  RESCHECK(FSIZE);
3764 #endif
3765  break;
3766 
3767  case 'M':
3768 #ifdef RLIMIT_MEMLOCK
3769  RESCHECK(MEMLOCK);
3770 #endif
3771 #ifdef RLIMIT_MSGQUEUE
3772  RESCHECK(MSGQUEUE);
3773 #endif
3774  break;
3775 
3776  case 'N':
3777 #ifdef RLIMIT_NOFILE
3778  RESCHECK(NOFILE);
3779 #endif
3780 #ifdef RLIMIT_NPROC
3781  RESCHECK(NPROC);
3782 #endif
3783 #ifdef RLIMIT_NICE
3784  RESCHECK(NICE);
3785 #endif
3786  break;
3787 
3788  case 'R':
3789 #ifdef RLIMIT_RSS
3790  RESCHECK(RSS);
3791 #endif
3792 #ifdef RLIMIT_RTPRIO
3793  RESCHECK(RTPRIO);
3794 #endif
3795 #ifdef RLIMIT_RTTIME
3796  RESCHECK(RTTIME);
3797 #endif
3798  break;
3799 
3800  case 'S':
3801 #ifdef RLIMIT_STACK
3802  RESCHECK(STACK);
3803 #endif
3804 #ifdef RLIMIT_SBSIZE
3805  RESCHECK(SBSIZE);
3806 #endif
3807 #ifdef RLIMIT_SIGPENDING
3808  RESCHECK(SIGPENDING);
3809 #endif
3810  break;
3811  }
3812  return -1;
3813 
3814  found:
3815  switch (casetype) {
3816  case 0:
3817  for (p = name; *p; p++)
3818  if (!ISUPPER(*p))
3819  return -1;
3820  break;
3821 
3822  case 1:
3823  for (p = name; *p; p++)
3824  if (!ISLOWER(*p))
3825  return -1;
3826  break;
3827 
3828  default:
3829  rb_bug("unexpected casetype");
3830  }
3831  return resource;
3832 #undef RESCHECK
3833 }
3834 
3835 static int
3836 rlimit_type_by_hname(const char *name)
3837 {
3838  return rlimit_resource_name2int(name, 0);
3839 }
3840 
3841 static int
3842 rlimit_type_by_lname(const char *name)
3843 {
3844  return rlimit_resource_name2int(name, 1);
3845 }
3846 
3847 static int
3848 rlimit_resource_type(VALUE rtype)
3849 {
3850  const char *name;
3851  VALUE v;
3852  int r;
3853 
3854  switch (TYPE(rtype)) {
3855  case T_SYMBOL:
3856  name = rb_id2name(SYM2ID(rtype));
3857  break;
3858 
3859  default:
3860  v = rb_check_string_type(rtype);
3861  if (!NIL_P(v)) {
3862  rtype = v;
3863  case T_STRING:
3864  name = StringValueCStr(rtype);
3865  break;
3866  }
3867  /* fall through */
3868 
3869  case T_FIXNUM:
3870  case T_BIGNUM:
3871  return NUM2INT(rtype);
3872  }
3873 
3874  r = rlimit_type_by_hname(name);
3875  if (r != -1)
3876  return r;
3877 
3878  rb_raise(rb_eArgError, "invalid resource name: %s", name);
3879 }
3880 
3881 static rlim_t
3882 rlimit_resource_value(VALUE rval)
3883 {
3884  const char *name;
3885  VALUE v;
3886 
3887  switch (TYPE(rval)) {
3888  case T_SYMBOL:
3889  name = rb_id2name(SYM2ID(rval));
3890  break;
3891 
3892  default:
3893  v = rb_check_string_type(rval);
3894  if (!NIL_P(v)) {
3895  rval = v;
3896  case T_STRING:
3897  name = StringValueCStr(rval);
3898  break;
3899  }
3900  /* fall through */
3901 
3902  case T_FIXNUM:
3903  case T_BIGNUM:
3904  return NUM2RLIM(rval);
3905  }
3906 
3907 #ifdef RLIM_INFINITY
3908  if (strcmp(name, "INFINITY") == 0) return RLIM_INFINITY;
3909 #endif
3910 #ifdef RLIM_SAVED_MAX
3911  if (strcmp(name, "SAVED_MAX") == 0) return RLIM_SAVED_MAX;
3912 #endif
3913 #ifdef RLIM_SAVED_CUR
3914  if (strcmp(name, "SAVED_CUR") == 0) return RLIM_SAVED_CUR;
3915 #endif
3916  rb_raise(rb_eArgError, "invalid resource value: %s", name);
3917 }
3918 #endif
3919 
3920 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
3921 /*
3922  * call-seq:
3923  * Process.getrlimit(resource) -> [cur_limit, max_limit]
3924  *
3925  * Gets the resource limit of the process.
3926  * _cur_limit_ means current (soft) limit and
3927  * _max_limit_ means maximum (hard) limit.
3928  *
3929  * _resource_ indicates the kind of resource to limit.
3930  * It is specified as a symbol such as <code>:CORE</code>,
3931  * a string such as <code>"CORE"</code> or
3932  * a constant such as <code>Process::RLIMIT_CORE</code>.
3933  * See Process.setrlimit for details.
3934  *
3935  * _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
3936  * <code>Process::RLIM_SAVED_MAX</code> or
3937  * <code>Process::RLIM_SAVED_CUR</code>.
3938  * See Process.setrlimit and the system getrlimit(2) manual for details.
3939  */
3940 
3941 static VALUE
3942 proc_getrlimit(VALUE obj, VALUE resource)
3943 {
3944  struct rlimit rlim;
3945 
3946  rb_secure(2);
3947 
3948  if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
3949  rb_sys_fail("getrlimit");
3950  }
3951  return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
3952 }
3953 #else
3954 #define proc_getrlimit rb_f_notimplement
3955 #endif
3956 
3957 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
3958 /*
3959  * call-seq:
3960  * Process.setrlimit(resource, cur_limit, max_limit) -> nil
3961  * Process.setrlimit(resource, cur_limit) -> nil
3962  *
3963  * Sets the resource limit of the process.
3964  * _cur_limit_ means current (soft) limit and
3965  * _max_limit_ means maximum (hard) limit.
3966  *
3967  * If _max_limit_ is not given, _cur_limit_ is used.
3968  *
3969  * _resource_ indicates the kind of resource to limit.
3970  * It should be a symbol such as <code>:CORE</code>,
3971  * a string such as <code>"CORE"</code> or
3972  * a constant such as <code>Process::RLIMIT_CORE</code>.
3973  * The available resources are OS dependent.
3974  * Ruby may support following resources.
3975  *
3976  * [AS] total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)
3977  * [CORE] core size (bytes) (SUSv3)
3978  * [CPU] CPU time (seconds) (SUSv3)
3979  * [DATA] data segment (bytes) (SUSv3)
3980  * [FSIZE] file size (bytes) (SUSv3)
3981  * [MEMLOCK] total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)
3982  * [MSGQUEUE] allocation for POSIX message queues (bytes) (GNU/Linux)
3983  * [NICE] ceiling on process's nice(2) value (number) (GNU/Linux)
3984  * [NOFILE] file descriptors (number) (SUSv3)
3985  * [NPROC] number of processes for the user (number) (4.4BSD, GNU/Linux)
3986  * [RSS] resident memory size (bytes) (4.2BSD, GNU/Linux)
3987  * [RTPRIO] ceiling on the process's real-time priority (number) (GNU/Linux)
3988  * [RTTIME] CPU time for real-time process (us) (GNU/Linux)
3989  * [SBSIZE] all socket buffers (bytes) (NetBSD, FreeBSD)
3990  * [SIGPENDING] number of queued signals allowed (signals) (GNU/Linux)
3991  * [STACK] stack size (bytes) (SUSv3)
3992  *
3993  * _cur_limit_ and _max_limit_ may be
3994  * <code>:INFINITY</code>, <code>"INFINITY"</code> or
3995  * <code>Process::RLIM_INFINITY</code>,
3996  * which means that the resource is not limited.
3997  * They may be <code>Process::RLIM_SAVED_MAX</code>,
3998  * <code>Process::RLIM_SAVED_CUR</code> and
3999  * corresponding symbols and strings too.
4000  * See system setrlimit(2) manual for details.
4001  *
4002  * The following example raises the soft limit of core size to
4003  * the hard limit to try to make core dump possible.
4004  *
4005  * Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
4006  *
4007  */
4008 
4009 static VALUE
4010 proc_setrlimit(int argc, VALUE *argv, VALUE obj)
4011 {
4012  VALUE resource, rlim_cur, rlim_max;
4013  struct rlimit rlim;
4014 
4015  rb_secure(2);
4016 
4017  rb_scan_args(argc, argv, "21", &resource, &rlim_cur, &rlim_max);
4018  if (rlim_max == Qnil)
4019  rlim_max = rlim_cur;
4020 
4021  rlim.rlim_cur = rlimit_resource_value(rlim_cur);
4022  rlim.rlim_max = rlimit_resource_value(rlim_max);
4023 
4024  if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4025  rb_sys_fail("setrlimit");
4026  }
4027  return Qnil;
4028 }
4029 #else
4030 #define proc_setrlimit rb_f_notimplement
4031 #endif
4032 
4033 static int under_uid_switch = 0;
4034 static void
4036 {
4037  rb_secure(2);
4038  if (under_uid_switch) {
4039  rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
4040  }
4041 }
4042 
4043 static int under_gid_switch = 0;
4044 static void
4046 {
4047  rb_secure(2);
4048  if (under_gid_switch) {
4049  rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
4050  }
4051 }
4052 
4053 
4054 /*********************************************************************
4055  * Document-class: Process::Sys
4056  *
4057  * The <code>Process::Sys</code> module contains UID and GID
4058  * functions which provide direct bindings to the system calls of the
4059  * same names instead of the more-portable versions of the same
4060  * functionality found in the <code>Process</code>,
4061  * <code>Process::UID</code>, and <code>Process::GID</code> modules.
4062  */
4063 
4064 
4065 #if defined HAVE_SETUID
4066 /*
4067  * call-seq:
4068  * Process::Sys.setuid(integer) -> nil
4069  *
4070  * Set the user ID of the current process to _integer_. Not
4071  * available on all platforms.
4072  *
4073  */
4074 
4075 static VALUE
4076 p_sys_setuid(VALUE obj, VALUE id)
4077 {
4078  check_uid_switch();
4079  if (setuid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
4080  return Qnil;
4081 }
4082 #else
4083 #define p_sys_setuid rb_f_notimplement
4084 #endif
4085 
4086 
4087 #if defined HAVE_SETRUID
4088 /*
4089  * call-seq:
4090  * Process::Sys.setruid(integer) -> nil
4091  *
4092  * Set the real user ID of the calling process to _integer_.
4093  * Not available on all platforms.
4094  *
4095  */
4096 
4097 static VALUE
4098 p_sys_setruid(VALUE obj, VALUE id)
4099 {
4100  check_uid_switch();
4101  if (setruid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
4102  return Qnil;
4103 }
4104 #else
4105 #define p_sys_setruid rb_f_notimplement
4106 #endif
4107 
4108 
4109 #if defined HAVE_SETEUID
4110 /*
4111  * call-seq:
4112  * Process::Sys.seteuid(integer) -> nil
4113  *
4114  * Set the effective user ID of the calling process to
4115  * _integer_. Not available on all platforms.
4116  *
4117  */
4118 
4119 static VALUE
4120 p_sys_seteuid(VALUE obj, VALUE id)
4121 {
4122  check_uid_switch();
4123  if (seteuid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
4124  return Qnil;
4125 }
4126 #else
4127 #define p_sys_seteuid rb_f_notimplement
4128 #endif
4129 
4130 
4131 #if defined HAVE_SETREUID
4132 /*
4133  * call-seq:
4134  * Process::Sys.setreuid(rid, eid) -> nil
4135  *
4136  * Sets the (integer) real and/or effective user IDs of the current
4137  * process to _rid_ and _eid_, respectively. A value of
4138  * <code>-1</code> for either means to leave that ID unchanged. Not
4139  * available on all platforms.
4140  *
4141  */
4142 
4143 static VALUE
4144 p_sys_setreuid(VALUE obj, VALUE rid, VALUE eid)
4145 {
4146  check_uid_switch();
4147  if (setreuid(NUM2UIDT(rid),NUM2UIDT(eid)) != 0) rb_sys_fail(0);
4148  return Qnil;
4149 }
4150 #else
4151 #define p_sys_setreuid rb_f_notimplement
4152 #endif
4153 
4154 
4155 #if defined HAVE_SETRESUID
4156 /*
4157  * call-seq:
4158  * Process::Sys.setresuid(rid, eid, sid) -> nil
4159  *
4160  * Sets the (integer) real, effective, and saved user IDs of the
4161  * current process to _rid_, _eid_, and _sid_ respectively. A
4162  * value of <code>-1</code> for any value means to
4163  * leave that ID unchanged. Not available on all platforms.
4164  *
4165  */
4166 
4167 static VALUE
4168 p_sys_setresuid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
4169 {
4170  check_uid_switch();
4171  if (setresuid(NUM2UIDT(rid),NUM2UIDT(eid),NUM2UIDT(sid)) != 0) rb_sys_fail(0);
4172  return Qnil;
4173 }
4174 #else
4175 #define p_sys_setresuid rb_f_notimplement
4176 #endif
4177 
4178 
4179 /*
4180  * call-seq:
4181  * Process.uid -> fixnum
4182  * Process::UID.rid -> fixnum
4183  * Process::Sys.getuid -> fixnum
4184  *
4185  * Returns the (real) user ID of this process.
4186  *
4187  * Process.uid #=> 501
4188  */
4189 
4190 static VALUE
4192 {
4193  rb_uid_t uid = getuid();
4194  return UIDT2NUM(uid);
4195 }
4196 
4197 
4198 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
4199 /*
4200  * call-seq:
4201  * Process.uid= integer -> numeric
4202  *
4203  * Sets the (integer) user ID for this process. Not available on all
4204  * platforms.
4205  */
4206 
4207 static VALUE
4208 proc_setuid(VALUE obj, VALUE id)
4209 {
4210  rb_uid_t uid;
4211 
4212  check_uid_switch();
4213 
4214  uid = NUM2UIDT(id);
4215 #if defined(HAVE_SETRESUID)
4216  if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
4217 #elif defined HAVE_SETREUID
4218  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
4219 #elif defined HAVE_SETRUID
4220  if (setruid(uid) < 0) rb_sys_fail(0);
4221 #elif defined HAVE_SETUID
4222  {
4223  if (geteuid() == uid) {
4224  if (setuid(uid) < 0) rb_sys_fail(0);
4225  }
4226  else {
4227  rb_notimplement();
4228  }
4229  }
4230 #endif
4231  return id;
4232 }
4233 #else
4234 #define proc_setuid rb_f_notimplement
4235 #endif
4236 
4237 
4238 /********************************************************************
4239  *
4240  * Document-class: Process::UID
4241  *
4242  * The <code>Process::UID</code> module contains a collection of
4243  * module functions which can be used to portably get, set, and
4244  * switch the current process's real, effective, and saved user IDs.
4245  *
4246  */
4247 
4248 static rb_uid_t SAVED_USER_ID = -1;
4249 
4250 #ifdef BROKEN_SETREUID
4251 int
4252 setreuid(rb_uid_t ruid, rb_uid_t euid)
4253 {
4254  if (ruid != (rb_uid_t)-1 && ruid != getuid()) {
4255  if (euid == (rb_uid_t)-1) euid = geteuid();
4256  if (setuid(ruid) < 0) return -1;
4257  }
4258  if (euid != (rb_uid_t)-1 && euid != geteuid()) {
4259  if (seteuid(euid) < 0) return -1;
4260  }
4261  return 0;
4262 }
4263 #endif
4264 
4265 /*
4266  * call-seq:
4267  * Process::UID.change_privilege(integer) -> fixnum
4268  *
4269  * Change the current process's real and effective user ID to that
4270  * specified by _integer_. Returns the new user ID. Not
4271  * available on all platforms.
4272  *
4273  * [Process.uid, Process.euid] #=> [0, 0]
4274  * Process::UID.change_privilege(31) #=> 31
4275  * [Process.uid, Process.euid] #=> [31, 31]
4276  */
4277 
4278 static VALUE
4280 {
4281  rb_uid_t uid;
4282 
4283  check_uid_switch();
4284 
4285  uid = NUM2UIDT(id);
4286 
4287  if (geteuid() == 0) { /* root-user */
4288 #if defined(HAVE_SETRESUID)
4289  if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
4290  SAVED_USER_ID = uid;
4291 #elif defined(HAVE_SETUID)
4292  if (setuid(uid) < 0) rb_sys_fail(0);
4293  SAVED_USER_ID = uid;
4294 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
4295  if (getuid() == uid) {
4296  if (SAVED_USER_ID == uid) {
4297  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
4298  } else {
4299  if (uid == 0) { /* (r,e,s) == (root, root, x) */
4300  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
4301  if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
4302  SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
4303  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
4304  SAVED_USER_ID = uid;
4305  } else {
4306  if (setreuid(0, -1) < 0) rb_sys_fail(0);
4307  SAVED_USER_ID = 0;
4308  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
4309  SAVED_USER_ID = uid;
4310  }
4311  }
4312  } else {
4313  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
4314  SAVED_USER_ID = uid;
4315  }
4316 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
4317  if (getuid() == uid) {
4318  if (SAVED_USER_ID == uid) {
4319  if (seteuid(uid) < 0) rb_sys_fail(0);
4320  } else {
4321  if (uid == 0) {
4322  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
4323  SAVED_USER_ID = 0;
4324  if (setruid(0) < 0) rb_sys_fail(0);
4325  } else {
4326  if (setruid(0) < 0) rb_sys_fail(0);
4327  SAVED_USER_ID = 0;
4328  if (seteuid(uid) < 0) rb_sys_fail(0);
4329  if (setruid(uid) < 0) rb_sys_fail(0);
4330  SAVED_USER_ID = uid;
4331  }
4332  }
4333  } else {
4334  if (seteuid(uid) < 0) rb_sys_fail(0);
4335  if (setruid(uid) < 0) rb_sys_fail(0);
4336  SAVED_USER_ID = uid;
4337  }
4338 #else
4339  rb_notimplement();
4340 #endif
4341  } else { /* unprivileged user */
4342 #if defined(HAVE_SETRESUID)
4343  if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
4344  (geteuid() == uid)? (rb_uid_t)-1: uid,
4345  (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
4346  SAVED_USER_ID = uid;
4347 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
4348  if (SAVED_USER_ID == uid) {
4349  if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
4350  (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
4351  rb_sys_fail(0);
4352  } else if (getuid() != uid) {
4353  if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
4354  rb_sys_fail(0);
4355  SAVED_USER_ID = uid;
4356  } else if (/* getuid() == uid && */ geteuid() != uid) {
4357  if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
4358  SAVED_USER_ID = uid;
4359  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
4360  } else { /* getuid() == uid && geteuid() == uid */
4361  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
4362  if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
4363  SAVED_USER_ID = uid;
4364  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
4365  }
4366 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
4367  if (SAVED_USER_ID == uid) {
4368  if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
4369  if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
4370  } else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
4371  if (getuid() != uid) {
4372  if (setruid(uid) < 0) rb_sys_fail(0);
4373  SAVED_USER_ID = uid;
4374  } else {
4375  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
4376  SAVED_USER_ID = uid;
4377  if (setruid(uid) < 0) rb_sys_fail(0);
4378  }
4379  } else if (/* geteuid() != uid && */ getuid() == uid) {
4380  if (seteuid(uid) < 0) rb_sys_fail(0);
4381  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
4382  SAVED_USER_ID = uid;
4383  if (setruid(uid) < 0) rb_sys_fail(0);
4384  } else {
4385  errno = EPERM;
4386  rb_sys_fail(0);
4387  }
4388 #elif defined HAVE_44BSD_SETUID
4389  if (getuid() == uid) {
4390  /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
4391  if (setuid(uid) < 0) rb_sys_fail(0);
4392  SAVED_USER_ID = uid;
4393  } else {
4394  errno = EPERM;
4395  rb_sys_fail(0);
4396  }
4397 #elif defined HAVE_SETEUID
4398  if (getuid() == uid && SAVED_USER_ID == uid) {
4399  if (seteuid(uid) < 0) rb_sys_fail(0);
4400  } else {
4401  errno = EPERM;
4402  rb_sys_fail(0);
4403  }
4404 #elif defined HAVE_SETUID
4405  if (getuid() == uid && SAVED_USER_ID == uid) {
4406  if (setuid(uid) < 0) rb_sys_fail(0);
4407  } else {
4408  errno = EPERM;
4409  rb_sys_fail(0);
4410  }
4411 #else
4412  rb_notimplement();
4413 #endif
4414  }
4415  return id;
4416 }
4417 
4418 
4419 
4420 #if defined HAVE_SETGID
4421 /*
4422  * call-seq:
4423  * Process::Sys.setgid(integer) -> nil
4424  *
4425  * Set the group ID of the current process to _integer_. Not
4426  * available on all platforms.
4427  *
4428  */
4429 
4430 static VALUE
4431 p_sys_setgid(VALUE obj, VALUE id)
4432 {
4433  check_gid_switch();
4434  if (setgid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
4435  return Qnil;
4436 }
4437 #else
4438 #define p_sys_setgid rb_f_notimplement
4439 #endif
4440 
4441 
4442 #if defined HAVE_SETRGID
4443 /*
4444  * call-seq:
4445  * Process::Sys.setrgid(integer) -> nil
4446  *
4447  * Set the real group ID of the calling process to _integer_.
4448  * Not available on all platforms.
4449  *
4450  */
4451 
4452 static VALUE
4453 p_sys_setrgid(VALUE obj, VALUE id)
4454 {
4455  check_gid_switch();
4456  if (setrgid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
4457  return Qnil;
4458 }
4459 #else
4460 #define p_sys_setrgid rb_f_notimplement
4461 #endif
4462 
4463 
4464 #if defined HAVE_SETEGID
4465 /*
4466  * call-seq:
4467  * Process::Sys.setegid(integer) -> nil
4468  *
4469  * Set the effective group ID of the calling process to
4470  * _integer_. Not available on all platforms.
4471  *
4472  */
4473 
4474 static VALUE
4475 p_sys_setegid(VALUE obj, VALUE id)
4476 {
4477  check_gid_switch();
4478  if (setegid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
4479  return Qnil;
4480 }
4481 #else
4482 #define p_sys_setegid rb_f_notimplement
4483 #endif
4484 
4485 
4486 #if defined HAVE_SETREGID
4487 /*
4488  * call-seq:
4489  * Process::Sys.setregid(rid, eid) -> nil
4490  *
4491  * Sets the (integer) real and/or effective group IDs of the current
4492  * process to <em>rid</em> and <em>eid</em>, respectively. A value of
4493  * <code>-1</code> for either means to leave that ID unchanged. Not
4494  * available on all platforms.
4495  *
4496  */
4497 
4498 static VALUE
4499 p_sys_setregid(VALUE obj, VALUE rid, VALUE eid)
4500 {
4501  check_gid_switch();
4502  if (setregid(NUM2GIDT(rid),NUM2GIDT(eid)) != 0) rb_sys_fail(0);
4503  return Qnil;
4504 }
4505 #else
4506 #define p_sys_setregid rb_f_notimplement
4507 #endif
4508 
4509 #if defined HAVE_SETRESGID
4510 /*
4511  * call-seq:
4512  * Process::Sys.setresgid(rid, eid, sid) -> nil
4513  *
4514  * Sets the (integer) real, effective, and saved user IDs of the
4515  * current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
4516  * respectively. A value of <code>-1</code> for any value means to
4517  * leave that ID unchanged. Not available on all platforms.
4518  *
4519  */
4520 
4521 static VALUE
4522 p_sys_setresgid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
4523 {
4524  check_gid_switch();
4525  if (setresgid(NUM2GIDT(rid),NUM2GIDT(eid),NUM2GIDT(sid)) != 0) rb_sys_fail(0);
4526  return Qnil;
4527 }
4528 #else
4529 #define p_sys_setresgid rb_f_notimplement
4530 #endif
4531 
4532 
4533 #if defined HAVE_ISSETUGID
4534 /*
4535  * call-seq:
4536  * Process::Sys.issetugid -> true or false
4537  *
4538  * Returns +true+ if the process was created as a result
4539  * of an execve(2) system call which had either of the setuid or
4540  * setgid bits set (and extra privileges were given as a result) or
4541  * if it has changed any of its real, effective or saved user or
4542  * group IDs since it began execution.
4543  *
4544  */
4545 
4546 static VALUE
4548 {
4549  rb_secure(2);
4550  if (issetugid()) {
4551  return Qtrue;
4552  } else {
4553  return Qfalse;
4554  }
4555 }
4556 #else
4557 #define p_sys_issetugid rb_f_notimplement
4558 #endif
4559 
4560 
4561 /*
4562  * call-seq:
4563  * Process.gid -> fixnum
4564  * Process::GID.rid -> fixnum
4565  * Process::Sys.getgid -> fixnum
4566  *
4567  * Returns the (real) group ID for this process.
4568  *
4569  * Process.gid #=> 500
4570  */
4571 
4572 static VALUE
4574 {
4575  rb_gid_t gid = getgid();
4576  return GIDT2NUM(gid);
4577 }
4578 
4579 
4580 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
4581 /*
4582  * call-seq:
4583  * Process.gid= fixnum -> fixnum
4584  *
4585  * Sets the group ID for this process.
4586  */
4587 
4588 static VALUE
4589 proc_setgid(VALUE obj, VALUE id)
4590 {
4591  rb_gid_t gid;
4592 
4593  check_gid_switch();
4594 
4595  gid = NUM2GIDT(id);
4596 #if defined(HAVE_SETRESGID)
4597  if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
4598 #elif defined HAVE_SETREGID
4599  if (setregid(gid, -1) < 0) rb_sys_fail(0);
4600 #elif defined HAVE_SETRGID
4601  if (setrgid(gid) < 0) rb_sys_fail(0);
4602 #elif defined HAVE_SETGID
4603  {
4604  if (getegid() == gid) {
4605  if (setgid(gid) < 0) rb_sys_fail(0);
4606  }
4607  else {
4608  rb_notimplement();
4609  }
4610  }
4611 #endif
4612  return GIDT2NUM(gid);
4613 }
4614 #else
4615 #define proc_setgid rb_f_notimplement
4616 #endif
4617 
4618 
4619 #if defined(HAVE_SETGROUPS) || defined(HAVE_GETGROUPS)
4620 /*
4621  * Maximum supplementary groups are platform dependent.
4622  * FWIW, 65536 is enough big for our supported OSs.
4623  *
4624  * OS Name max groups
4625  * -----------------------------------------------
4626  * Linux Kernel >= 2.6.3 65536
4627  * Linux Kernel < 2.6.3 32
4628  * IBM AIX 5.2 64
4629  * IBM AIX 5.3 ... 6.1 128
4630  * IBM AIX 7.1 128 (can be configured to be up to 2048)
4631  * OpenBSD, NetBSD 16
4632  * FreeBSD < 8.0 16
4633  * FreeBSD >=8.0 1023
4634  * Darwin (Mac OS X) 16
4635  * Sun Solaris 7,8,9,10 16
4636  * Sun Solaris 11 / OpenSolaris 1024
4637  * HP-UX 20
4638  * Windows 1015
4639  */
4640 #define RB_MAX_GROUPS (65536)
4641 static int _maxgroups = -1;
4642 static int get_sc_ngroups_max(void)
4643 {
4644 #ifdef _SC_NGROUPS_MAX
4645  return (int)sysconf(_SC_NGROUPS_MAX);
4646 #elif defined(NGROUPS_MAX)
4647  return (int)NGROUPS_MAX;
4648 #else
4649  return -1;
4650 #endif
4651 }
4652 static int maxgroups(void)
4653 {
4654  if (_maxgroups < 0) {
4655  _maxgroups = get_sc_ngroups_max();
4656  if (_maxgroups < 0)
4657  _maxgroups = RB_MAX_GROUPS;
4658  }
4659 
4660  return _maxgroups;
4661 }
4662 #endif
4663 
4664 
4665 
4666 #ifdef HAVE_GETGROUPS
4667 /*
4668  * call-seq:
4669  * Process.groups -> array
4670  *
4671  * Get an <code>Array</code> of the gids of groups in the
4672  * supplemental group access list for this process.
4673  *
4674  * Process.groups #=> [27, 6, 10, 11]
4675  *
4676  */
4677 
4678 static VALUE
4679 proc_getgroups(VALUE obj)
4680 {
4681  VALUE ary;
4682  int i, ngroups;
4683  rb_gid_t *groups;
4684 
4685  ngroups = getgroups(0, NULL);
4686  if (ngroups == -1)
4687  rb_sys_fail(0);
4688 
4689  groups = ALLOCA_N(rb_gid_t, ngroups);
4690 
4691  ngroups = getgroups(ngroups, groups);
4692  if (ngroups == -1)
4693  rb_sys_fail(0);
4694 
4695  ary = rb_ary_new();
4696  for (i = 0; i < ngroups; i++)
4697  rb_ary_push(ary, GIDT2NUM(groups[i]));
4698 
4699  return ary;
4700 }
4701 #else
4702 #define proc_getgroups rb_f_notimplement
4703 #endif
4704 
4705 
4706 #ifdef HAVE_SETGROUPS
4707 /*
4708  * call-seq:
4709  * Process.groups= array -> array
4710  *
4711  * Set the supplemental group access list to the given
4712  * <code>Array</code> of group IDs.
4713  *
4714  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
4715  * Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11]
4716  * Process.groups #=> [27, 6, 10, 11]
4717  *
4718  */
4719 
4720 static VALUE
4721 proc_setgroups(VALUE obj, VALUE ary)
4722 {
4723  int ngroups, i;
4724  rb_gid_t *groups;
4725 #ifdef HAVE_GETGRNAM_R
4726  long getgr_buf_len = sysconf(_SC_GETGR_R_SIZE_MAX);
4727  char* getgr_buf;
4728 
4729  if (getgr_buf_len < 0)
4730  getgr_buf_len = 4096;
4731  getgr_buf = ALLOCA_N(char, getgr_buf_len);
4732 #endif
4733 
4734  Check_Type(ary, T_ARRAY);
4735 
4736  ngroups = RARRAY_LENINT(ary);
4737  if (ngroups > maxgroups())
4738  rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());
4739 
4740  groups = ALLOCA_N(rb_gid_t, ngroups);
4741 
4742  for (i = 0; i < ngroups; i++) {
4743  VALUE g = RARRAY_PTR(ary)[i];
4744 
4745  if (FIXNUM_P(g)) {
4746  groups[i] = NUM2GIDT(g);
4747  }
4748  else {
4749  VALUE tmp = rb_check_string_type(g);
4750  struct group grp;
4751  struct group *p;
4752  int ret;
4753 
4754  if (NIL_P(tmp)) {
4755  groups[i] = NUM2GIDT(g);
4756  }
4757  else {
4758  const char *grpname = StringValueCStr(tmp);
4759 
4760 #ifdef HAVE_GETGRNAM_R
4761  ret = getgrnam_r(grpname, &grp, getgr_buf, getgr_buf_len, &p);
4762  if (ret)
4763  rb_sys_fail("getgrnam_r");
4764 #else
4765  p = getgrnam(grpname);
4766 #endif
4767  if (p == NULL) {
4769  "can't find group for %s", RSTRING_PTR(tmp));
4770  }
4771  groups[i] = p->gr_gid;
4772  }
4773  }
4774  }
4775 
4776  if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
4777  rb_sys_fail(0);
4778 
4779  return proc_getgroups(obj);
4780 }
4781 #else
4782 #define proc_setgroups rb_f_notimplement
4783 #endif
4784 
4785 
4786 #ifdef HAVE_INITGROUPS
4787 /*
4788  * call-seq:
4789  * Process.initgroups(username, gid) -> array
4790  *
4791  * Initializes the supplemental group access list by reading the
4792  * system group database and using all groups of which the given user
4793  * is a member. The group with the specified <em>gid</em> is also
4794  * added to the list. Returns the resulting <code>Array</code> of the
4795  * gids of all the groups in the supplementary group access list. Not
4796  * available on all platforms.
4797  *
4798  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
4799  * Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
4800  * Process.groups #=> [30, 6, 10, 11]
4801  *
4802  */
4803 
4804 static VALUE
4805 proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
4806 {
4807  if (initgroups(StringValuePtr(uname), NUM2GIDT(base_grp)) != 0) {
4808  rb_sys_fail(0);
4809  }
4810  return proc_getgroups(obj);
4811 }
4812 #else
4813 #define proc_initgroups rb_f_notimplement
4814 #endif
4815 
4816 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
4817 /*
4818  * call-seq:
4819  * Process.maxgroups -> fixnum
4820  *
4821  * Returns the maximum number of gids allowed in the supplemental
4822  * group access list.
4823  *
4824  * Process.maxgroups #=> 32
4825  */
4826 
4827 static VALUE
4829 {
4830  return INT2FIX(maxgroups());
4831 }
4832 #else
4833 #define proc_getmaxgroups rb_f_notimplement
4834 #endif
4835 
4836 #ifdef HAVE_SETGROUPS
4837 /*
4838  * call-seq:
4839  * Process.maxgroups= fixnum -> fixnum
4840  *
4841  * Sets the maximum number of gids allowed in the supplemental group
4842  * access list.
4843  */
4844 
4845 static VALUE
4846 proc_setmaxgroups(VALUE obj, VALUE val)
4847 {
4848  int ngroups = FIX2INT(val);
4849  int ngroups_max = get_sc_ngroups_max();
4850 
4851  if (ngroups <= 0)
4852  rb_raise(rb_eArgError, "maxgroups %d shold be positive", ngroups);
4853 
4854  if (ngroups > RB_MAX_GROUPS)
4855  ngroups = RB_MAX_GROUPS;
4856 
4857  if (ngroups_max > 0 && ngroups > ngroups_max)
4858  ngroups = ngroups_max;
4859 
4860  _maxgroups = ngroups;
4861 
4862  return INT2FIX(_maxgroups);
4863 }
4864 #else
4865 #define proc_setmaxgroups rb_f_notimplement
4866 #endif
4867 
4868 #if defined(HAVE_DAEMON) || (defined(HAVE_FORK) && defined(HAVE_SETSID))
4869 static int rb_daemon(int nochdir, int noclose);
4870 
4871 /*
4872  * call-seq:
4873  * Process.daemon() -> 0
4874  * Process.daemon(nochdir=nil,noclose=nil) -> 0
4875  *
4876  * Detach the process from controlling terminal and run in
4877  * the background as system daemon. Unless the argument
4878  * nochdir is true (i.e. non false), it changes the current
4879  * working directory to the root ("/"). Unless the argument
4880  * noclose is true, daemon() will redirect standard input,
4881  * standard output and standard error to /dev/null.
4882  * Return zero on success, or raise one of Errno::*.
4883  */
4884 
4885 static VALUE
4886 proc_daemon(int argc, VALUE *argv)
4887 {
4888  VALUE nochdir, noclose;
4889  int n;
4890 
4891  rb_secure(2);
4892  rb_scan_args(argc, argv, "02", &nochdir, &noclose);
4893 
4894  prefork();
4895  n = rb_daemon(RTEST(nochdir), RTEST(noclose));
4896  if (n < 0) rb_sys_fail("daemon");
4897  return INT2FIX(n);
4898 }
4899 
4900 static int
4901 rb_daemon(int nochdir, int noclose)
4902 {
4903  int err = 0;
4904 #ifdef HAVE_DAEMON
4905  before_fork();
4906  err = daemon(nochdir, noclose);
4907  after_fork();
4908 #else
4909  int n;
4910 
4911  switch (rb_fork(0, 0, 0, Qnil)) {
4912  case -1:
4913  rb_sys_fail("daemon");
4914  case 0:
4915  break;
4916  default:
4917  _exit(EXIT_SUCCESS);
4918  }
4919 
4920  proc_setsid();
4921 
4922  /* must not be process-leader */
4923  switch (rb_fork(0, 0, 0, Qnil)) {
4924  case -1:
4925  return -1;
4926  case 0:
4927  break;
4928  default:
4929  _exit(EXIT_SUCCESS);
4930  }
4931 
4932  if (!nochdir)
4933  err = chdir("/");
4934 
4935  if (!noclose && (n = open("/dev/null", O_RDWR, 0)) != -1) {
4936  rb_update_max_fd(n);
4937  (void)dup2(n, 0);
4938  (void)dup2(n, 1);
4939  (void)dup2(n, 2);
4940  if (n > 2)
4941  (void)close (n);
4942  }
4943 #endif
4944  return err;
4945 }
4946 #else
4947 #define proc_daemon rb_f_notimplement
4948 #endif
4949 
4950 /********************************************************************
4951  *
4952  * Document-class: Process::GID
4953  *
4954  * The <code>Process::GID</code> module contains a collection of
4955  * module functions which can be used to portably get, set, and
4956  * switch the current process's real, effective, and saved group IDs.
4957  *
4958  */
4959 
4960 static rb_gid_t SAVED_GROUP_ID = -1;
4961 
4962 #ifdef BROKEN_SETREGID
4963 int
4964 setregid(rb_gid_t rgid, rb_gid_t egid)
4965 {
4966  if (rgid != (rb_gid_t)-1 && rgid != getgid()) {
4967  if (egid == (rb_gid_t)-1) egid = getegid();
4968  if (setgid(rgid) < 0) return -1;
4969  }
4970  if (egid != (rb_gid_t)-1 && egid != getegid()) {
4971  if (setegid(egid) < 0) return -1;
4972  }
4973  return 0;
4974 }
4975 #endif
4976 
4977 /*
4978  * call-seq:
4979  * Process::GID.change_privilege(integer) -> fixnum
4980  *
4981  * Change the current process's real and effective group ID to that
4982  * specified by _integer_. Returns the new group ID. Not
4983  * available on all platforms.
4984  *
4985  * [Process.gid, Process.egid] #=> [0, 0]
4986  * Process::GID.change_privilege(33) #=> 33
4987  * [Process.gid, Process.egid] #=> [33, 33]
4988  */
4989 
4990 static VALUE
4992 {
4993  rb_gid_t gid;
4994 
4995  check_gid_switch();
4996 
4997  gid = NUM2GIDT(id);
4998 
4999  if (geteuid() == 0) { /* root-user */
5000 #if defined(HAVE_SETRESGID)
5001  if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
5002  SAVED_GROUP_ID = gid;
5003 #elif defined HAVE_SETGID
5004  if (setgid(gid) < 0) rb_sys_fail(0);
5005  SAVED_GROUP_ID = gid;
5006 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5007  if (getgid() == gid) {
5008  if (SAVED_GROUP_ID == gid) {
5009  if (setregid(-1, gid) < 0) rb_sys_fail(0);
5010  } else {
5011  if (gid == 0) { /* (r,e,s) == (root, y, x) */
5012  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5013  if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
5014  SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
5015  if (setregid(gid, gid) < 0) rb_sys_fail(0);
5016  SAVED_GROUP_ID = gid;
5017  } else { /* (r,e,s) == (z, y, x) */
5018  if (setregid(0, 0) < 0) rb_sys_fail(0);
5019  SAVED_GROUP_ID = 0;
5020  if (setregid(gid, gid) < 0) rb_sys_fail(0);
5021  SAVED_GROUP_ID = gid;
5022  }
5023  }
5024  } else {
5025  if (setregid(gid, gid) < 0) rb_sys_fail(0);
5026  SAVED_GROUP_ID = gid;
5027  }
5028 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
5029  if (getgid() == gid) {
5030  if (SAVED_GROUP_ID == gid) {
5031  if (setegid(gid) < 0) rb_sys_fail(0);
5032  } else {
5033  if (gid == 0) {
5034  if (setegid(gid) < 0) rb_sys_fail(0);
5035  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5036  SAVED_GROUP_ID = 0;
5037  if (setrgid(0) < 0) rb_sys_fail(0);
5038  } else {
5039  if (setrgid(0) < 0) rb_sys_fail(0);
5040  SAVED_GROUP_ID = 0;
5041  if (setegid(gid) < 0) rb_sys_fail(0);
5042  if (setrgid(gid) < 0) rb_sys_fail(0);
5043  SAVED_GROUP_ID = gid;
5044  }
5045  }
5046  } else {
5047  if (setegid(gid) < 0) rb_sys_fail(0);
5048  if (setrgid(gid) < 0) rb_sys_fail(0);
5049  SAVED_GROUP_ID = gid;
5050  }
5051 #else
5052  rb_notimplement();
5053 #endif
5054  } else { /* unprivileged user */
5055 #if defined(HAVE_SETRESGID)
5056  if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
5057  (getegid() == gid)? (rb_gid_t)-1: gid,
5058  (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
5059  SAVED_GROUP_ID = gid;
5060 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5061  if (SAVED_GROUP_ID == gid) {
5062  if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
5063  (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5064  rb_sys_fail(0);
5065  } else if (getgid() != gid) {
5066  if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5067  rb_sys_fail(0);
5068  SAVED_GROUP_ID = gid;
5069  } else if (/* getgid() == gid && */ getegid() != gid) {
5070  if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
5071  SAVED_GROUP_ID = gid;
5072  if (setregid(gid, -1) < 0) rb_sys_fail(0);
5073  } else { /* getgid() == gid && getegid() == gid */
5074  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5075  if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
5076  SAVED_GROUP_ID = gid;
5077  if (setregid(gid, -1) < 0) rb_sys_fail(0);
5078  }
5079 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
5080  if (SAVED_GROUP_ID == gid) {
5081  if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
5082  if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
5083  } else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
5084  if (getgid() != gid) {
5085  if (setrgid(gid) < 0) rb_sys_fail(0);
5086  SAVED_GROUP_ID = gid;
5087  } else {
5088  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5089  SAVED_GROUP_ID = gid;
5090  if (setrgid(gid) < 0) rb_sys_fail(0);
5091  }
5092  } else if (/* getegid() != gid && */ getgid() == gid) {
5093  if (setegid(gid) < 0) rb_sys_fail(0);
5094  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5095  SAVED_GROUP_ID = gid;
5096  if (setrgid(gid) < 0) rb_sys_fail(0);
5097  } else {
5098  errno = EPERM;
5099  rb_sys_fail(0);
5100  }
5101 #elif defined HAVE_44BSD_SETGID
5102  if (getgid() == gid) {
5103  /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
5104  if (setgid(gid) < 0) rb_sys_fail(0);
5105  SAVED_GROUP_ID = gid;
5106  } else {
5107  errno = EPERM;
5108  rb_sys_fail(0);
5109  }
5110 #elif defined HAVE_SETEGID
5111  if (getgid() == gid && SAVED_GROUP_ID == gid) {
5112  if (setegid(gid) < 0) rb_sys_fail(0);
5113  } else {
5114  errno = EPERM;
5115  rb_sys_fail(0);
5116  }
5117 #elif defined HAVE_SETGID
5118  if (getgid() == gid && SAVED_GROUP_ID == gid) {
5119  if (setgid(gid) < 0) rb_sys_fail(0);
5120  } else {
5121  errno = EPERM;
5122  rb_sys_fail(0);
5123  }
5124 #else
5125  rb_notimplement();
5126 #endif
5127  }
5128  return id;
5129 }
5130 
5131 
5132 /*
5133  * call-seq:
5134  * Process.euid -> fixnum
5135  * Process::UID.eid -> fixnum
5136  * Process::Sys.geteuid -> fixnum
5137  *
5138  * Returns the effective user ID for this process.
5139  *
5140  * Process.euid #=> 501
5141  */
5142 
5143 static VALUE
5145 {
5146  rb_uid_t euid = geteuid();
5147  return UIDT2NUM(euid);
5148 }
5149 
5150 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
5151 /*
5152  * call-seq:
5153  * Process.euid= integer
5154  *
5155  * Sets the effective user ID for this process. Not available on all
5156  * platforms.
5157  */
5158 
5159 static VALUE
5160 proc_seteuid(VALUE obj, VALUE euid)
5161 {
5162  rb_uid_t uid;
5163 
5164  check_uid_switch();
5165 
5166  uid = NUM2UIDT(euid);
5167 #if defined(HAVE_SETRESUID)
5168  if (setresuid(-1, uid, -1) < 0) rb_sys_fail(0);
5169 #elif defined HAVE_SETREUID
5170  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
5171 #elif defined HAVE_SETEUID
5172  if (seteuid(uid) < 0) rb_sys_fail(0);
5173 #elif defined HAVE_SETUID
5174  if (uid == getuid()) {
5175  if (setuid(uid) < 0) rb_sys_fail(0);
5176  }
5177  else {
5178  rb_notimplement();
5179  }
5180 #else
5181  rb_notimplement();
5182 #endif
5183  return euid;
5184 }
5185 #endif
5186 
5187 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
5188 #define proc_seteuid_m proc_seteuid
5189 #else
5190 #define proc_seteuid_m rb_f_notimplement
5191 #endif
5192 
5193 static rb_uid_t
5194 rb_seteuid_core(rb_uid_t euid)
5195 {
5196  rb_uid_t uid;
5197 
5198  check_uid_switch();
5199 
5200  uid = getuid();
5201 
5202 #if defined(HAVE_SETRESUID)
5203  if (uid != euid) {
5204  if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
5205  SAVED_USER_ID = euid;
5206  } else {
5207  if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
5208  }
5209 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5210  if (setreuid(-1, euid) < 0) rb_sys_fail(0);
5211  if (uid != euid) {
5212  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
5213  if (setreuid(uid,euid) < 0) rb_sys_fail(0);
5214  SAVED_USER_ID = euid;
5215  }
5216 #elif defined HAVE_SETEUID
5217  if (seteuid(euid) < 0) rb_sys_fail(0);
5218 #elif defined HAVE_SETUID
5219  if (geteuid() == 0) rb_sys_fail(0);
5220  if (setuid(euid) < 0) rb_sys_fail(0);
5221 #else
5222  rb_notimplement();
5223 #endif
5224  return euid;
5225 }
5226 
5227 
5228 /*
5229  * call-seq:
5230  * Process::UID.grant_privilege(integer) -> fixnum
5231  * Process::UID.eid= integer -> fixnum
5232  *
5233  * Set the effective user ID, and if possible, the saved user ID of
5234  * the process to the given _integer_. Returns the new
5235  * effective user ID. Not available on all platforms.
5236  *
5237  * [Process.uid, Process.euid] #=> [0, 0]
5238  * Process::UID.grant_privilege(31) #=> 31
5239  * [Process.uid, Process.euid] #=> [0, 31]
5240  */
5241 
5242 static VALUE
5244 {
5246  return id;
5247 }
5248 
5249 
5250 /*
5251  * call-seq:
5252  * Process.egid -> fixnum
5253  * Process::GID.eid -> fixnum
5254  * Process::Sys.geteid -> fixnum
5255  *
5256  * Returns the effective group ID for this process. Not available on
5257  * all platforms.
5258  *
5259  * Process.egid #=> 500
5260  */
5261 
5262 static VALUE
5264 {
5265  rb_gid_t egid = getegid();
5266 
5267  return GIDT2NUM(egid);
5268 }
5269 
5270 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
5271 /*
5272  * call-seq:
5273  * Process.egid = fixnum -> fixnum
5274  *
5275  * Sets the effective group ID for this process. Not available on all
5276  * platforms.
5277  */
5278 
5279 static VALUE
5280 proc_setegid(VALUE obj, VALUE egid)
5281 {
5282  rb_gid_t gid;
5283 
5284  check_gid_switch();
5285 
5286  gid = NUM2GIDT(egid);
5287 #if defined(HAVE_SETRESGID)
5288  if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
5289 #elif defined HAVE_SETREGID
5290  if (setregid(-1, gid) < 0) rb_sys_fail(0);
5291 #elif defined HAVE_SETEGID
5292  if (setegid(gid) < 0) rb_sys_fail(0);
5293 #elif defined HAVE_SETGID
5294  if (gid == getgid()) {
5295  if (setgid(gid) < 0) rb_sys_fail(0);
5296  }
5297  else {
5298  rb_notimplement();
5299  }
5300 #else
5301  rb_notimplement();
5302 #endif
5303  return egid;
5304 }
5305 #endif
5306 
5307 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
5308 #define proc_setegid_m proc_setegid
5309 #else
5310 #define proc_setegid_m rb_f_notimplement
5311 #endif
5312 
5313 static rb_gid_t
5314 rb_setegid_core(rb_gid_t egid)
5315 {
5316  rb_gid_t gid;
5317 
5318  check_gid_switch();
5319 
5320  gid = getgid();
5321 
5322 #if defined(HAVE_SETRESGID)
5323  if (gid != egid) {
5324  if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
5325  SAVED_GROUP_ID = egid;
5326  } else {
5327  if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
5328  }
5329 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5330  if (setregid(-1, egid) < 0) rb_sys_fail(0);
5331  if (gid != egid) {
5332  if (setregid(egid,gid) < 0) rb_sys_fail(0);
5333  if (setregid(gid,egid) < 0) rb_sys_fail(0);
5334  SAVED_GROUP_ID = egid;
5335  }
5336 #elif defined HAVE_SETEGID
5337  if (setegid(egid) < 0) rb_sys_fail(0);
5338 #elif defined HAVE_SETGID
5339  if (geteuid() == 0 /* root user */) rb_sys_fail(0);
5340  if (setgid(egid) < 0) rb_sys_fail(0);
5341 #else
5342  rb_notimplement();
5343 #endif
5344  return egid;
5345 }
5346 
5347 
5348 /*
5349  * call-seq:
5350  * Process::GID.grant_privilege(integer) -> fixnum
5351  * Process::GID.eid = integer -> fixnum
5352  *
5353  * Set the effective group ID, and if possible, the saved group ID of
5354  * the process to the given _integer_. Returns the new
5355  * effective group ID. Not available on all platforms.
5356  *
5357  * [Process.gid, Process.egid] #=> [0, 0]
5358  * Process::GID.grant_privilege(31) #=> 33
5359  * [Process.gid, Process.egid] #=> [0, 33]
5360  */
5361 
5362 static VALUE
5364 {
5366  return id;
5367 }
5368 
5369 
5370 /*
5371  * call-seq:
5372  * Process::UID.re_exchangeable? -> true or false
5373  *
5374  * Returns +true+ if the real and effective user IDs of a
5375  * process may be exchanged on the current platform.
5376  *
5377  */
5378 
5379 static VALUE
5381 {
5382 #if defined(HAVE_SETRESUID)
5383  return Qtrue;
5384 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5385  return Qtrue;
5386 #else
5387  return Qfalse;
5388 #endif
5389 }
5390 
5391 
5392 /*
5393  * call-seq:
5394  * Process::UID.re_exchange -> fixnum
5395  *
5396  * Exchange real and effective user IDs and return the new effective
5397  * user ID. Not available on all platforms.
5398  *
5399  * [Process.uid, Process.euid] #=> [0, 31]
5400  * Process::UID.re_exchange #=> 0
5401  * [Process.uid, Process.euid] #=> [31, 0]
5402  */
5403 
5404 static VALUE
5406 {
5407  rb_uid_t uid, euid;
5408 
5409  check_uid_switch();
5410 
5411  uid = getuid();
5412  euid = geteuid();
5413 
5414 #if defined(HAVE_SETRESUID)
5415  if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
5416  SAVED_USER_ID = uid;
5417 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5418  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
5419  SAVED_USER_ID = uid;
5420 #else
5421  rb_notimplement();
5422 #endif
5423  return UIDT2NUM(uid);
5424 }
5425 
5426 
5427 /*
5428  * call-seq:
5429  * Process::GID.re_exchangeable? -> true or false
5430  *
5431  * Returns +true+ if the real and effective group IDs of a
5432  * process may be exchanged on the current platform.
5433  *
5434  */
5435 
5436 static VALUE
5438 {
5439 #if defined(HAVE_SETRESGID)
5440  return Qtrue;
5441 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5442  return Qtrue;
5443 #else
5444  return Qfalse;
5445 #endif
5446 }
5447 
5448 
5449 /*
5450  * call-seq:
5451  * Process::GID.re_exchange -> fixnum
5452  *
5453  * Exchange real and effective group IDs and return the new effective
5454  * group ID. Not available on all platforms.
5455  *
5456  * [Process.gid, Process.egid] #=> [0, 33]
5457  * Process::GID.re_exchange #=> 0
5458  * [Process.gid, Process.egid] #=> [33, 0]
5459  */
5460 
5461 static VALUE
5463 {
5464  rb_gid_t gid, egid;
5465 
5466  check_gid_switch();
5467 
5468  gid = getgid();
5469  egid = getegid();
5470 
5471 #if defined(HAVE_SETRESGID)
5472  if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
5473  SAVED_GROUP_ID = gid;
5474 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5475  if (setregid(egid,gid) < 0) rb_sys_fail(0);
5476  SAVED_GROUP_ID = gid;
5477 #else
5478  rb_notimplement();
5479 #endif
5480  return GIDT2NUM(gid);
5481 }
5482 
5483 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
5484 
5485 /*
5486  * call-seq:
5487  * Process::UID.sid_available? -> true or false
5488  *
5489  * Returns +true+ if the current platform has saved user
5490  * ID functionality.
5491  *
5492  */
5493 
5494 static VALUE
5496 {
5497 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
5498  return Qtrue;
5499 #else
5500  return Qfalse;
5501 #endif
5502 }
5503 
5504 
5505 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
5506 static VALUE
5507 p_uid_sw_ensure(rb_uid_t id)
5508 {
5509  under_uid_switch = 0;
5510  id = rb_seteuid_core(id);
5511  return UIDT2NUM(id);
5512 }
5513 
5514 
5515 /*
5516  * call-seq:
5517  * Process::UID.switch -> fixnum
5518  * Process::UID.switch {|| block} -> object
5519  *
5520  * Switch the effective and real user IDs of the current process. If
5521  * a <em>block</em> is given, the user IDs will be switched back
5522  * after the block is executed. Returns the new effective user ID if
5523  * called without a block, and the return value of the block if one
5524  * is given.
5525  *
5526  */
5527 
5528 static VALUE
5529 p_uid_switch(VALUE obj)
5530 {
5531  rb_uid_t uid, euid;
5532 
5533  check_uid_switch();
5534 
5535  uid = getuid();
5536  euid = geteuid();
5537 
5538  if (uid != euid) {
5539  proc_seteuid(obj, UIDT2NUM(uid));
5540  if (rb_block_given_p()) {
5541  under_uid_switch = 1;
5542  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
5543  } else {
5544  return UIDT2NUM(euid);
5545  }
5546  } else if (euid != SAVED_USER_ID) {
5547  proc_seteuid(obj, UIDT2NUM(SAVED_USER_ID));
5548  if (rb_block_given_p()) {
5549  under_uid_switch = 1;
5550  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
5551  } else {
5552  return UIDT2NUM(uid);
5553  }
5554  } else {
5555  errno = EPERM;
5556  rb_sys_fail(0);
5557  }
5558 }
5559 #else
5560 static VALUE
5562 {
5563  under_uid_switch = 0;
5564  return p_uid_exchange(obj);
5565 }
5566 
5567 static VALUE
5569 {
5570  rb_uid_t uid, euid;
5571 
5572  check_uid_switch();
5573 
5574  uid = getuid();
5575  euid = geteuid();
5576 
5577  if (uid == euid) {
5578  errno = EPERM;
5579  rb_sys_fail(0);
5580  }
5581  p_uid_exchange(obj);
5582  if (rb_block_given_p()) {
5583  under_uid_switch = 1;
5584  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
5585  } else {
5586  return UIDT2NUM(euid);
5587  }
5588 }
5589 #endif
5590 
5591 
5592 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
5593 
5594 /*
5595  * call-seq:
5596  * Process::GID.sid_available? -> true or false
5597  *
5598  * Returns +true+ if the current platform has saved group
5599  * ID functionality.
5600  *
5601  */
5602 
5603 static VALUE
5605 {
5606 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
5607  return Qtrue;
5608 #else
5609  return Qfalse;
5610 #endif
5611 }
5612 
5613 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
5614 static VALUE
5615 p_gid_sw_ensure(rb_gid_t id)
5616 {
5617  under_gid_switch = 0;
5618  id = rb_setegid_core(id);
5619  return GIDT2NUM(id);
5620 }
5621 
5622 
5623 /*
5624  * call-seq:
5625  * Process::GID.switch -> fixnum
5626  * Process::GID.switch {|| block} -> object
5627  *
5628  * Switch the effective and real group IDs of the current process. If
5629  * a <em>block</em> is given, the group IDs will be switched back
5630  * after the block is executed. Returns the new effective group ID if
5631  * called without a block, and the return value of the block if one
5632  * is given.
5633  *
5634  */
5635 
5636 static VALUE
5637 p_gid_switch(VALUE obj)
5638 {
5639  rb_gid_t gid, egid;
5640 
5641  check_gid_switch();
5642 
5643  gid = getgid();
5644  egid = getegid();
5645 
5646  if (gid != egid) {
5647  proc_setegid(obj, GIDT2NUM(gid));
5648  if (rb_block_given_p()) {
5649  under_gid_switch = 1;
5650  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
5651  } else {
5652  return GIDT2NUM(egid);
5653  }
5654  }
5655  else if (egid != SAVED_GROUP_ID) {
5656  proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
5657  if (rb_block_given_p()) {
5658  under_gid_switch = 1;
5659  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
5660  } else {
5661  return GIDT2NUM(gid);
5662  }
5663  }
5664  else {
5665  errno = EPERM;
5666  rb_sys_fail(0);
5667  }
5668 }
5669 #else
5670 static VALUE
5672 {
5673  under_gid_switch = 0;
5674  return p_gid_exchange(obj);
5675 }
5676 
5677 static VALUE
5679 {
5680  rb_gid_t gid, egid;
5681 
5682  check_gid_switch();
5683 
5684  gid = getgid();
5685  egid = getegid();
5686 
5687  if (gid == egid) {
5688  errno = EPERM;
5689  rb_sys_fail(0);
5690  }
5691  p_gid_exchange(obj);
5692  if (rb_block_given_p()) {
5693  under_gid_switch = 1;
5694  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
5695  } else {
5696  return GIDT2NUM(egid);
5697  }
5698 }
5699 #endif
5700 
5701 
5702 #if defined(HAVE_TIMES)
5703 /*
5704  * call-seq:
5705  * Process.times -> aStructTms
5706  *
5707  * Returns a <code>Tms</code> structure (see <code>Struct::Tms</code>)
5708  * that contains user and system CPU times for this process,
5709  * and also for children processes.
5710  *
5711  * t = Process.times
5712  * [ t.utime, t.stime, t.cutime, t.cstime ] #=> [0.0, 0.02, 0.00, 0.00]
5713  */
5714 
5715 VALUE
5716 rb_proc_times(VALUE obj)
5717 {
5718  const double hertz =
5719 #ifdef HAVE__SC_CLK_TCK
5720  (double)sysconf(_SC_CLK_TCK);
5721 #else
5722 #ifndef HZ
5723 # ifdef CLK_TCK
5724 # define HZ CLK_TCK
5725 # else
5726 # define HZ 60
5727 # endif
5728 #endif /* HZ */
5729  HZ;
5730 #endif
5731  struct tms buf;
5732  volatile VALUE utime, stime, cutime, sctime;
5733 
5734  times(&buf);
5735  return rb_struct_new(rb_cProcessTms,
5736  utime = DBL2NUM(buf.tms_utime / hertz),
5737  stime = DBL2NUM(buf.tms_stime / hertz),
5738  cutime = DBL2NUM(buf.tms_cutime / hertz),
5739  sctime = DBL2NUM(buf.tms_cstime / hertz));
5740 }
5741 #else
5742 #define rb_proc_times rb_f_notimplement
5743 #endif
5744 
5749 
5750 
5751 /*
5752  * The <code>Process</code> module is a collection of methods used to
5753  * manipulate processes.
5754  */
5755 
5756 void
5758 {
5761  rb_define_global_function("exec", rb_f_exec, -1);
5764  rb_define_global_function("system", rb_f_system, -1);
5765  rb_define_global_function("spawn", rb_f_spawn, -1);
5766  rb_define_global_function("sleep", rb_f_sleep, -1);
5767  rb_define_global_function("exit", rb_f_exit, -1);
5768  rb_define_global_function("abort", rb_f_abort, -1);
5769 
5770  rb_mProcess = rb_define_module("Process");
5771 
5772 #ifdef WNOHANG
5773  /* see Process.wait */
5774  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
5775 #else
5776  /* see Process.wait */
5777  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
5778 #endif
5779 #ifdef WUNTRACED
5780  /* see Process.wait */
5781  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
5782 #else
5783  /* see Process.wait */
5784  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
5785 #endif
5786 
5787  rb_define_singleton_method(rb_mProcess, "exec", rb_f_exec, -1);
5788  rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
5789  rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
5790  rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
5791  rb_define_singleton_method(rb_mProcess, "exit", rb_f_exit, -1);
5792  rb_define_singleton_method(rb_mProcess, "abort", rb_f_abort, -1);
5793 
5794  rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1); /* in signal.c */
5795  rb_define_module_function(rb_mProcess, "wait", proc_wait, -1);
5796  rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
5797  rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
5798  rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
5799  rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
5800  rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
5801 
5802  rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
5804 
5811 
5813 
5822 
5823  rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
5824  rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
5825 
5826  rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, 0);
5827  rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, 0);
5828  rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
5829  rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
5830 
5831  rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
5832 
5833  rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
5834  rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
5835 
5836 #ifdef HAVE_GETPRIORITY
5837  /* see Process.setpriority */
5838  rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
5839  /* see Process.setpriority */
5840  rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
5841  /* see Process.setpriority */
5842  rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
5843 #endif
5844 
5845  rb_define_module_function(rb_mProcess, "getrlimit", proc_getrlimit, 1);
5846  rb_define_module_function(rb_mProcess, "setrlimit", proc_setrlimit, -1);
5847 #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
5848  {
5849  VALUE inf = RLIM2NUM(RLIM_INFINITY);
5850 #ifdef RLIM_SAVED_MAX
5851  {
5852  VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
5853  /* see Process.setrlimit */
5854  rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
5855  }
5856 #endif
5857  /* see Process.setrlimit */
5858  rb_define_const(rb_mProcess, "RLIM_INFINITY", inf);
5859 #ifdef RLIM_SAVED_CUR
5860  {
5861  VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
5862  /* see Process.setrlimit */
5863  rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
5864  }
5865 #endif
5866  }
5867 #ifdef RLIMIT_AS
5868  /* Maximum size of the process's virtual memory (address space) in bytes.
5869  *
5870  * see the system getrlimit(2) manual for details.
5871  */
5872  rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
5873 #endif
5874 #ifdef RLIMIT_CORE
5875  /* Maximum size of the core file.
5876  *
5877  * see the system getrlimit(2) manual for details.
5878  */
5879  rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
5880 #endif
5881 #ifdef RLIMIT_CPU
5882  /* CPU time limit in seconds.
5883  *
5884  * see the system getrlimit(2) manual for details.
5885  */
5886  rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
5887 #endif
5888 #ifdef RLIMIT_DATA
5889  /* Maximum size of the process's data segment.
5890  *
5891  * see the system getrlimit(2) manual for details.
5892  */
5893  rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
5894 #endif
5895 #ifdef RLIMIT_FSIZE
5896  /* Maximum size of files that the process may create.
5897  *
5898  * see the system getrlimit(2) manual for details.
5899  */
5900  rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
5901 #endif
5902 #ifdef RLIMIT_MEMLOCK
5903  /* Maximum number of bytes of memory that may be locked into RAM.
5904  *
5905  * see the system getrlimit(2) manual for details.
5906  */
5907  rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
5908 #endif
5909 #ifdef RLIMIT_MSGQUEUE
5910  /* Specifies the limit on the number of bytes that can be allocated
5911  * for POSIX message queues for the real user ID of the calling process.
5912  *
5913  * see the system getrlimit(2) manual for details.
5914  */
5915  rb_define_const(rb_mProcess, "RLIMIT_MSGQUEUE", INT2FIX(RLIMIT_MSGQUEUE));
5916 #endif
5917 #ifdef RLIMIT_NICE
5918  /* Specifies a ceiling to which the process's nice value can be raised.
5919  *
5920  * see the system getrlimit(2) manual for details.
5921  */
5922  rb_define_const(rb_mProcess, "RLIMIT_NICE", INT2FIX(RLIMIT_NICE));
5923 #endif
5924 #ifdef RLIMIT_NOFILE
5925  /* Specifies a value one greater than the maximum file descriptor
5926  * number that can be opened by this process.
5927  *
5928  * see the system getrlimit(2) manual for details.
5929  */
5930  rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
5931 #endif
5932 #ifdef RLIMIT_NPROC
5933  /* The maximum number of processes that can be created for the
5934  * real user ID of the calling process.
5935  *
5936  * see the system getrlimit(2) manual for details.
5937  */
5938  rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
5939 #endif
5940 #ifdef RLIMIT_RSS
5941  /* Specifies the limit (in pages) of the process's resident set.
5942  *
5943  * see the system getrlimit(2) manual for details.
5944  */
5945  rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
5946 #endif
5947 #ifdef RLIMIT_RTPRIO
5948  /* Specifies a ceiling on the real-time priority that may be set for this process.
5949  *
5950  * see the system getrlimit(2) manual for details.
5951  */
5952  rb_define_const(rb_mProcess, "RLIMIT_RTPRIO", INT2FIX(RLIMIT_RTPRIO));
5953 #endif
5954 #ifdef RLIMIT_RTTIME
5955  /* Specifies limit on CPU time this process scheduled under a real-time
5956  * scheduling policy can consume.
5957  *
5958  * see the system getrlimit(2) manual for details.
5959  */
5960  rb_define_const(rb_mProcess, "RLIMIT_RTTIME", INT2FIX(RLIMIT_RTTIME));
5961 #endif
5962 #ifdef RLIMIT_SBSIZE
5963  /* Maximum size of the socket buffer.
5964  */
5965  rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
5966 #endif
5967 #ifdef RLIMIT_SIGPENDING
5968  /* Specifies a limit on the number of signals that may be queued for
5969  * the real user ID of the calling process.
5970  *
5971  * see the system getrlimit(2) manual for details.
5972  */
5973  rb_define_const(rb_mProcess, "RLIMIT_SIGPENDING", INT2FIX(RLIMIT_SIGPENDING));
5974 #endif
5975 #ifdef RLIMIT_STACK
5976  /* Maximum size of the stack, in bytes.
5977  *
5978  * see the system getrlimit(2) manual for details.
5979  */
5980  rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
5981 #endif
5982 #endif
5983 
5984  rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
5985  rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
5986  rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
5987  rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
5988  rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
5989  rb_define_module_function(rb_mProcess, "euid=", proc_seteuid_m, 1);
5990  rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
5991  rb_define_module_function(rb_mProcess, "egid=", proc_setegid_m, 1);
5992  rb_define_module_function(rb_mProcess, "initgroups", proc_initgroups, 2);
5993  rb_define_module_function(rb_mProcess, "groups", proc_getgroups, 0);
5994  rb_define_module_function(rb_mProcess, "groups=", proc_setgroups, 1);
5995  rb_define_module_function(rb_mProcess, "maxgroups", proc_getmaxgroups, 0);
5996  rb_define_module_function(rb_mProcess, "maxgroups=", proc_setmaxgroups, 1);
5997 
5998  rb_define_module_function(rb_mProcess, "daemon", proc_daemon, -1);
5999 
6000  rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
6001 
6002 #if defined(HAVE_TIMES) || defined(_WIN32)
6003  rb_cProcessTms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", NULL);
6004 #endif
6005 
6006  SAVED_USER_ID = geteuid();
6007  SAVED_GROUP_ID = getegid();
6008 
6009  rb_mProcUID = rb_define_module_under(rb_mProcess, "UID");
6010  rb_mProcGID = rb_define_module_under(rb_mProcess, "GID");
6011 
6012  rb_define_module_function(rb_mProcUID, "rid", proc_getuid, 0);
6013  rb_define_module_function(rb_mProcGID, "rid", proc_getgid, 0);
6014  rb_define_module_function(rb_mProcUID, "eid", proc_geteuid, 0);
6015  rb_define_module_function(rb_mProcGID, "eid", proc_getegid, 0);
6016  rb_define_module_function(rb_mProcUID, "change_privilege", p_uid_change_privilege, 1);
6017  rb_define_module_function(rb_mProcGID, "change_privilege", p_gid_change_privilege, 1);
6018  rb_define_module_function(rb_mProcUID, "grant_privilege", p_uid_grant_privilege, 1);
6019  rb_define_module_function(rb_mProcGID, "grant_privilege", p_gid_grant_privilege, 1);
6020  rb_define_alias(rb_singleton_class(rb_mProcUID), "eid=", "grant_privilege");
6021  rb_define_alias(rb_singleton_class(rb_mProcGID), "eid=", "grant_privilege");
6022  rb_define_module_function(rb_mProcUID, "re_exchange", p_uid_exchange, 0);
6023  rb_define_module_function(rb_mProcGID, "re_exchange", p_gid_exchange, 0);
6024  rb_define_module_function(rb_mProcUID, "re_exchangeable?", p_uid_exchangeable, 0);
6025  rb_define_module_function(rb_mProcGID, "re_exchangeable?", p_gid_exchangeable, 0);
6026  rb_define_module_function(rb_mProcUID, "sid_available?", p_uid_have_saved_id, 0);
6027  rb_define_module_function(rb_mProcGID, "sid_available?", p_gid_have_saved_id, 0);
6028  rb_define_module_function(rb_mProcUID, "switch", p_uid_switch, 0);
6029  rb_define_module_function(rb_mProcGID, "switch", p_gid_switch, 0);
6030 
6031  rb_mProcID_Syscall = rb_define_module_under(rb_mProcess, "Sys");
6032 
6033  rb_define_module_function(rb_mProcID_Syscall, "getuid", proc_getuid, 0);
6034  rb_define_module_function(rb_mProcID_Syscall, "geteuid", proc_geteuid, 0);
6035  rb_define_module_function(rb_mProcID_Syscall, "getgid", proc_getgid, 0);
6036  rb_define_module_function(rb_mProcID_Syscall, "getegid", proc_getegid, 0);
6037 
6038  rb_define_module_function(rb_mProcID_Syscall, "setuid", p_sys_setuid, 1);
6039  rb_define_module_function(rb_mProcID_Syscall, "setgid", p_sys_setgid, 1);
6040 
6041  rb_define_module_function(rb_mProcID_Syscall, "setruid", p_sys_setruid, 1);
6042  rb_define_module_function(rb_mProcID_Syscall, "setrgid", p_sys_setrgid, 1);
6043 
6044  rb_define_module_function(rb_mProcID_Syscall, "seteuid", p_sys_seteuid, 1);
6045  rb_define_module_function(rb_mProcID_Syscall, "setegid", p_sys_setegid, 1);
6046 
6047  rb_define_module_function(rb_mProcID_Syscall, "setreuid", p_sys_setreuid, 2);
6048  rb_define_module_function(rb_mProcID_Syscall, "setregid", p_sys_setregid, 2);
6049 
6050  rb_define_module_function(rb_mProcID_Syscall, "setresuid", p_sys_setresuid, 3);
6051  rb_define_module_function(rb_mProcID_Syscall, "setresgid", p_sys_setresgid, 3);
6052  rb_define_module_function(rb_mProcID_Syscall, "issetugid", p_sys_issetugid, 0);
6053 }
6054