Ruby  1.9.3p551(2014-11-13revision48407)
process.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  process.c -
4 
5  $Author: usa $
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 #else
1953 #define redirect_dup(oldfd) dup(oldfd)
1954 #endif
1955 
1956 #if defined(DEBUG_REDIRECT) || defined(_WIN32)
1957 static int
1958 redirect_dup2(int oldfd, int newfd)
1959 {
1960  int ret;
1961  ret = dup2(oldfd, newfd);
1962  if (newfd >= 0 && newfd <= 2)
1963  SetStdHandle(newfd == 0 ? STD_INPUT_HANDLE : newfd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, (HANDLE)rb_w32_get_osfhandle(newfd));
1964 #if defined(DEBUG_REDIRECT)
1965  ttyprintf("dup2(%d, %d)\n", oldfd, newfd);
1966 #endif
1967  return ret;
1968 }
1969 #else
1970 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
1971 #endif
1972 
1973 #if defined(DEBUG_REDIRECT)
1974 static int
1975 redirect_close(int fd)
1976 {
1977  int ret;
1978  ret = close(fd);
1979  ttyprintf("close(%d)\n", fd);
1980  return ret;
1981 }
1982 
1983 static int
1984 redirect_open(const char *pathname, int flags, mode_t perm)
1985 {
1986  int ret;
1987  ret = open(pathname, flags, perm);
1988  ttyprintf("open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
1989  return ret;
1990 }
1991 
1992 #else
1993 #define redirect_close(fd) close(fd)
1994 #define redirect_open(pathname, flags, perm) open((pathname), (flags), (perm))
1995 #endif
1996 
1997 static int
1998 save_redirect_fd(int fd, VALUE save, char *errmsg, size_t errmsg_buflen)
1999 {
2000  if (!NIL_P(save)) {
2001  VALUE newary;
2002  int save_fd = redirect_dup(fd);
2003  if (save_fd == -1) {
2004  if (errno == EBADF)
2005  return 0;
2006  ERRMSG("dup");
2007  return -1;
2008  }
2009  rb_update_max_fd(save_fd);
2010  newary = rb_ary_entry(save, EXEC_OPTION_DUP2);
2011  if (NIL_P(newary)) {
2012  newary = hide_obj(rb_ary_new());
2013  rb_ary_store(save, EXEC_OPTION_DUP2, newary);
2014  }
2015  rb_ary_push(newary,
2016  hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd))));
2017 
2018  newary = rb_ary_entry(save, EXEC_OPTION_CLOSE);
2019  if (NIL_P(newary)) {
2020  newary = hide_obj(rb_ary_new());
2021  rb_ary_store(save, EXEC_OPTION_CLOSE, newary);
2022  }
2023  rb_ary_push(newary, hide_obj(rb_assoc_new(INT2FIX(save_fd), Qnil)));
2024  }
2025 
2026  return 0;
2027 }
2028 
2029 static VALUE
2030 save_env_i(VALUE i, VALUE ary, int argc, VALUE *argv)
2031 {
2032  rb_ary_push(ary, hide_obj(rb_ary_dup(argv[0])));
2033  return Qnil;
2034 }
2035 
2036 static void
2038 {
2039  if (!NIL_P(save) && NIL_P(rb_ary_entry(save, EXEC_OPTION_ENV))) {
2041  if (RTEST(env)) {
2042  VALUE ary = hide_obj(rb_ary_new());
2043  rb_block_call(env, rb_intern("each"), 0, 0, save_env_i,
2044  (VALUE)ary);
2045  rb_ary_store(save, EXEC_OPTION_ENV, ary);
2046  }
2048  }
2049 }
2050 
2051 static int
2052 intcmp(const void *a, const void *b)
2053 {
2054  return *(int*)a - *(int*)b;
2055 }
2056 
2057 static int
2058 intrcmp(const void *a, const void *b)
2059 {
2060  return *(int*)b - *(int*)a;
2061 }
2062 
2063 static int
2064 run_exec_dup2(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
2065 {
2066  long n, i;
2067  int ret;
2068  int extra_fd = -1;
2069  struct fd_pair {
2070  int oldfd;
2071  int newfd;
2072  long older_index;
2073  long num_newer;
2074  } *pairs = 0;
2075 
2076  n = RARRAY_LEN(ary);
2077  pairs = (struct fd_pair *)malloc(sizeof(struct fd_pair) * n);
2078  if (pairs == NULL) {
2079  ERRMSG("malloc");
2080  return -1;
2081  }
2082 
2083  /* initialize oldfd and newfd: O(n) */
2084  for (i = 0; i < n; i++) {
2085  VALUE elt = RARRAY_PTR(ary)[i];
2086  pairs[i].oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
2087  pairs[i].newfd = FIX2INT(RARRAY_PTR(elt)[0]); /* unique */
2088  pairs[i].older_index = -1;
2089  }
2090 
2091  /* sort the table by oldfd: O(n log n) */
2092  if (!RTEST(save))
2093  qsort(pairs, n, sizeof(struct fd_pair), intcmp);
2094  else
2095  qsort(pairs, n, sizeof(struct fd_pair), intrcmp);
2096 
2097  /* initialize older_index and num_newer: O(n log n) */
2098  for (i = 0; i < n; i++) {
2099  int newfd = pairs[i].newfd;
2100  struct fd_pair key, *found;
2101  key.oldfd = newfd;
2102  found = bsearch(&key, pairs, n, sizeof(struct fd_pair), intcmp);
2103  pairs[i].num_newer = 0;
2104  if (found) {
2105  while (pairs < found && (found-1)->oldfd == newfd)
2106  found--;
2107  while (found < pairs+n && found->oldfd == newfd) {
2108  pairs[i].num_newer++;
2109  found->older_index = i;
2110  found++;
2111  }
2112  }
2113  }
2114 
2115  /* non-cyclic redirection: O(n) */
2116  for (i = 0; i < n; i++) {
2117  long j = i;
2118  while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
2119  if (save_redirect_fd(pairs[j].newfd, save, errmsg, errmsg_buflen) < 0)
2120  goto fail;
2121  ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
2122  if (ret == -1) {
2123  ERRMSG("dup2");
2124  goto fail;
2125  }
2126  rb_update_max_fd(pairs[j].newfd);
2127  pairs[j].oldfd = -1;
2128  j = pairs[j].older_index;
2129  if (j != -1)
2130  pairs[j].num_newer--;
2131  }
2132  }
2133 
2134  /* cyclic redirection: O(n) */
2135  for (i = 0; i < n; i++) {
2136  long j;
2137  if (pairs[i].oldfd == -1)
2138  continue;
2139  if (pairs[i].oldfd == pairs[i].newfd) { /* self cycle */
2140 #ifdef F_GETFD
2141  int fd = pairs[i].oldfd;
2142  ret = fcntl(fd, F_GETFD);
2143  if (ret == -1) {
2144  ERRMSG("fcntl(F_GETFD)");
2145  goto fail;
2146  }
2147  if (ret & FD_CLOEXEC) {
2148  ret &= ~FD_CLOEXEC;
2149  ret = fcntl(fd, F_SETFD, ret);
2150  if (ret == -1) {
2151  ERRMSG("fcntl(F_SETFD)");
2152  goto fail;
2153  }
2154  }
2155 #endif
2156  pairs[i].oldfd = -1;
2157  continue;
2158  }
2159  if (extra_fd == -1) {
2160  extra_fd = redirect_dup(pairs[i].oldfd);
2161  if (extra_fd == -1) {
2162  ERRMSG("dup");
2163  goto fail;
2164  }
2165  rb_update_max_fd(extra_fd);
2166  }
2167  else {
2168  ret = redirect_dup2(pairs[i].oldfd, extra_fd);
2169  if (ret == -1) {
2170  ERRMSG("dup2");
2171  goto fail;
2172  }
2173  rb_update_max_fd(extra_fd);
2174  }
2175  pairs[i].oldfd = extra_fd;
2176  j = pairs[i].older_index;
2177  pairs[i].older_index = -1;
2178  while (j != -1) {
2179  ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
2180  if (ret == -1) {
2181  ERRMSG("dup2");
2182  goto fail;
2183  }
2184  rb_update_max_fd(ret);
2185  pairs[j].oldfd = -1;
2186  j = pairs[j].older_index;
2187  }
2188  }
2189  if (extra_fd != -1) {
2190  ret = redirect_close(extra_fd);
2191  if (ret == -1) {
2192  ERRMSG("close");
2193  goto fail;
2194  }
2195  }
2196 
2197  xfree(pairs);
2198  return 0;
2199 
2200  fail:
2201  xfree(pairs);
2202  return -1;
2203 }
2204 
2205 static int
2206 run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
2207 {
2208  long i;
2209  int ret;
2210 
2211  for (i = 0; i < RARRAY_LEN(ary); i++) {
2212  VALUE elt = RARRAY_PTR(ary)[i];
2213  int fd = FIX2INT(RARRAY_PTR(elt)[0]);
2214  ret = redirect_close(fd);
2215  if (ret == -1) {
2216  ERRMSG("close");
2217  return -1;
2218  }
2219  }
2220  return 0;
2221 }
2222 
2223 static int
2224 run_exec_open(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
2225 {
2226  long i;
2227  int ret;
2228 
2229  for (i = 0; i < RARRAY_LEN(ary);) {
2230  VALUE elt = RARRAY_PTR(ary)[i];
2231  int fd = FIX2INT(RARRAY_PTR(elt)[0]);
2232  VALUE param = RARRAY_PTR(elt)[1];
2233  char *path = RSTRING_PTR(RARRAY_PTR(param)[0]);
2234  int flags = NUM2INT(RARRAY_PTR(param)[1]);
2235  int perm = NUM2INT(RARRAY_PTR(param)[2]);
2236  int need_close = 1;
2237  int fd2 = redirect_open(path, flags, perm);
2238  if (fd2 == -1) {
2239  ERRMSG("open");
2240  return -1;
2241  }
2242  rb_update_max_fd(fd2);
2243  while (i < RARRAY_LEN(ary) &&
2244  (elt = RARRAY_PTR(ary)[i], RARRAY_PTR(elt)[1] == param)) {
2245  fd = FIX2INT(RARRAY_PTR(elt)[0]);
2246  if (fd == fd2) {
2247  need_close = 0;
2248  }
2249  else {
2250  if (save_redirect_fd(fd, save, errmsg, errmsg_buflen) < 0)
2251  return -1;
2252  ret = redirect_dup2(fd2, fd);
2253  if (ret == -1) {
2254  ERRMSG("dup2");
2255  return -1;
2256  }
2257  rb_update_max_fd(fd);
2258  }
2259  i++;
2260  }
2261  if (need_close) {
2262  ret = redirect_close(fd2);
2263  if (ret == -1) {
2264  ERRMSG("close");
2265  return -1;
2266  }
2267  }
2268  }
2269  return 0;
2270 }
2271 
2272 static int
2273 run_exec_dup2_child(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
2274 {
2275  long i;
2276  int ret;
2277 
2278  for (i = 0; i < RARRAY_LEN(ary); i++) {
2279  VALUE elt = RARRAY_PTR(ary)[i];
2280  int newfd = FIX2INT(RARRAY_PTR(elt)[0]);
2281  int oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
2282 
2283  if (save_redirect_fd(newfd, save, errmsg, errmsg_buflen) < 0)
2284  return -1;
2285  ret = redirect_dup2(oldfd, newfd);
2286  if (ret == -1) {
2287  ERRMSG("dup2");
2288  return -1;
2289  }
2290  rb_update_max_fd(newfd);
2291  }
2292  return 0;
2293 }
2294 
2295 #ifdef HAVE_SETPGID
2296 static int
2297 run_exec_pgroup(VALUE obj, VALUE save, char *errmsg, size_t errmsg_buflen)
2298 {
2299  /*
2300  * If FD_CLOEXEC is available, rb_fork waits the child's execve.
2301  * So setpgid is done in the child when rb_fork is returned in the parent.
2302  * No race condition, even without setpgid from the parent.
2303  * (Is there an environment which has setpgid but FD_CLOEXEC?)
2304  */
2305  int ret;
2306  pid_t pgroup;
2307  if (!NIL_P(save)) {
2308  /* maybe meaningless with no fork environment... */
2309  rb_ary_store(save, EXEC_OPTION_PGROUP, PIDT2NUM(getpgrp()));
2310  }
2311  pgroup = NUM2PIDT(obj);
2312  if (pgroup == 0) {
2313  pgroup = getpid();
2314  }
2315  ret = setpgid(getpid(), pgroup);
2316  if (ret == -1) ERRMSG("setpgid");
2317  return ret;
2318 }
2319 #endif
2320 
2321 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2322 static int
2323 run_exec_rlimit(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
2324 {
2325  long i;
2326  for (i = 0; i < RARRAY_LEN(ary); i++) {
2327  VALUE elt = RARRAY_PTR(ary)[i];
2328  int rtype = NUM2INT(RARRAY_PTR(elt)[0]);
2329  struct rlimit rlim;
2330  if (!NIL_P(save)) {
2331  VALUE tmp, newary;
2332  if (getrlimit(rtype, &rlim) == -1) {
2333  ERRMSG("getrlimit");
2334  return -1;
2335  }
2336  tmp = hide_obj(rb_ary_new3(3, RARRAY_PTR(elt)[0],
2337  RLIM2NUM(rlim.rlim_cur),
2338  RLIM2NUM(rlim.rlim_max)));
2339  newary = rb_ary_entry(save, EXEC_OPTION_RLIMIT);
2340  if (NIL_P(newary)) {
2341  newary = hide_obj(rb_ary_new());
2342  rb_ary_store(save, EXEC_OPTION_RLIMIT, newary);
2343  }
2344  rb_ary_push(newary, tmp);
2345  }
2346  rlim.rlim_cur = NUM2RLIM(RARRAY_PTR(elt)[1]);
2347  rlim.rlim_max = NUM2RLIM(RARRAY_PTR(elt)[2]);
2348  if (setrlimit(rtype, &rlim) == -1) {
2349  ERRMSG("setrlimit");
2350  return -1;
2351  }
2352  }
2353  return 0;
2354 }
2355 #endif
2356 
2357 int
2358 rb_run_exec_options_err(const struct rb_exec_arg *e, struct rb_exec_arg *s, char *errmsg, size_t errmsg_buflen)
2359 {
2360  VALUE options = e->options;
2361  VALUE soptions = Qnil;
2362  VALUE obj;
2363 
2364  if (!RTEST(options))
2365  return 0;
2366 
2367  if (s) {
2368  s->argc = 0;
2369  s->argv = NULL;
2370  s->prog = NULL;
2371  s->options = soptions = hide_obj(rb_ary_new());
2372  s->redirect_fds = Qnil;
2373  }
2374 
2375 #ifdef HAVE_SETPGID
2376  obj = rb_ary_entry(options, EXEC_OPTION_PGROUP);
2377  if (RTEST(obj)) {
2378  if (run_exec_pgroup(obj, soptions, errmsg, errmsg_buflen) == -1)
2379  return -1;
2380  }
2381 #endif
2382 
2383 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2384  obj = rb_ary_entry(options, EXEC_OPTION_RLIMIT);
2385  if (!NIL_P(obj)) {
2386  if (run_exec_rlimit(obj, soptions, errmsg, errmsg_buflen) == -1)
2387  return -1;
2388  }
2389 #endif
2390 
2391  obj = rb_ary_entry(options, EXEC_OPTION_UNSETENV_OTHERS);
2392  if (RTEST(obj)) {
2393  save_env(soptions);
2394  rb_env_clear();
2395  }
2396 
2397  obj = rb_ary_entry(options, EXEC_OPTION_ENV);
2398  if (!NIL_P(obj)) {
2399  long i;
2400  save_env(soptions);
2401  for (i = 0; i < RARRAY_LEN(obj); i++) {
2402  VALUE pair = RARRAY_PTR(obj)[i];
2403  VALUE key = RARRAY_PTR(pair)[0];
2404  VALUE val = RARRAY_PTR(pair)[1];
2405  if (NIL_P(val))
2406  ruby_setenv(StringValueCStr(key), 0);
2407  else
2409  }
2410  }
2411 
2412  obj = rb_ary_entry(options, EXEC_OPTION_CHDIR);
2413  if (!NIL_P(obj)) {
2414  if (!NIL_P(soptions)) {
2415  char *cwd = my_getcwd();
2416  rb_ary_store(soptions, EXEC_OPTION_CHDIR,
2417  hide_obj(rb_str_new2(cwd)));
2418  xfree(cwd);
2419  }
2420  if (chdir(RSTRING_PTR(obj)) == -1) {
2421  ERRMSG("chdir");
2422  return -1;
2423  }
2424  }
2425 
2426  obj = rb_ary_entry(options, EXEC_OPTION_UMASK);
2427  if (!NIL_P(obj)) {
2428  mode_t mask = NUM2MODET(obj);
2429  mode_t oldmask = umask(mask); /* never fail */
2430  if (!NIL_P(soptions))
2431  rb_ary_store(soptions, EXEC_OPTION_UMASK, MODET2NUM(oldmask));
2432  }
2433 
2434  obj = rb_ary_entry(options, EXEC_OPTION_DUP2);
2435  if (!NIL_P(obj)) {
2436  if (run_exec_dup2(obj, soptions, errmsg, errmsg_buflen) == -1)
2437  return -1;
2438  }
2439 
2440  obj = rb_ary_entry(options, EXEC_OPTION_CLOSE);
2441  if (!NIL_P(obj)) {
2442  if (!NIL_P(soptions))
2443  rb_warn("cannot close fd before spawn");
2444  else {
2445  if (run_exec_close(obj, errmsg, errmsg_buflen) == -1)
2446  return -1;
2447  }
2448  }
2449 
2450 #ifdef HAVE_FORK
2451  obj = rb_ary_entry(options, EXEC_OPTION_CLOSE_OTHERS);
2452  if (obj != Qfalse) {
2454  }
2455 #endif
2456 
2457  obj = rb_ary_entry(options, EXEC_OPTION_OPEN);
2458  if (!NIL_P(obj)) {
2459  if (run_exec_open(obj, soptions, errmsg, errmsg_buflen) == -1)
2460  return -1;
2461  }
2462 
2463  obj = rb_ary_entry(options, EXEC_OPTION_DUP2_CHILD);
2464  if (!NIL_P(obj)) {
2465  if (run_exec_dup2_child(obj, soptions, errmsg, errmsg_buflen) == -1)
2466  return -1;
2467  }
2468 
2469  return 0;
2470 }
2471 
2472 int
2473 rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
2474 {
2475  return rb_run_exec_options_err(e, s, NULL, 0);
2476 }
2477 
2478 int
2479 rb_exec_err(const struct rb_exec_arg *e, char *errmsg, size_t errmsg_buflen)
2480 {
2481  int argc = e->argc;
2482  VALUE *argv = e->argv;
2483  const char *prog = e->prog;
2484 
2485  if (rb_run_exec_options_err(e, NULL, errmsg, errmsg_buflen) < 0) {
2486  return -1;
2487  }
2488 
2489  if (argc == 0) {
2490  rb_proc_exec(prog);
2491  }
2492  else {
2493  rb_proc_exec_n(argc, argv, prog);
2494  }
2495  return -1;
2496 }
2497 
2498 int
2499 rb_exec(const struct rb_exec_arg *e)
2500 {
2501 #if !defined FD_CLOEXEC && !defined HAVE_SPAWNV
2502  char errmsg[80] = { '\0' };
2503  int ret = rb_exec_err(e, errmsg, sizeof(errmsg));
2505  if (errmsg[0]) {
2506  fprintf(stderr, "%s\n", errmsg);
2507  }
2508  else {
2509  fprintf(stderr, "%s:%d: command not found: %s\n",
2510  rb_sourcefile(), rb_sourceline(), e->prog);
2511  }
2512  );
2513  return ret;
2514 #else
2515  return rb_exec_err(e, NULL, 0);
2516 #endif
2517 }
2518 
2519 #ifdef HAVE_FORK
2520 static int
2521 rb_exec_atfork(void* arg, char *errmsg, size_t errmsg_buflen)
2522 {
2524  return rb_exec_err(arg, errmsg, errmsg_buflen);
2525 }
2526 #endif
2527 
2528 #ifdef HAVE_FORK
2529 #ifdef FD_CLOEXEC
2530 #if SIZEOF_INT == SIZEOF_LONG
2531 #define proc_syswait (VALUE (*)(VALUE))rb_syswait
2532 #else
2533 static VALUE
2534 proc_syswait(VALUE pid)
2535 {
2536  rb_syswait((int)pid);
2537  return Qnil;
2538 }
2539 #endif
2540 #endif
2541 
2542 static int
2543 move_fds_to_avoid_crash(int *fdp, int n, VALUE fds)
2544 {
2545  long min = 0;
2546  int i;
2547  for (i = 0; i < n; i++) {
2548  int ret;
2549  while (RTEST(rb_hash_lookup(fds, INT2FIX(fdp[i])))) {
2550  if (min <= fdp[i])
2551  min = fdp[i]+1;
2552  while (RTEST(rb_hash_lookup(fds, INT2FIX(min))))
2553  min++;
2554  ret = fcntl(fdp[i], F_DUPFD, min);
2555  if (ret == -1)
2556  return -1;
2557  rb_update_max_fd(ret);
2558  close(fdp[i]);
2559  fdp[i] = ret;
2560  }
2561  }
2562  return 0;
2563 }
2564 
2565 static int
2566 pipe_nocrash(int filedes[2], VALUE fds)
2567 {
2568  int ret;
2569  ret = rb_pipe(filedes);
2570  if (ret == -1)
2571  return -1;
2572  if (RTEST(fds)) {
2573  int save = errno;
2574  if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
2575  close(filedes[0]);
2576  close(filedes[1]);
2577  return -1;
2578  }
2579  errno = save;
2580  }
2581  return ret;
2582 }
2583 
2584 struct chfunc_protect_t {
2585  int (*chfunc)(void*, char *, size_t);
2586  void *arg;
2587  char *errmsg;
2588  size_t buflen;
2589 };
2590 
2591 static VALUE
2592 chfunc_protect(VALUE arg)
2593 {
2594  struct chfunc_protect_t *p = (struct chfunc_protect_t *)arg;
2595 
2596  return (VALUE)(*p->chfunc)(p->arg, p->errmsg, p->buflen);
2597 }
2598 
2599 #ifndef O_BINARY
2600 #define O_BINARY 0
2601 #endif
2602 
2603 /*
2604  * Forks child process, and returns the process ID in the parent
2605  * process.
2606  *
2607  * If +status+ is given, protects from any exceptions and sets the
2608  * jump status to it.
2609  *
2610  * In the child process, just returns 0 if +chfunc+ is +NULL+.
2611  * Otherwise +chfunc+ will be called with +charg+, and then the child
2612  * process exits with +EXIT_SUCCESS+ when it returned zero.
2613  *
2614  * In the case of the function is called and returns non-zero value,
2615  * the child process exits with non-+EXIT_SUCCESS+ value (normally
2616  * 127). And, on the platforms where +FD_CLOEXEC+ is available,
2617  * +errno+ is propagated to the parent process, and this function
2618  * returns -1 in the parent process. On the other platforms, just
2619  * returns pid.
2620  *
2621  * If fds is not Qnil, internal pipe for the errno propagation is
2622  * arranged to avoid conflicts of the hash keys in +fds+.
2623  *
2624  * +chfunc+ must not raise any exceptions.
2625  */
2626 rb_pid_t
2627 rb_fork_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds,
2628  char *errmsg, size_t errmsg_buflen)
2629 {
2630  rb_pid_t pid;
2631  int err, state = 0;
2632 #ifdef FD_CLOEXEC
2633  int ep[2];
2634  VALUE io = Qnil;
2635 #endif
2636 
2637 #define prefork() ( \
2638  rb_io_flush(rb_stdout), \
2639  rb_io_flush(rb_stderr) \
2640  )
2641  prefork();
2642 
2643 #ifdef FD_CLOEXEC
2644  if (chfunc) {
2645  if (pipe_nocrash(ep, fds)) return -1;
2646  if (fcntl(ep[1], F_SETFD, FD_CLOEXEC)) {
2647  preserving_errno((close(ep[0]), close(ep[1])));
2648  return -1;
2649  }
2650  }
2651 #endif
2652  for (; before_fork(), (pid = fork()) < 0; prefork()) {
2653  after_fork();
2654  switch (errno) {
2655  case EAGAIN:
2656 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
2657  case EWOULDBLOCK:
2658 #endif
2659  if (!status && !chfunc) {
2660  rb_thread_sleep(1);
2661  continue;
2662  }
2663  else {
2664  rb_protect((VALUE (*)())rb_thread_sleep, 1, &state);
2665  if (status) *status = state;
2666  if (!state) continue;
2667  }
2668  default:
2669 #ifdef FD_CLOEXEC
2670  if (chfunc) {
2671  preserving_errno((close(ep[0]), close(ep[1])));
2672  }
2673 #endif
2674  if (state && !status) rb_jump_tag(state);
2675  return -1;
2676  }
2677  }
2678  if (!pid) {
2679  forked_child = 1;
2680  if (chfunc) {
2681  struct chfunc_protect_t arg;
2682  arg.chfunc = chfunc;
2683  arg.arg = charg;
2684  arg.errmsg = errmsg;
2685  arg.buflen = errmsg_buflen;
2686 #ifdef FD_CLOEXEC
2687  close(ep[0]);
2688 #endif
2689  if (!(int)rb_protect(chfunc_protect, (VALUE)&arg, &state)) _exit(EXIT_SUCCESS);
2690 #ifdef FD_CLOEXEC
2691  if (write(ep[1], &state, sizeof(state)) == sizeof(state) && state) {
2692  VALUE errinfo = rb_errinfo();
2693  io = rb_io_fdopen(ep[1], O_WRONLY|O_BINARY, NULL);
2694  rb_marshal_dump(errinfo, io);
2695  rb_io_flush(io);
2696  }
2697  err = errno;
2698  if (write(ep[1], &err, sizeof(err)) < 0) err = errno;
2699  if (errmsg && 0 < errmsg_buflen) {
2700  errmsg[errmsg_buflen-1] = '\0';
2701  errmsg_buflen = strlen(errmsg);
2702  if (errmsg_buflen > 0 &&write(ep[1], errmsg, errmsg_buflen) < 0)
2703  err = errno;
2704  }
2705  if (!NIL_P(io)) rb_io_close(io);
2706 #endif
2707 #if EXIT_SUCCESS == 127
2708  _exit(EXIT_FAILURE);
2709 #else
2710  _exit(127);
2711 #endif
2712  }
2713  }
2714  after_fork();
2715 #ifdef FD_CLOEXEC
2716  if (pid && chfunc) {
2717  ssize_t size;
2718  VALUE exc = Qnil;
2719  close(ep[1]);
2720  if ((read(ep[0], &state, sizeof(state))) == sizeof(state) && state) {
2721  io = rb_io_fdopen(ep[0], O_RDONLY|O_BINARY, NULL);
2722  exc = rb_marshal_load(io);
2723  rb_set_errinfo(exc);
2724  }
2725 #define READ_FROM_CHILD(ptr, len) \
2726  (NIL_P(io) ? read(ep[0], (ptr), (len)) : rb_io_bufread(io, (ptr), (len)))
2727  if ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) {
2728  err = errno;
2729  }
2730  if (size == sizeof(err) &&
2731  errmsg && 0 < errmsg_buflen) {
2732  ssize_t ret = READ_FROM_CHILD(errmsg, errmsg_buflen-1);
2733  if (0 <= ret) {
2734  errmsg[ret] = '\0';
2735  }
2736  }
2737  if (NIL_P(io))
2738  close(ep[0]);
2739  else
2740  rb_io_close(io);
2741  if (state || size) {
2742  if (status) {
2743  *status = state;
2744  rb_protect(proc_syswait, (VALUE)pid, status);
2745  }
2746  else {
2747  rb_syswait(pid);
2748  if (state) rb_exc_raise(exc);
2749  }
2750  errno = err;
2751  return -1;
2752  }
2753  }
2754 #endif
2755  return pid;
2756 }
2757 
2758 struct chfunc_wrapper_t {
2759  int (*chfunc)(void*);
2760  void *arg;
2761 };
2762 
2763 static int
2764 chfunc_wrapper(void *arg_, char *errmsg, size_t errmsg_buflen)
2765 {
2766  struct chfunc_wrapper_t *arg = arg_;
2767  return arg->chfunc(arg->arg);
2768 }
2769 
2770 rb_pid_t
2771 rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds)
2772 {
2773  if (chfunc) {
2774  struct chfunc_wrapper_t warg;
2775  warg.chfunc = chfunc;
2776  warg.arg = charg;
2777  return rb_fork_err(status, chfunc_wrapper, &warg, fds, NULL, 0);
2778  }
2779  else {
2780  return rb_fork_err(status, NULL, NULL, fds, NULL, 0);
2781  }
2782 
2783 }
2784 
2785 #endif
2786 
2787 #if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
2788 /*
2789  * call-seq:
2790  * Kernel.fork [{ block }] -> fixnum or nil
2791  * Process.fork [{ block }] -> fixnum or nil
2792  *
2793  * Creates a subprocess. If a block is specified, that block is run
2794  * in the subprocess, and the subprocess terminates with a status of
2795  * zero. Otherwise, the +fork+ call returns twice, once in
2796  * the parent, returning the process ID of the child, and once in
2797  * the child, returning _nil_. The child process can exit using
2798  * <code>Kernel.exit!</code> to avoid running any
2799  * <code>at_exit</code> functions. The parent process should
2800  * use <code>Process.wait</code> to collect the termination statuses
2801  * of its children or use <code>Process.detach</code> to register
2802  * disinterest in their status; otherwise, the operating system
2803  * may accumulate zombie processes.
2804  *
2805  * The thread calling fork is the only thread in the created child process.
2806  * fork doesn't copy other threads.
2807  *
2808  * If fork is not usable, Process.respond_to?(:fork) returns false.
2809  */
2810 
2811 static VALUE
2812 rb_f_fork(VALUE obj)
2813 {
2814  rb_pid_t pid;
2815 
2816  rb_secure(2);
2817 
2818  switch (pid = rb_fork(0, 0, 0, Qnil)) {
2819  case 0:
2820  rb_thread_atfork();
2821  if (rb_block_given_p()) {
2822  int status;
2823 
2824  rb_protect(rb_yield, Qundef, &status);
2825  ruby_stop(status);
2826  }
2827  return Qnil;
2828 
2829  case -1:
2830  rb_sys_fail("fork(2)");
2831  return Qnil;
2832 
2833  default:
2834  return PIDT2NUM(pid);
2835  }
2836 }
2837 #else
2838 #define rb_f_fork rb_f_notimplement
2839 #endif
2840 
2841 /*
2842  * call-seq:
2843  * Process.exit!(status=false)
2844  *
2845  * Exits the process immediately. No exit handlers are
2846  * run. <em>status</em> is returned to the underlying system as the
2847  * exit status.
2848  *
2849  * Process.exit!(true)
2850  */
2851 
2852 static VALUE
2853 rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
2854 {
2855  VALUE status;
2856  int istatus;
2857 
2858  rb_secure(4);
2859  if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
2860  switch (status) {
2861  case Qtrue:
2862  istatus = EXIT_SUCCESS;
2863  break;
2864  case Qfalse:
2865  istatus = EXIT_FAILURE;
2866  break;
2867  default:
2868  istatus = NUM2INT(status);
2869  break;
2870  }
2871  }
2872  else {
2873  istatus = EXIT_FAILURE;
2874  }
2875  _exit(istatus);
2876 
2877  return Qnil; /* not reached */
2878 }
2879 
2880 void
2881 rb_exit(int status)
2882 {
2883  if (GET_THREAD()->tag) {
2884  VALUE args[2];
2885 
2886  args[0] = INT2NUM(status);
2887  args[1] = rb_str_new2("exit");
2889  }
2890  ruby_finalize();
2891  exit(status);
2892 }
2893 
2894 
2895 /*
2896  * call-seq:
2897  * exit(status=true)
2898  * Kernel::exit(status=true)
2899  * Process::exit(status=true)
2900  *
2901  * Initiates the termination of the Ruby script by raising the
2902  * <code>SystemExit</code> exception. This exception may be caught. The
2903  * optional parameter is used to return a status code to the invoking
2904  * environment.
2905  * +true+ and +FALSE+ of _status_ means success and failure
2906  * respectively. The interpretation of other integer values are
2907  * system dependent.
2908  *
2909  * begin
2910  * exit
2911  * puts "never get here"
2912  * rescue SystemExit
2913  * puts "rescued a SystemExit exception"
2914  * end
2915  * puts "after begin block"
2916  *
2917  * <em>produces:</em>
2918  *
2919  * rescued a SystemExit exception
2920  * after begin block
2921  *
2922  * Just prior to termination, Ruby executes any <code>at_exit</code> functions
2923  * (see Kernel::at_exit) and runs any object finalizers (see
2924  * ObjectSpace::define_finalizer).
2925  *
2926  * at_exit { puts "at_exit function" }
2927  * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
2928  * exit
2929  *
2930  * <em>produces:</em>
2931  *
2932  * at_exit function
2933  * in finalizer
2934  */
2935 
2936 VALUE
2937 rb_f_exit(int argc, VALUE *argv)
2938 {
2939  VALUE status;
2940  int istatus;
2941 
2942  rb_secure(4);
2943  if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
2944  switch (status) {
2945  case Qtrue:
2946  istatus = EXIT_SUCCESS;
2947  break;
2948  case Qfalse:
2949  istatus = EXIT_FAILURE;
2950  break;
2951  default:
2952  istatus = NUM2INT(status);
2953 #if EXIT_SUCCESS != 0
2954  if (istatus == 0)
2955  istatus = EXIT_SUCCESS;
2956 #endif
2957  break;
2958  }
2959  }
2960  else {
2961  istatus = EXIT_SUCCESS;
2962  }
2963  rb_exit(istatus);
2964  return Qnil; /* not reached */
2965 }
2966 
2967 
2968 /*
2969  * call-seq:
2970  * abort
2971  * Kernel::abort([msg])
2972  * Process::abort([msg])
2973  *
2974  * Terminate execution immediately, effectively by calling
2975  * <code>Kernel.exit(false)</code>. If _msg_ is given, it is written
2976  * to STDERR prior to terminating.
2977  */
2978 
2979 VALUE
2980 rb_f_abort(int argc, VALUE *argv)
2981 {
2982  rb_secure(4);
2983  if (argc == 0) {
2984  if (!NIL_P(GET_THREAD()->errinfo)) {
2985  ruby_error_print();
2986  }
2988  }
2989  else {
2990  VALUE args[2];
2991 
2992  rb_scan_args(argc, argv, "1", &args[1]);
2993  StringValue(argv[0]);
2994  rb_io_puts(argc, argv, rb_stderr);
2995  args[0] = INT2NUM(EXIT_FAILURE);
2997  }
2998  return Qnil; /* not reached */
2999 }
3000 
3001 void
3002 rb_syswait(rb_pid_t pid)
3003 {
3004  static int overriding;
3005 #ifdef SIGHUP
3006  RETSIGTYPE (*hfunc)(int) = 0;
3007 #endif
3008 #ifdef SIGQUIT
3009  RETSIGTYPE (*qfunc)(int) = 0;
3010 #endif
3011  RETSIGTYPE (*ifunc)(int) = 0;
3012  int status;
3013  int i, hooked = FALSE;
3014 
3015  if (!overriding) {
3016 #ifdef SIGHUP
3017  hfunc = signal(SIGHUP, SIG_IGN);
3018 #endif
3019 #ifdef SIGQUIT
3020  qfunc = signal(SIGQUIT, SIG_IGN);
3021 #endif
3022  ifunc = signal(SIGINT, SIG_IGN);
3023  overriding = TRUE;
3024  hooked = TRUE;
3025  }
3026 
3027  do {
3028  i = rb_waitpid(pid, &status, 0);
3029  } while (i == -1 && errno == EINTR);
3030 
3031  if (hooked) {
3032 #ifdef SIGHUP
3033  signal(SIGHUP, hfunc);
3034 #endif
3035 #ifdef SIGQUIT
3036  signal(SIGQUIT, qfunc);
3037 #endif
3038  signal(SIGINT, ifunc);
3039  overriding = FALSE;
3040  }
3041 }
3042 
3043 static VALUE
3044 rb_exec_arg_prepare(struct rb_exec_arg *earg, int argc, VALUE *argv, int default_close_others)
3045 {
3046  VALUE prog = rb_exec_arg_init(argc, argv, TRUE, earg);
3048  VALUE v = default_close_others ? Qtrue : Qfalse;
3049  rb_exec_arg_addopt(earg, ID2SYM(rb_intern("close_others")), v);
3050  }
3051  rb_exec_arg_fixup(earg);
3052  return prog;
3053 }
3054 
3055 static rb_pid_t
3056 rb_spawn_process(struct rb_exec_arg *earg, VALUE prog, char *errmsg, size_t errmsg_buflen)
3057 {
3058  rb_pid_t pid;
3059 #if !USE_SPAWNV
3060  int status;
3061 #endif
3062 #if !defined HAVE_FORK || USE_SPAWNV
3063  struct rb_exec_arg sarg;
3064  int argc;
3065  VALUE *argv;
3066 #endif
3067 
3068 #if defined HAVE_FORK && !USE_SPAWNV
3069  pid = rb_fork_err(&status, rb_exec_atfork, earg, earg->redirect_fds, errmsg, errmsg_buflen);
3070 #else
3071  if (rb_run_exec_options_err(earg, &sarg, errmsg, errmsg_buflen) < 0) {
3072  return -1;
3073  }
3074 
3075  argc = earg->argc;
3076  argv = earg->argv;
3077  if (prog && argc) argv[0] = prog;
3078 # if defined HAVE_SPAWNV
3079  if (!argc) {
3080  pid = proc_spawn(RSTRING_PTR(prog));
3081  }
3082  else {
3083  pid = proc_spawn_n(argc, argv, prog, earg->options);
3084  }
3085 # if defined(_WIN32)
3086  if (pid == -1)
3087  rb_last_status_set(0x7f << 8, 0);
3088 # endif
3089 # else
3090  if (argc) prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
3091  status = system(StringValuePtr(prog));
3092  rb_last_status_set((status & 0xff) << 8, 0);
3093 # endif
3094 
3095  rb_run_exec_options_err(&sarg, NULL, errmsg, errmsg_buflen);
3096 #endif
3097  return pid;
3098 }
3099 
3100 static rb_pid_t
3101 rb_spawn_internal(int argc, VALUE *argv, int default_close_others,
3102  char *errmsg, size_t errmsg_buflen)
3103 {
3104  struct rb_exec_arg earg;
3105  VALUE prog = rb_exec_arg_prepare(&earg, argc, argv, default_close_others);
3106  return rb_spawn_process(&earg, prog, errmsg, errmsg_buflen);
3107 }
3108 
3109 rb_pid_t
3110 rb_spawn_err(int argc, VALUE *argv, char *errmsg, size_t errmsg_buflen)
3111 {
3112  return rb_spawn_internal(argc, argv, TRUE, errmsg, errmsg_buflen);
3113 }
3114 
3115 rb_pid_t
3116 rb_spawn(int argc, VALUE *argv)
3117 {
3118  return rb_spawn_internal(argc, argv, TRUE, NULL, 0);
3119 }
3120 
3121 /*
3122  * call-seq:
3123  * system([env,] command... [,options]) -> true, false or nil
3124  *
3125  * Executes _command..._ in a subshell.
3126  * _command..._ is one of following forms.
3127  *
3128  * commandline : command line string which is passed to the standard shell
3129  * cmdname, arg1, ... : command name and one or more arguments (no shell)
3130  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
3131  *
3132  * system returns +true+ if the command gives zero exit status,
3133  * +false+ for non zero exit status.
3134  * Returns +nil+ if command execution fails.
3135  * An error status is available in <code>$?</code>.
3136  * The arguments are processed in the same way as
3137  * for <code>Kernel.spawn</code>.
3138  *
3139  * The hash arguments, env and options, are same as
3140  * <code>exec</code> and <code>spawn</code>.
3141  * See <code>Kernel.spawn</code> for details.
3142  *
3143  * system("echo *")
3144  * system("echo", "*")
3145  *
3146  * <em>produces:</em>
3147  *
3148  * config.h main.rb
3149  * *
3150  *
3151  * See <code>Kernel.exec</code> for the standard shell.
3152  */
3153 
3154 static VALUE
3155 rb_f_system(int argc, VALUE *argv)
3156 {
3157  rb_pid_t pid;
3158  int status;
3159 
3160 #if defined(SIGCLD) && !defined(SIGCHLD)
3161 # define SIGCHLD SIGCLD
3162 #endif
3163 
3164 #ifdef SIGCHLD
3165  RETSIGTYPE (*chfunc)(int);
3166 
3167  chfunc = signal(SIGCHLD, SIG_DFL);
3168 #endif
3169  pid = rb_spawn_internal(argc, argv, FALSE, NULL, 0);
3170 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3171  if (pid > 0) {
3172  rb_syswait(pid);
3173  }
3174 #endif
3175 #ifdef SIGCHLD
3176  signal(SIGCHLD, chfunc);
3177 #endif
3178  if (pid < 0) {
3179  return Qnil;
3180  }
3181  status = PST2INT(rb_last_status_get());
3182  if (status == EXIT_SUCCESS) return Qtrue;
3183  return Qfalse;
3184 }
3185 
3186 /*
3187  * call-seq:
3188  * spawn([env,] command... [,options]) -> pid
3189  * Process.spawn([env,] command... [,options]) -> pid
3190  *
3191  * spawn executes specified command and return its pid.
3192  *
3193  * This method doesn't wait for end of the command.
3194  * The parent process should
3195  * use <code>Process.wait</code> to collect
3196  * the termination status of its child or
3197  * use <code>Process.detach</code> to register
3198  * disinterest in their status;
3199  * otherwise, the operating system may accumulate zombie processes.
3200  *
3201  * spawn has bunch of options to specify process attributes:
3202  *
3203  * env: hash
3204  * name => val : set the environment variable
3205  * name => nil : unset the environment variable
3206  * command...:
3207  * commandline : command line string which is passed to the standard shell
3208  * cmdname, arg1, ... : command name and one or more arguments (no shell)
3209  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
3210  * options: hash
3211  * clearing environment variables:
3212  * :unsetenv_others => true : clear environment variables except specified by env
3213  * :unsetenv_others => false : don't clear (default)
3214  * process group:
3215  * :pgroup => true or 0 : make a new process group
3216  * :pgroup => pgid : join to specified process group
3217  * :pgroup => nil : don't change the process group (default)
3218  * create new process group: Windows only
3219  * :new_pgroup => true : the new process is the root process of a new process group
3220  * :new_pgroup => false : don't create a new process group (default)
3221  * resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
3222  * :rlimit_resourcename => limit
3223  * :rlimit_resourcename => [cur_limit, max_limit]
3224  * current directory:
3225  * :chdir => str
3226  * umask:
3227  * :umask => int
3228  * redirection:
3229  * key:
3230  * FD : single file descriptor in child process
3231  * [FD, FD, ...] : multiple file descriptor in child process
3232  * value:
3233  * FD : redirect to the file descriptor in parent process
3234  * string : redirect to file with open(string, "r" or "w")
3235  * [string] : redirect to file with open(string, File::RDONLY)
3236  * [string, open_mode] : redirect to file with open(string, open_mode, 0644)
3237  * [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
3238  * [:child, FD] : redirect to the redirected file descriptor
3239  * :close : close the file descriptor in child process
3240  * FD is one of follows
3241  * :in : the file descriptor 0 which is the standard input
3242  * :out : the file descriptor 1 which is the standard output
3243  * :err : the file descriptor 2 which is the standard error
3244  * integer : the file descriptor of specified the integer
3245  * io : the file descriptor specified as io.fileno
3246  * file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
3247  * :close_others => false : inherit fds (default for system and exec)
3248  * :close_others => true : don't inherit (default for spawn and IO.popen)
3249  *
3250  * If a hash is given as +env+, the environment is
3251  * updated by +env+ before <code>exec(2)</code> in the child process.
3252  * If a pair in +env+ has nil as the value, the variable is deleted.
3253  *
3254  * # set FOO as BAR and unset BAZ.
3255  * pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
3256  *
3257  * If a hash is given as +options+,
3258  * it specifies
3259  * process group,
3260  * create new process group,
3261  * resource limit,
3262  * current directory,
3263  * umask and
3264  * redirects for the child process.
3265  * Also, it can be specified to clear environment variables.
3266  *
3267  * The <code>:unsetenv_others</code> key in +options+ specifies
3268  * to clear environment variables, other than specified by +env+.
3269  *
3270  * pid = spawn(command, :unsetenv_others=>true) # no environment variable
3271  * pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
3272  *
3273  * The <code>:pgroup</code> key in +options+ specifies a process group.
3274  * The corresponding value should be true, zero or positive integer.
3275  * true and zero means the process should be a process leader of a new
3276  * process group.
3277  * Other values specifies a process group to be belongs.
3278  *
3279  * pid = spawn(command, :pgroup=>true) # process leader
3280  * pid = spawn(command, :pgroup=>10) # belongs to the process group 10
3281  *
3282  * The <code>:new_pgroup</code> key in +options+ specifies to pass
3283  * +CREATE_NEW_PROCESS_GROUP+ flag to <code>CreateProcessW()</code> that is
3284  * Windows API. This option is only for Windows.
3285  * true means the new process is the root process of the new process group.
3286  * The new process has CTRL+C disabled. This flag is necessary for
3287  * <code>Process.kill(:SIGINT, pid)</code> on the subprocess.
3288  * :new_pgroup is false by default.
3289  *
3290  * pid = spawn(command, :new_pgroup=>true) # new process group
3291  * pid = spawn(command, :new_pgroup=>false) # same process group
3292  *
3293  * The <code>:rlimit_</code><em>foo</em> key specifies a resource limit.
3294  * <em>foo</em> should be one of resource types such as <code>core</code>.
3295  * The corresponding value should be an integer or an array which have one or
3296  * two integers: same as cur_limit and max_limit arguments for
3297  * Process.setrlimit.
3298  *
3299  * cur, max = Process.getrlimit(:CORE)
3300  * pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
3301  * pid = spawn(command, :rlimit_core=>max) # enable core dump
3302  * pid = spawn(command, :rlimit_core=>0) # never dump core.
3303  *
3304  * The <code>:chdir</code> key in +options+ specifies the current directory.
3305  *
3306  * pid = spawn(command, :chdir=>"/var/tmp")
3307  *
3308  * The <code>:umask</code> key in +options+ specifies the umask.
3309  *
3310  * pid = spawn(command, :umask=>077)
3311  *
3312  * The :in, :out, :err, a fixnum, an IO and an array key specifies a redirection.
3313  * The redirection maps a file descriptor in the child process.
3314  *
3315  * For example, stderr can be merged into stdout as follows:
3316  *
3317  * pid = spawn(command, :err=>:out)
3318  * pid = spawn(command, 2=>1)
3319  * pid = spawn(command, STDERR=>:out)
3320  * pid = spawn(command, STDERR=>STDOUT)
3321  *
3322  * The hash keys specifies a file descriptor
3323  * in the child process started by <code>spawn</code>.
3324  * :err, 2 and STDERR specifies the standard error stream (stderr).
3325  *
3326  * The hash values specifies a file descriptor
3327  * in the parent process which invokes <code>spawn</code>.
3328  * :out, 1 and STDOUT specifies the standard output stream (stdout).
3329  *
3330  * In the above example,
3331  * the standard output in the child process is not specified.
3332  * So it is inherited from the parent process.
3333  *
3334  * The standard input stream (stdin) can be specified by :in, 0 and STDIN.
3335  *
3336  * A filename can be specified as a hash value.
3337  *
3338  * pid = spawn(command, :in=>"/dev/null") # read mode
3339  * pid = spawn(command, :out=>"/dev/null") # write mode
3340  * pid = spawn(command, :err=>"log") # write mode
3341  * pid = spawn(command, 3=>"/dev/null") # read mode
3342  *
3343  * For stdout and stderr,
3344  * it is opened in write mode.
3345  * Otherwise read mode is used.
3346  *
3347  * For specifying flags and permission of file creation explicitly,
3348  * an array is used instead.
3349  *
3350  * pid = spawn(command, :in=>["file"]) # read mode is assumed
3351  * pid = spawn(command, :in=>["file", "r"])
3352  * pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
3353  * pid = spawn(command, :out=>["log", "w", 0600])
3354  * pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
3355  *
3356  * The array specifies a filename, flags and permission.
3357  * The flags can be a string or an integer.
3358  * If the flags is omitted or nil, File::RDONLY is assumed.
3359  * The permission should be an integer.
3360  * If the permission is omitted or nil, 0644 is assumed.
3361  *
3362  * If an array of IOs and integers are specified as a hash key,
3363  * all the elements are redirected.
3364  *
3365  * # stdout and stderr is redirected to log file.
3366  * # The file "log" is opened just once.
3367  * pid = spawn(command, [:out, :err]=>["log", "w"])
3368  *
3369  * Another way to merge multiple file descriptors is [:child, fd].
3370  * \[:child, fd] means the file descriptor in the child process.
3371  * This is different from fd.
3372  * For example, :err=>:out means redirecting child stderr to parent stdout.
3373  * But :err=>[:child, :out] means redirecting child stderr to child stdout.
3374  * They differs if stdout is redirected in the child process as follows.
3375  *
3376  * # stdout and stderr is redirected to log file.
3377  * # The file "log" is opened just once.
3378  * pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
3379  *
3380  * \[:child, :out] can be used to merge stderr into stdout in IO.popen.
3381  * In this case, IO.popen redirects stdout to a pipe in the child process
3382  * and [:child, :out] refers the redirected stdout.
3383  *
3384  * io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
3385  * p io.read #=> "out\nerr\n"
3386  *
3387  * spawn closes all non-standard unspecified descriptors by default.
3388  * The "standard" descriptors are 0, 1 and 2.
3389  * This behavior is specified by :close_others option.
3390  * :close_others doesn't affect the standard descriptors which are
3391  * closed only if :close is specified explicitly.
3392  *
3393  * pid = spawn(command, :close_others=>true) # close 3,4,5,... (default)
3394  * pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
3395  *
3396  * :close_others is true by default for spawn and IO.popen.
3397  *
3398  * So IO.pipe and spawn can be used as IO.popen.
3399  *
3400  * # similar to r = IO.popen(command)
3401  * r, w = IO.pipe
3402  * pid = spawn(command, :out=>w) # r, w is closed in the child process.
3403  * w.close
3404  *
3405  * :close is specified as a hash value to close a fd individually.
3406  *
3407  * f = open(foo)
3408  * system(command, f=>:close) # don't inherit f.
3409  *
3410  * If a file descriptor need to be inherited,
3411  * io=>io can be used.
3412  *
3413  * # valgrind has --log-fd option for log destination.
3414  * # log_w=>log_w indicates log_w.fileno inherits to child process.
3415  * log_r, log_w = IO.pipe
3416  * pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
3417  * log_w.close
3418  * p log_r.read
3419  *
3420  * It is also possible to exchange file descriptors.
3421  *
3422  * pid = spawn(command, :out=>:err, :err=>:out)
3423  *
3424  * The hash keys specify file descriptors in the child process.
3425  * The hash values specifies file descriptors in the parent process.
3426  * So the above specifies exchanging stdout and stderr.
3427  * Internally, +spawn+ uses an extra file descriptor to resolve such cyclic
3428  * file descriptor mapping.
3429  *
3430  * See <code>Kernel.exec</code> for the standard shell.
3431  */
3432 
3433 static VALUE
3434 rb_f_spawn(int argc, VALUE *argv)
3435 {
3436  rb_pid_t pid;
3437  char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
3438  struct rb_exec_arg earg;
3439 
3440  pid = rb_spawn_process(&earg, rb_exec_arg_prepare(&earg, argc, argv, TRUE), errmsg, sizeof(errmsg));
3441  if (pid == -1) {
3442  const char *prog = errmsg;
3443  if (!prog[0] && !(prog = earg.prog) && earg.argc) {
3444  prog = RSTRING_PTR(earg.argv[0]);
3445  }
3446  rb_sys_fail(prog);
3447  }
3448 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3449  return PIDT2NUM(pid);
3450 #else
3451  return Qnil;
3452 #endif
3453 }
3454 
3455 /*
3456  * call-seq:
3457  * sleep([duration]) -> fixnum
3458  *
3459  * Suspends the current thread for _duration_ seconds (which may be any number,
3460  * including a +Float+ with fractional seconds). Returns the actual number of
3461  * seconds slept (rounded), which may be less than that asked for if another
3462  * thread calls <code>Thread#run</code>. Called without an argument, sleep()
3463  * will sleep forever.
3464  *
3465  * Time.new #=> 2008-03-08 19:56:19 +0900
3466  * sleep 1.2 #=> 1
3467  * Time.new #=> 2008-03-08 19:56:20 +0900
3468  * sleep 1.9 #=> 2
3469  * Time.new #=> 2008-03-08 19:56:22 +0900
3470  */
3471 
3472 static VALUE
3473 rb_f_sleep(int argc, VALUE *argv)
3474 {
3475  time_t beg, end;
3476 
3477  beg = time(0);
3478  if (argc == 0) {
3480  }
3481  else if (argc == 1) {
3483  }
3484  else {
3485  rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
3486  }
3487 
3488  end = time(0) - beg;
3489 
3490  return INT2FIX(end);
3491 }
3492 
3493 
3494 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
3495 /*
3496  * call-seq:
3497  * Process.getpgrp -> integer
3498  *
3499  * Returns the process group ID for this process. Not available on
3500  * all platforms.
3501  *
3502  * Process.getpgid(0) #=> 25527
3503  * Process.getpgrp #=> 25527
3504  */
3505 
3506 static VALUE
3507 proc_getpgrp(void)
3508 {
3509  rb_pid_t pgrp;
3510 
3511  rb_secure(2);
3512 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
3513  pgrp = getpgrp();
3514  if (pgrp < 0) rb_sys_fail(0);
3515  return PIDT2NUM(pgrp);
3516 #else /* defined(HAVE_GETPGID) */
3517  pgrp = getpgid(0);
3518  if (pgrp < 0) rb_sys_fail(0);
3519  return PIDT2NUM(pgrp);
3520 #endif
3521 }
3522 #else
3523 #define proc_getpgrp rb_f_notimplement
3524 #endif
3525 
3526 
3527 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
3528 /*
3529  * call-seq:
3530  * Process.setpgrp -> 0
3531  *
3532  * Equivalent to <code>setpgid(0,0)</code>. Not available on all
3533  * platforms.
3534  */
3535 
3536 static VALUE
3537 proc_setpgrp(void)
3538 {
3539  rb_secure(2);
3540  /* check for posix setpgid() first; this matches the posix */
3541  /* getpgrp() above. It appears that configure will set SETPGRP_VOID */
3542  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
3543  /* this confusion. */
3544 #ifdef HAVE_SETPGID
3545  if (setpgid(0,0) < 0) rb_sys_fail(0);
3546 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
3547  if (setpgrp() < 0) rb_sys_fail(0);
3548 #endif
3549  return INT2FIX(0);
3550 }
3551 #else
3552 #define proc_setpgrp rb_f_notimplement
3553 #endif
3554 
3555 
3556 #if defined(HAVE_GETPGID)
3557 /*
3558  * call-seq:
3559  * Process.getpgid(pid) -> integer
3560  *
3561  * Returns the process group ID for the given process id. Not
3562  * available on all platforms.
3563  *
3564  * Process.getpgid(Process.ppid()) #=> 25527
3565  */
3566 
3567 static VALUE
3568 proc_getpgid(VALUE obj, VALUE pid)
3569 {
3570  rb_pid_t i;
3571 
3572  rb_secure(2);
3573  i = getpgid(NUM2PIDT(pid));
3574  if (i < 0) rb_sys_fail(0);
3575  return PIDT2NUM(i);
3576 }
3577 #else
3578 #define proc_getpgid rb_f_notimplement
3579 #endif
3580 
3581 
3582 #ifdef HAVE_SETPGID
3583 /*
3584  * call-seq:
3585  * Process.setpgid(pid, integer) -> 0
3586  *
3587  * Sets the process group ID of _pid_ (0 indicates this
3588  * process) to <em>integer</em>. Not available on all platforms.
3589  */
3590 
3591 static VALUE
3592 proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
3593 {
3594  rb_pid_t ipid, ipgrp;
3595 
3596  rb_secure(2);
3597  ipid = NUM2PIDT(pid);
3598  ipgrp = NUM2PIDT(pgrp);
3599 
3600  if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
3601  return INT2FIX(0);
3602 }
3603 #else
3604 #define proc_setpgid rb_f_notimplement
3605 #endif
3606 
3607 
3608 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
3609 #if !defined(HAVE_SETSID)
3610 static rb_pid_t ruby_setsid(void);
3611 #define setsid() ruby_setsid()
3612 #endif
3613 /*
3614  * call-seq:
3615  * Process.setsid -> fixnum
3616  *
3617  * Establishes this process as a new session and process group
3618  * leader, with no controlling tty. Returns the session id. Not
3619  * available on all platforms.
3620  *
3621  * Process.setsid #=> 27422
3622  */
3623 
3624 static VALUE
3625 proc_setsid(void)
3626 {
3627  rb_pid_t pid;
3628 
3629  rb_secure(2);
3630  pid = setsid();
3631  if (pid < 0) rb_sys_fail(0);
3632  return PIDT2NUM(pid);
3633 }
3634 
3635 #if !defined(HAVE_SETSID)
3636 #define HAVE_SETSID 1
3637 static rb_pid_t
3638 ruby_setsid(void)
3639 {
3640  rb_pid_t pid;
3641  int ret;
3642 
3643  pid = getpid();
3644 #if defined(SETPGRP_VOID)
3645  ret = setpgrp();
3646  /* If `pid_t setpgrp(void)' is equivalent to setsid(),
3647  `ret' will be the same value as `pid', and following open() will fail.
3648  In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
3649 #else
3650  ret = setpgrp(0, pid);
3651 #endif
3652  if (ret == -1) return -1;
3653 
3654  if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
3655  rb_update_max_fd(fd);
3656  ioctl(fd, TIOCNOTTY, NULL);
3657  close(fd);
3658  }
3659  return pid;
3660 }
3661 #endif
3662 #else
3663 #define proc_setsid rb_f_notimplement
3664 #endif
3665 
3666 
3667 #ifdef HAVE_GETPRIORITY
3668 /*
3669  * call-seq:
3670  * Process.getpriority(kind, integer) -> fixnum
3671  *
3672  * Gets the scheduling priority for specified process, process group,
3673  * or user. <em>kind</em> indicates the kind of entity to find: one
3674  * of <code>Process::PRIO_PGRP</code>,
3675  * <code>Process::PRIO_USER</code>, or
3676  * <code>Process::PRIO_PROCESS</code>. _integer_ is an id
3677  * indicating the particular process, process group, or user (an id
3678  * of 0 means _current_). Lower priorities are more favorable
3679  * for scheduling. Not available on all platforms.
3680  *
3681  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
3682  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
3683  */
3684 
3685 static VALUE
3686 proc_getpriority(VALUE obj, VALUE which, VALUE who)
3687 {
3688  int prio, iwhich, iwho;
3689 
3690  rb_secure(2);
3691  iwhich = NUM2INT(which);
3692  iwho = NUM2INT(who);
3693 
3694  errno = 0;
3695  prio = getpriority(iwhich, iwho);
3696  if (errno) rb_sys_fail(0);
3697  return INT2FIX(prio);
3698 }
3699 #else
3700 #define proc_getpriority rb_f_notimplement
3701 #endif
3702 
3703 
3704 #ifdef HAVE_GETPRIORITY
3705 /*
3706  * call-seq:
3707  * Process.setpriority(kind, integer, priority) -> 0
3708  *
3709  * See <code>Process#getpriority</code>.
3710  *
3711  * Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0
3712  * Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0
3713  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
3714  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
3715  */
3716 
3717 static VALUE
3718 proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
3719 {
3720  int iwhich, iwho, iprio;
3721 
3722  rb_secure(2);
3723  iwhich = NUM2INT(which);
3724  iwho = NUM2INT(who);
3725  iprio = NUM2INT(prio);
3726 
3727  if (setpriority(iwhich, iwho, iprio) < 0)
3728  rb_sys_fail(0);
3729  return INT2FIX(0);
3730 }
3731 #else
3732 #define proc_setpriority rb_f_notimplement
3733 #endif
3734 
3735 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
3736 static int
3737 rlimit_resource_name2int(const char *name, int casetype)
3738 {
3739  int resource;
3740  const char *p;
3741 #define RESCHECK(r) \
3742  do { \
3743  if (STRCASECMP(name, #r) == 0) { \
3744  resource = RLIMIT_##r; \
3745  goto found; \
3746  } \
3747  } while (0)
3748 
3749  switch (TOUPPER(*name)) {
3750  case 'A':
3751 #ifdef RLIMIT_AS
3752  RESCHECK(AS);
3753 #endif
3754  break;
3755 
3756  case 'C':
3757 #ifdef RLIMIT_CORE
3758  RESCHECK(CORE);
3759 #endif
3760 #ifdef RLIMIT_CPU
3761  RESCHECK(CPU);
3762 #endif
3763  break;
3764 
3765  case 'D':
3766 #ifdef RLIMIT_DATA
3767  RESCHECK(DATA);
3768 #endif
3769  break;
3770 
3771  case 'F':
3772 #ifdef RLIMIT_FSIZE
3773  RESCHECK(FSIZE);
3774 #endif
3775  break;
3776 
3777  case 'M':
3778 #ifdef RLIMIT_MEMLOCK
3779  RESCHECK(MEMLOCK);
3780 #endif
3781 #ifdef RLIMIT_MSGQUEUE
3782  RESCHECK(MSGQUEUE);
3783 #endif
3784  break;
3785 
3786  case 'N':
3787 #ifdef RLIMIT_NOFILE
3788  RESCHECK(NOFILE);
3789 #endif
3790 #ifdef RLIMIT_NPROC
3791  RESCHECK(NPROC);
3792 #endif
3793 #ifdef RLIMIT_NICE
3794  RESCHECK(NICE);
3795 #endif
3796  break;
3797 
3798  case 'R':
3799 #ifdef RLIMIT_RSS
3800  RESCHECK(RSS);
3801 #endif
3802 #ifdef RLIMIT_RTPRIO
3803  RESCHECK(RTPRIO);
3804 #endif
3805 #ifdef RLIMIT_RTTIME
3806  RESCHECK(RTTIME);
3807 #endif
3808  break;
3809 
3810  case 'S':
3811 #ifdef RLIMIT_STACK
3812  RESCHECK(STACK);
3813 #endif
3814 #ifdef RLIMIT_SBSIZE
3815  RESCHECK(SBSIZE);
3816 #endif
3817 #ifdef RLIMIT_SIGPENDING
3818  RESCHECK(SIGPENDING);
3819 #endif
3820  break;
3821  }
3822  return -1;
3823 
3824  found:
3825  switch (casetype) {
3826  case 0:
3827  for (p = name; *p; p++)
3828  if (!ISUPPER(*p))
3829  return -1;
3830  break;
3831 
3832  case 1:
3833  for (p = name; *p; p++)
3834  if (!ISLOWER(*p))
3835  return -1;
3836  break;
3837 
3838  default:
3839  rb_bug("unexpected casetype");
3840  }
3841  return resource;
3842 #undef RESCHECK
3843 }
3844 
3845 static int
3846 rlimit_type_by_hname(const char *name)
3847 {
3848  return rlimit_resource_name2int(name, 0);
3849 }
3850 
3851 static int
3852 rlimit_type_by_lname(const char *name)
3853 {
3854  return rlimit_resource_name2int(name, 1);
3855 }
3856 
3857 static int
3858 rlimit_resource_type(VALUE rtype)
3859 {
3860  const char *name;
3861  VALUE v;
3862  int r;
3863 
3864  switch (TYPE(rtype)) {
3865  case T_SYMBOL:
3866  name = rb_id2name(SYM2ID(rtype));
3867  break;
3868 
3869  default:
3870  v = rb_check_string_type(rtype);
3871  if (!NIL_P(v)) {
3872  rtype = v;
3873  case T_STRING:
3874  name = StringValueCStr(rtype);
3875  break;
3876  }
3877  /* fall through */
3878 
3879  case T_FIXNUM:
3880  case T_BIGNUM:
3881  return NUM2INT(rtype);
3882  }
3883 
3884  r = rlimit_type_by_hname(name);
3885  if (r != -1)
3886  return r;
3887 
3888  rb_raise(rb_eArgError, "invalid resource name: %s", name);
3889 }
3890 
3891 static rlim_t
3892 rlimit_resource_value(VALUE rval)
3893 {
3894  const char *name;
3895  VALUE v;
3896 
3897  switch (TYPE(rval)) {
3898  case T_SYMBOL:
3899  name = rb_id2name(SYM2ID(rval));
3900  break;
3901 
3902  default:
3903  v = rb_check_string_type(rval);
3904  if (!NIL_P(v)) {
3905  rval = v;
3906  case T_STRING:
3907  name = StringValueCStr(rval);
3908  break;
3909  }
3910  /* fall through */
3911 
3912  case T_FIXNUM:
3913  case T_BIGNUM:
3914  return NUM2RLIM(rval);
3915  }
3916 
3917 #ifdef RLIM_INFINITY
3918  if (strcmp(name, "INFINITY") == 0) return RLIM_INFINITY;
3919 #endif
3920 #ifdef RLIM_SAVED_MAX
3921  if (strcmp(name, "SAVED_MAX") == 0) return RLIM_SAVED_MAX;
3922 #endif
3923 #ifdef RLIM_SAVED_CUR
3924  if (strcmp(name, "SAVED_CUR") == 0) return RLIM_SAVED_CUR;
3925 #endif
3926  rb_raise(rb_eArgError, "invalid resource value: %s", name);
3927 }
3928 #endif
3929 
3930 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
3931 /*
3932  * call-seq:
3933  * Process.getrlimit(resource) -> [cur_limit, max_limit]
3934  *
3935  * Gets the resource limit of the process.
3936  * _cur_limit_ means current (soft) limit and
3937  * _max_limit_ means maximum (hard) limit.
3938  *
3939  * _resource_ indicates the kind of resource to limit.
3940  * It is specified as a symbol such as <code>:CORE</code>,
3941  * a string such as <code>"CORE"</code> or
3942  * a constant such as <code>Process::RLIMIT_CORE</code>.
3943  * See Process.setrlimit for details.
3944  *
3945  * _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
3946  * <code>Process::RLIM_SAVED_MAX</code> or
3947  * <code>Process::RLIM_SAVED_CUR</code>.
3948  * See Process.setrlimit and the system getrlimit(2) manual for details.
3949  */
3950 
3951 static VALUE
3952 proc_getrlimit(VALUE obj, VALUE resource)
3953 {
3954  struct rlimit rlim;
3955 
3956  rb_secure(2);
3957 
3958  if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
3959  rb_sys_fail("getrlimit");
3960  }
3961  return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
3962 }
3963 #else
3964 #define proc_getrlimit rb_f_notimplement
3965 #endif
3966 
3967 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
3968 /*
3969  * call-seq:
3970  * Process.setrlimit(resource, cur_limit, max_limit) -> nil
3971  * Process.setrlimit(resource, cur_limit) -> nil
3972  *
3973  * Sets the resource limit of the process.
3974  * _cur_limit_ means current (soft) limit and
3975  * _max_limit_ means maximum (hard) limit.
3976  *
3977  * If _max_limit_ is not given, _cur_limit_ is used.
3978  *
3979  * _resource_ indicates the kind of resource to limit.
3980  * It should be a symbol such as <code>:CORE</code>,
3981  * a string such as <code>"CORE"</code> or
3982  * a constant such as <code>Process::RLIMIT_CORE</code>.
3983  * The available resources are OS dependent.
3984  * Ruby may support following resources.
3985  *
3986  * [AS] total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)
3987  * [CORE] core size (bytes) (SUSv3)
3988  * [CPU] CPU time (seconds) (SUSv3)
3989  * [DATA] data segment (bytes) (SUSv3)
3990  * [FSIZE] file size (bytes) (SUSv3)
3991  * [MEMLOCK] total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)
3992  * [MSGQUEUE] allocation for POSIX message queues (bytes) (GNU/Linux)
3993  * [NICE] ceiling on process's nice(2) value (number) (GNU/Linux)
3994  * [NOFILE] file descriptors (number) (SUSv3)
3995  * [NPROC] number of processes for the user (number) (4.4BSD, GNU/Linux)
3996  * [RSS] resident memory size (bytes) (4.2BSD, GNU/Linux)
3997  * [RTPRIO] ceiling on the process's real-time priority (number) (GNU/Linux)
3998  * [RTTIME] CPU time for real-time process (us) (GNU/Linux)
3999  * [SBSIZE] all socket buffers (bytes) (NetBSD, FreeBSD)
4000  * [SIGPENDING] number of queued signals allowed (signals) (GNU/Linux)
4001  * [STACK] stack size (bytes) (SUSv3)
4002  *
4003  * _cur_limit_ and _max_limit_ may be
4004  * <code>:INFINITY</code>, <code>"INFINITY"</code> or
4005  * <code>Process::RLIM_INFINITY</code>,
4006  * which means that the resource is not limited.
4007  * They may be <code>Process::RLIM_SAVED_MAX</code>,
4008  * <code>Process::RLIM_SAVED_CUR</code> and
4009  * corresponding symbols and strings too.
4010  * See system setrlimit(2) manual for details.
4011  *
4012  * The following example raises the soft limit of core size to
4013  * the hard limit to try to make core dump possible.
4014  *
4015  * Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
4016  *
4017  */
4018 
4019 static VALUE
4020 proc_setrlimit(int argc, VALUE *argv, VALUE obj)
4021 {
4022  VALUE resource, rlim_cur, rlim_max;
4023  struct rlimit rlim;
4024 
4025  rb_secure(2);
4026 
4027  rb_scan_args(argc, argv, "21", &resource, &rlim_cur, &rlim_max);
4028  if (rlim_max == Qnil)
4029  rlim_max = rlim_cur;
4030 
4031  rlim.rlim_cur = rlimit_resource_value(rlim_cur);
4032  rlim.rlim_max = rlimit_resource_value(rlim_max);
4033 
4034  if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4035  rb_sys_fail("setrlimit");
4036  }
4037  return Qnil;
4038 }
4039 #else
4040 #define proc_setrlimit rb_f_notimplement
4041 #endif
4042 
4043 static int under_uid_switch = 0;
4044 static void
4046 {
4047  rb_secure(2);
4048  if (under_uid_switch) {
4049  rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
4050  }
4051 }
4052 
4053 static int under_gid_switch = 0;
4054 static void
4056 {
4057  rb_secure(2);
4058  if (under_gid_switch) {
4059  rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
4060  }
4061 }
4062 
4063 
4064 /*********************************************************************
4065  * Document-class: Process::Sys
4066  *
4067  * The <code>Process::Sys</code> module contains UID and GID
4068  * functions which provide direct bindings to the system calls of the
4069  * same names instead of the more-portable versions of the same
4070  * functionality found in the <code>Process</code>,
4071  * <code>Process::UID</code>, and <code>Process::GID</code> modules.
4072  */
4073 
4074 
4075 #if defined HAVE_SETUID
4076 /*
4077  * call-seq:
4078  * Process::Sys.setuid(integer) -> nil
4079  *
4080  * Set the user ID of the current process to _integer_. Not
4081  * available on all platforms.
4082  *
4083  */
4084 
4085 static VALUE
4086 p_sys_setuid(VALUE obj, VALUE id)
4087 {
4088  check_uid_switch();
4089  if (setuid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
4090  return Qnil;
4091 }
4092 #else
4093 #define p_sys_setuid rb_f_notimplement
4094 #endif
4095 
4096 
4097 #if defined HAVE_SETRUID
4098 /*
4099  * call-seq:
4100  * Process::Sys.setruid(integer) -> nil
4101  *
4102  * Set the real user ID of the calling process to _integer_.
4103  * Not available on all platforms.
4104  *
4105  */
4106 
4107 static VALUE
4108 p_sys_setruid(VALUE obj, VALUE id)
4109 {
4110  check_uid_switch();
4111  if (setruid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
4112  return Qnil;
4113 }
4114 #else
4115 #define p_sys_setruid rb_f_notimplement
4116 #endif
4117 
4118 
4119 #if defined HAVE_SETEUID
4120 /*
4121  * call-seq:
4122  * Process::Sys.seteuid(integer) -> nil
4123  *
4124  * Set the effective user ID of the calling process to
4125  * _integer_. Not available on all platforms.
4126  *
4127  */
4128 
4129 static VALUE
4130 p_sys_seteuid(VALUE obj, VALUE id)
4131 {
4132  check_uid_switch();
4133  if (seteuid(NUM2UIDT(id)) != 0) rb_sys_fail(0);
4134  return Qnil;
4135 }
4136 #else
4137 #define p_sys_seteuid rb_f_notimplement
4138 #endif
4139 
4140 
4141 #if defined HAVE_SETREUID
4142 /*
4143  * call-seq:
4144  * Process::Sys.setreuid(rid, eid) -> nil
4145  *
4146  * Sets the (integer) real and/or effective user IDs of the current
4147  * process to _rid_ and _eid_, respectively. A value of
4148  * <code>-1</code> for either means to leave that ID unchanged. Not
4149  * available on all platforms.
4150  *
4151  */
4152 
4153 static VALUE
4154 p_sys_setreuid(VALUE obj, VALUE rid, VALUE eid)
4155 {
4156  check_uid_switch();
4157  if (setreuid(NUM2UIDT(rid),NUM2UIDT(eid)) != 0) rb_sys_fail(0);
4158  return Qnil;
4159 }
4160 #else
4161 #define p_sys_setreuid rb_f_notimplement
4162 #endif
4163 
4164 
4165 #if defined HAVE_SETRESUID
4166 /*
4167  * call-seq:
4168  * Process::Sys.setresuid(rid, eid, sid) -> nil
4169  *
4170  * Sets the (integer) real, effective, and saved user IDs of the
4171  * current process to _rid_, _eid_, and _sid_ respectively. A
4172  * value of <code>-1</code> for any value means to
4173  * leave that ID unchanged. Not available on all platforms.
4174  *
4175  */
4176 
4177 static VALUE
4178 p_sys_setresuid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
4179 {
4180  check_uid_switch();
4181  if (setresuid(NUM2UIDT(rid),NUM2UIDT(eid),NUM2UIDT(sid)) != 0) rb_sys_fail(0);
4182  return Qnil;
4183 }
4184 #else
4185 #define p_sys_setresuid rb_f_notimplement
4186 #endif
4187 
4188 
4189 /*
4190  * call-seq:
4191  * Process.uid -> fixnum
4192  * Process::UID.rid -> fixnum
4193  * Process::Sys.getuid -> fixnum
4194  *
4195  * Returns the (real) user ID of this process.
4196  *
4197  * Process.uid #=> 501
4198  */
4199 
4200 static VALUE
4202 {
4203  rb_uid_t uid = getuid();
4204  return UIDT2NUM(uid);
4205 }
4206 
4207 
4208 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
4209 /*
4210  * call-seq:
4211  * Process.uid= integer -> numeric
4212  *
4213  * Sets the (integer) user ID for this process. Not available on all
4214  * platforms.
4215  */
4216 
4217 static VALUE
4218 proc_setuid(VALUE obj, VALUE id)
4219 {
4220  rb_uid_t uid;
4221 
4222  check_uid_switch();
4223 
4224  uid = NUM2UIDT(id);
4225 #if defined(HAVE_SETRESUID)
4226  if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
4227 #elif defined HAVE_SETREUID
4228  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
4229 #elif defined HAVE_SETRUID
4230  if (setruid(uid) < 0) rb_sys_fail(0);
4231 #elif defined HAVE_SETUID
4232  {
4233  if (geteuid() == uid) {
4234  if (setuid(uid) < 0) rb_sys_fail(0);
4235  }
4236  else {
4237  rb_notimplement();
4238  }
4239  }
4240 #endif
4241  return id;
4242 }
4243 #else
4244 #define proc_setuid rb_f_notimplement
4245 #endif
4246 
4247 
4248 /********************************************************************
4249  *
4250  * Document-class: Process::UID
4251  *
4252  * The <code>Process::UID</code> module contains a collection of
4253  * module functions which can be used to portably get, set, and
4254  * switch the current process's real, effective, and saved user IDs.
4255  *
4256  */
4257 
4258 static rb_uid_t SAVED_USER_ID = -1;
4259 
4260 #ifdef BROKEN_SETREUID
4261 int
4262 setreuid(rb_uid_t ruid, rb_uid_t euid)
4263 {
4264  if (ruid != (rb_uid_t)-1 && ruid != getuid()) {
4265  if (euid == (rb_uid_t)-1) euid = geteuid();
4266  if (setuid(ruid) < 0) return -1;
4267  }
4268  if (euid != (rb_uid_t)-1 && euid != geteuid()) {
4269  if (seteuid(euid) < 0) return -1;
4270  }
4271  return 0;
4272 }
4273 #endif
4274 
4275 /*
4276  * call-seq:
4277  * Process::UID.change_privilege(integer) -> fixnum
4278  *
4279  * Change the current process's real and effective user ID to that
4280  * specified by _integer_. Returns the new user ID. Not
4281  * available on all platforms.
4282  *
4283  * [Process.uid, Process.euid] #=> [0, 0]
4284  * Process::UID.change_privilege(31) #=> 31
4285  * [Process.uid, Process.euid] #=> [31, 31]
4286  */
4287 
4288 static VALUE
4290 {
4291  rb_uid_t uid;
4292 
4293  check_uid_switch();
4294 
4295  uid = NUM2UIDT(id);
4296 
4297  if (geteuid() == 0) { /* root-user */
4298 #if defined(HAVE_SETRESUID)
4299  if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
4300  SAVED_USER_ID = uid;
4301 #elif defined(HAVE_SETUID)
4302  if (setuid(uid) < 0) rb_sys_fail(0);
4303  SAVED_USER_ID = uid;
4304 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
4305  if (getuid() == uid) {
4306  if (SAVED_USER_ID == uid) {
4307  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
4308  } else {
4309  if (uid == 0) { /* (r,e,s) == (root, root, x) */
4310  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
4311  if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
4312  SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
4313  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
4314  SAVED_USER_ID = uid;
4315  } else {
4316  if (setreuid(0, -1) < 0) rb_sys_fail(0);
4317  SAVED_USER_ID = 0;
4318  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
4319  SAVED_USER_ID = uid;
4320  }
4321  }
4322  } else {
4323  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
4324  SAVED_USER_ID = uid;
4325  }
4326 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
4327  if (getuid() == uid) {
4328  if (SAVED_USER_ID == uid) {
4329  if (seteuid(uid) < 0) rb_sys_fail(0);
4330  } else {
4331  if (uid == 0) {
4332  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
4333  SAVED_USER_ID = 0;
4334  if (setruid(0) < 0) rb_sys_fail(0);
4335  } else {
4336  if (setruid(0) < 0) rb_sys_fail(0);
4337  SAVED_USER_ID = 0;
4338  if (seteuid(uid) < 0) rb_sys_fail(0);
4339  if (setruid(uid) < 0) rb_sys_fail(0);
4340  SAVED_USER_ID = uid;
4341  }
4342  }
4343  } else {
4344  if (seteuid(uid) < 0) rb_sys_fail(0);
4345  if (setruid(uid) < 0) rb_sys_fail(0);
4346  SAVED_USER_ID = uid;
4347  }
4348 #else
4349  rb_notimplement();
4350 #endif
4351  } else { /* unprivileged user */
4352 #if defined(HAVE_SETRESUID)
4353  if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
4354  (geteuid() == uid)? (rb_uid_t)-1: uid,
4355  (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
4356  SAVED_USER_ID = uid;
4357 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
4358  if (SAVED_USER_ID == uid) {
4359  if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
4360  (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
4361  rb_sys_fail(0);
4362  } else if (getuid() != uid) {
4363  if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
4364  rb_sys_fail(0);
4365  SAVED_USER_ID = uid;
4366  } else if (/* getuid() == uid && */ geteuid() != uid) {
4367  if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
4368  SAVED_USER_ID = uid;
4369  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
4370  } else { /* getuid() == uid && geteuid() == uid */
4371  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
4372  if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
4373  SAVED_USER_ID = uid;
4374  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
4375  }
4376 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
4377  if (SAVED_USER_ID == uid) {
4378  if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
4379  if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
4380  } else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
4381  if (getuid() != uid) {
4382  if (setruid(uid) < 0) rb_sys_fail(0);
4383  SAVED_USER_ID = uid;
4384  } else {
4385  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
4386  SAVED_USER_ID = uid;
4387  if (setruid(uid) < 0) rb_sys_fail(0);
4388  }
4389  } else if (/* geteuid() != uid && */ getuid() == uid) {
4390  if (seteuid(uid) < 0) rb_sys_fail(0);
4391  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
4392  SAVED_USER_ID = uid;
4393  if (setruid(uid) < 0) rb_sys_fail(0);
4394  } else {
4395  errno = EPERM;
4396  rb_sys_fail(0);
4397  }
4398 #elif defined HAVE_44BSD_SETUID
4399  if (getuid() == uid) {
4400  /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
4401  if (setuid(uid) < 0) rb_sys_fail(0);
4402  SAVED_USER_ID = uid;
4403  } else {
4404  errno = EPERM;
4405  rb_sys_fail(0);
4406  }
4407 #elif defined HAVE_SETEUID
4408  if (getuid() == uid && SAVED_USER_ID == uid) {
4409  if (seteuid(uid) < 0) rb_sys_fail(0);
4410  } else {
4411  errno = EPERM;
4412  rb_sys_fail(0);
4413  }
4414 #elif defined HAVE_SETUID
4415  if (getuid() == uid && SAVED_USER_ID == uid) {
4416  if (setuid(uid) < 0) rb_sys_fail(0);
4417  } else {
4418  errno = EPERM;
4419  rb_sys_fail(0);
4420  }
4421 #else
4422  rb_notimplement();
4423 #endif
4424  }
4425  return id;
4426 }
4427 
4428 
4429 
4430 #if defined HAVE_SETGID
4431 /*
4432  * call-seq:
4433  * Process::Sys.setgid(integer) -> nil
4434  *
4435  * Set the group ID of the current process to _integer_. Not
4436  * available on all platforms.
4437  *
4438  */
4439 
4440 static VALUE
4441 p_sys_setgid(VALUE obj, VALUE id)
4442 {
4443  check_gid_switch();
4444  if (setgid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
4445  return Qnil;
4446 }
4447 #else
4448 #define p_sys_setgid rb_f_notimplement
4449 #endif
4450 
4451 
4452 #if defined HAVE_SETRGID
4453 /*
4454  * call-seq:
4455  * Process::Sys.setrgid(integer) -> nil
4456  *
4457  * Set the real group ID of the calling process to _integer_.
4458  * Not available on all platforms.
4459  *
4460  */
4461 
4462 static VALUE
4463 p_sys_setrgid(VALUE obj, VALUE id)
4464 {
4465  check_gid_switch();
4466  if (setrgid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
4467  return Qnil;
4468 }
4469 #else
4470 #define p_sys_setrgid rb_f_notimplement
4471 #endif
4472 
4473 
4474 #if defined HAVE_SETEGID
4475 /*
4476  * call-seq:
4477  * Process::Sys.setegid(integer) -> nil
4478  *
4479  * Set the effective group ID of the calling process to
4480  * _integer_. Not available on all platforms.
4481  *
4482  */
4483 
4484 static VALUE
4485 p_sys_setegid(VALUE obj, VALUE id)
4486 {
4487  check_gid_switch();
4488  if (setegid(NUM2GIDT(id)) != 0) rb_sys_fail(0);
4489  return Qnil;
4490 }
4491 #else
4492 #define p_sys_setegid rb_f_notimplement
4493 #endif
4494 
4495 
4496 #if defined HAVE_SETREGID
4497 /*
4498  * call-seq:
4499  * Process::Sys.setregid(rid, eid) -> nil
4500  *
4501  * Sets the (integer) real and/or effective group IDs of the current
4502  * process to <em>rid</em> and <em>eid</em>, respectively. A value of
4503  * <code>-1</code> for either means to leave that ID unchanged. Not
4504  * available on all platforms.
4505  *
4506  */
4507 
4508 static VALUE
4509 p_sys_setregid(VALUE obj, VALUE rid, VALUE eid)
4510 {
4511  check_gid_switch();
4512  if (setregid(NUM2GIDT(rid),NUM2GIDT(eid)) != 0) rb_sys_fail(0);
4513  return Qnil;
4514 }
4515 #else
4516 #define p_sys_setregid rb_f_notimplement
4517 #endif
4518 
4519 #if defined HAVE_SETRESGID
4520 /*
4521  * call-seq:
4522  * Process::Sys.setresgid(rid, eid, sid) -> nil
4523  *
4524  * Sets the (integer) real, effective, and saved user IDs of the
4525  * current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
4526  * respectively. A value of <code>-1</code> for any value means to
4527  * leave that ID unchanged. Not available on all platforms.
4528  *
4529  */
4530 
4531 static VALUE
4532 p_sys_setresgid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
4533 {
4534  check_gid_switch();
4535  if (setresgid(NUM2GIDT(rid),NUM2GIDT(eid),NUM2GIDT(sid)) != 0) rb_sys_fail(0);
4536  return Qnil;
4537 }
4538 #else
4539 #define p_sys_setresgid rb_f_notimplement
4540 #endif
4541 
4542 
4543 #if defined HAVE_ISSETUGID
4544 /*
4545  * call-seq:
4546  * Process::Sys.issetugid -> true or false
4547  *
4548  * Returns +true+ if the process was created as a result
4549  * of an execve(2) system call which had either of the setuid or
4550  * setgid bits set (and extra privileges were given as a result) or
4551  * if it has changed any of its real, effective or saved user or
4552  * group IDs since it began execution.
4553  *
4554  */
4555 
4556 static VALUE
4558 {
4559  rb_secure(2);
4560  if (issetugid()) {
4561  return Qtrue;
4562  } else {
4563  return Qfalse;
4564  }
4565 }
4566 #else
4567 #define p_sys_issetugid rb_f_notimplement
4568 #endif
4569 
4570 
4571 /*
4572  * call-seq:
4573  * Process.gid -> fixnum
4574  * Process::GID.rid -> fixnum
4575  * Process::Sys.getgid -> fixnum
4576  *
4577  * Returns the (real) group ID for this process.
4578  *
4579  * Process.gid #=> 500
4580  */
4581 
4582 static VALUE
4584 {
4585  rb_gid_t gid = getgid();
4586  return GIDT2NUM(gid);
4587 }
4588 
4589 
4590 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
4591 /*
4592  * call-seq:
4593  * Process.gid= fixnum -> fixnum
4594  *
4595  * Sets the group ID for this process.
4596  */
4597 
4598 static VALUE
4599 proc_setgid(VALUE obj, VALUE id)
4600 {
4601  rb_gid_t gid;
4602 
4603  check_gid_switch();
4604 
4605  gid = NUM2GIDT(id);
4606 #if defined(HAVE_SETRESGID)
4607  if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
4608 #elif defined HAVE_SETREGID
4609  if (setregid(gid, -1) < 0) rb_sys_fail(0);
4610 #elif defined HAVE_SETRGID
4611  if (setrgid(gid) < 0) rb_sys_fail(0);
4612 #elif defined HAVE_SETGID
4613  {
4614  if (getegid() == gid) {
4615  if (setgid(gid) < 0) rb_sys_fail(0);
4616  }
4617  else {
4618  rb_notimplement();
4619  }
4620  }
4621 #endif
4622  return GIDT2NUM(gid);
4623 }
4624 #else
4625 #define proc_setgid rb_f_notimplement
4626 #endif
4627 
4628 
4629 #if defined(HAVE_SETGROUPS) || defined(HAVE_GETGROUPS)
4630 /*
4631  * Maximum supplementary groups are platform dependent.
4632  * FWIW, 65536 is enough big for our supported OSs.
4633  *
4634  * OS Name max groups
4635  * -----------------------------------------------
4636  * Linux Kernel >= 2.6.3 65536
4637  * Linux Kernel < 2.6.3 32
4638  * IBM AIX 5.2 64
4639  * IBM AIX 5.3 ... 6.1 128
4640  * IBM AIX 7.1 128 (can be configured to be up to 2048)
4641  * OpenBSD, NetBSD 16
4642  * FreeBSD < 8.0 16
4643  * FreeBSD >=8.0 1023
4644  * Darwin (Mac OS X) 16
4645  * Sun Solaris 7,8,9,10 16
4646  * Sun Solaris 11 / OpenSolaris 1024
4647  * HP-UX 20
4648  * Windows 1015
4649  */
4650 #define RB_MAX_GROUPS (65536)
4651 static int _maxgroups = -1;
4652 static int get_sc_ngroups_max(void)
4653 {
4654 #ifdef _SC_NGROUPS_MAX
4655  return (int)sysconf(_SC_NGROUPS_MAX);
4656 #elif defined(NGROUPS_MAX)
4657  return (int)NGROUPS_MAX;
4658 #else
4659  return -1;
4660 #endif
4661 }
4662 static int maxgroups(void)
4663 {
4664  if (_maxgroups < 0) {
4665  _maxgroups = get_sc_ngroups_max();
4666  if (_maxgroups < 0)
4667  _maxgroups = RB_MAX_GROUPS;
4668  }
4669 
4670  return _maxgroups;
4671 }
4672 #endif
4673 
4674 
4675 
4676 #ifdef HAVE_GETGROUPS
4677 /*
4678  * call-seq:
4679  * Process.groups -> array
4680  *
4681  * Get an <code>Array</code> of the gids of groups in the
4682  * supplemental group access list for this process.
4683  *
4684  * Process.groups #=> [27, 6, 10, 11]
4685  *
4686  */
4687 
4688 static VALUE
4689 proc_getgroups(VALUE obj)
4690 {
4691  VALUE ary;
4692  int i, ngroups;
4693  rb_gid_t *groups;
4694 
4695  ngroups = getgroups(0, NULL);
4696  if (ngroups == -1)
4697  rb_sys_fail(0);
4698 
4699  groups = ALLOCA_N(rb_gid_t, ngroups);
4700 
4701  ngroups = getgroups(ngroups, groups);
4702  if (ngroups == -1)
4703  rb_sys_fail(0);
4704 
4705  ary = rb_ary_new();
4706  for (i = 0; i < ngroups; i++)
4707  rb_ary_push(ary, GIDT2NUM(groups[i]));
4708 
4709  return ary;
4710 }
4711 #else
4712 #define proc_getgroups rb_f_notimplement
4713 #endif
4714 
4715 
4716 #ifdef HAVE_SETGROUPS
4717 /*
4718  * call-seq:
4719  * Process.groups= array -> array
4720  *
4721  * Set the supplemental group access list to the given
4722  * <code>Array</code> of group IDs.
4723  *
4724  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
4725  * Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11]
4726  * Process.groups #=> [27, 6, 10, 11]
4727  *
4728  */
4729 
4730 static VALUE
4731 proc_setgroups(VALUE obj, VALUE ary)
4732 {
4733  int ngroups, i;
4734  rb_gid_t *groups;
4735 #ifdef HAVE_GETGRNAM_R
4736  long getgr_buf_len = sysconf(_SC_GETGR_R_SIZE_MAX);
4737  char* getgr_buf;
4738 
4739  if (getgr_buf_len < 0)
4740  getgr_buf_len = 4096;
4741  getgr_buf = ALLOCA_N(char, getgr_buf_len);
4742 #endif
4743 
4744  Check_Type(ary, T_ARRAY);
4745 
4746  ngroups = RARRAY_LENINT(ary);
4747  if (ngroups > maxgroups())
4748  rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());
4749 
4750  groups = ALLOCA_N(rb_gid_t, ngroups);
4751 
4752  for (i = 0; i < ngroups; i++) {
4753  VALUE g = RARRAY_PTR(ary)[i];
4754 
4755  if (FIXNUM_P(g)) {
4756  groups[i] = NUM2GIDT(g);
4757  }
4758  else {
4759  VALUE tmp = rb_check_string_type(g);
4760  struct group grp;
4761  struct group *p;
4762  int ret;
4763 
4764  if (NIL_P(tmp)) {
4765  groups[i] = NUM2GIDT(g);
4766  }
4767  else {
4768  const char *grpname = StringValueCStr(tmp);
4769 
4770 #ifdef HAVE_GETGRNAM_R
4771  ret = getgrnam_r(grpname, &grp, getgr_buf, getgr_buf_len, &p);
4772  if (ret)
4773  rb_sys_fail("getgrnam_r");
4774 #else
4775  p = getgrnam(grpname);
4776 #endif
4777  if (p == NULL) {
4779  "can't find group for %s", RSTRING_PTR(tmp));
4780  }
4781  groups[i] = p->gr_gid;
4782  }
4783  }
4784  }
4785 
4786  if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
4787  rb_sys_fail(0);
4788 
4789  return proc_getgroups(obj);
4790 }
4791 #else
4792 #define proc_setgroups rb_f_notimplement
4793 #endif
4794 
4795 
4796 #ifdef HAVE_INITGROUPS
4797 /*
4798  * call-seq:
4799  * Process.initgroups(username, gid) -> array
4800  *
4801  * Initializes the supplemental group access list by reading the
4802  * system group database and using all groups of which the given user
4803  * is a member. The group with the specified <em>gid</em> is also
4804  * added to the list. Returns the resulting <code>Array</code> of the
4805  * gids of all the groups in the supplementary group access list. Not
4806  * available on all platforms.
4807  *
4808  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
4809  * Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
4810  * Process.groups #=> [30, 6, 10, 11]
4811  *
4812  */
4813 
4814 static VALUE
4815 proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
4816 {
4817  if (initgroups(StringValuePtr(uname), NUM2GIDT(base_grp)) != 0) {
4818  rb_sys_fail(0);
4819  }
4820  return proc_getgroups(obj);
4821 }
4822 #else
4823 #define proc_initgroups rb_f_notimplement
4824 #endif
4825 
4826 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
4827 /*
4828  * call-seq:
4829  * Process.maxgroups -> fixnum
4830  *
4831  * Returns the maximum number of gids allowed in the supplemental
4832  * group access list.
4833  *
4834  * Process.maxgroups #=> 32
4835  */
4836 
4837 static VALUE
4839 {
4840  return INT2FIX(maxgroups());
4841 }
4842 #else
4843 #define proc_getmaxgroups rb_f_notimplement
4844 #endif
4845 
4846 #ifdef HAVE_SETGROUPS
4847 /*
4848  * call-seq:
4849  * Process.maxgroups= fixnum -> fixnum
4850  *
4851  * Sets the maximum number of gids allowed in the supplemental group
4852  * access list.
4853  */
4854 
4855 static VALUE
4856 proc_setmaxgroups(VALUE obj, VALUE val)
4857 {
4858  int ngroups = FIX2INT(val);
4859  int ngroups_max = get_sc_ngroups_max();
4860 
4861  if (ngroups <= 0)
4862  rb_raise(rb_eArgError, "maxgroups %d shold be positive", ngroups);
4863 
4864  if (ngroups > RB_MAX_GROUPS)
4865  ngroups = RB_MAX_GROUPS;
4866 
4867  if (ngroups_max > 0 && ngroups > ngroups_max)
4868  ngroups = ngroups_max;
4869 
4870  _maxgroups = ngroups;
4871 
4872  return INT2FIX(_maxgroups);
4873 }
4874 #else
4875 #define proc_setmaxgroups rb_f_notimplement
4876 #endif
4877 
4878 #if defined(HAVE_DAEMON) || (defined(HAVE_FORK) && defined(HAVE_SETSID))
4879 static int rb_daemon(int nochdir, int noclose);
4880 
4881 /*
4882  * call-seq:
4883  * Process.daemon() -> 0
4884  * Process.daemon(nochdir=nil,noclose=nil) -> 0
4885  *
4886  * Detach the process from controlling terminal and run in
4887  * the background as system daemon. Unless the argument
4888  * nochdir is true (i.e. non false), it changes the current
4889  * working directory to the root ("/"). Unless the argument
4890  * noclose is true, daemon() will redirect standard input,
4891  * standard output and standard error to /dev/null.
4892  * Return zero on success, or raise one of Errno::*.
4893  */
4894 
4895 static VALUE
4896 proc_daemon(int argc, VALUE *argv)
4897 {
4898  VALUE nochdir, noclose;
4899  int n;
4900 
4901  rb_secure(2);
4902  rb_scan_args(argc, argv, "02", &nochdir, &noclose);
4903 
4904  prefork();
4905  n = rb_daemon(RTEST(nochdir), RTEST(noclose));
4906  if (n < 0) rb_sys_fail("daemon");
4907  return INT2FIX(n);
4908 }
4909 
4910 static int
4911 rb_daemon(int nochdir, int noclose)
4912 {
4913  int err = 0;
4914 #ifdef HAVE_DAEMON
4915  before_fork();
4916  err = daemon(nochdir, noclose);
4917  after_fork();
4918  rb_thread_atfork();
4919 #else
4920  int n;
4921 
4922 #define fork_daemon() \
4923  switch (rb_fork(0, 0, 0, Qnil)) { \
4924  case -1: return -1; \
4925  case 0: rb_thread_atfork(); break; \
4926  default: _exit(EXIT_SUCCESS); \
4927  }
4928 
4929  fork_daemon();
4930 
4931  if (setsid() < 0) return -1;
4932 
4933  /* must not be process-leader */
4934  fork_daemon();
4935 
4936  if (!nochdir)
4937  err = chdir("/");
4938 
4939  if (!noclose && (n = open("/dev/null", O_RDWR, 0)) != -1) {
4940  rb_update_max_fd(n);
4941  (void)dup2(n, 0);
4942  (void)dup2(n, 1);
4943  (void)dup2(n, 2);
4944  if (n > 2)
4945  (void)close (n);
4946  }
4947 #endif
4948  return err;
4949 }
4950 #else
4951 #define proc_daemon rb_f_notimplement
4952 #endif
4953 
4954 /********************************************************************
4955  *
4956  * Document-class: Process::GID
4957  *
4958  * The <code>Process::GID</code> module contains a collection of
4959  * module functions which can be used to portably get, set, and
4960  * switch the current process's real, effective, and saved group IDs.
4961  *
4962  */
4963 
4964 static rb_gid_t SAVED_GROUP_ID = -1;
4965 
4966 #ifdef BROKEN_SETREGID
4967 int
4968 setregid(rb_gid_t rgid, rb_gid_t egid)
4969 {
4970  if (rgid != (rb_gid_t)-1 && rgid != getgid()) {
4971  if (egid == (rb_gid_t)-1) egid = getegid();
4972  if (setgid(rgid) < 0) return -1;
4973  }
4974  if (egid != (rb_gid_t)-1 && egid != getegid()) {
4975  if (setegid(egid) < 0) return -1;
4976  }
4977  return 0;
4978 }
4979 #endif
4980 
4981 /*
4982  * call-seq:
4983  * Process::GID.change_privilege(integer) -> fixnum
4984  *
4985  * Change the current process's real and effective group ID to that
4986  * specified by _integer_. Returns the new group ID. Not
4987  * available on all platforms.
4988  *
4989  * [Process.gid, Process.egid] #=> [0, 0]
4990  * Process::GID.change_privilege(33) #=> 33
4991  * [Process.gid, Process.egid] #=> [33, 33]
4992  */
4993 
4994 static VALUE
4996 {
4997  rb_gid_t gid;
4998 
4999  check_gid_switch();
5000 
5001  gid = NUM2GIDT(id);
5002 
5003  if (geteuid() == 0) { /* root-user */
5004 #if defined(HAVE_SETRESGID)
5005  if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
5006  SAVED_GROUP_ID = gid;
5007 #elif defined HAVE_SETGID
5008  if (setgid(gid) < 0) rb_sys_fail(0);
5009  SAVED_GROUP_ID = gid;
5010 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5011  if (getgid() == gid) {
5012  if (SAVED_GROUP_ID == gid) {
5013  if (setregid(-1, gid) < 0) rb_sys_fail(0);
5014  } else {
5015  if (gid == 0) { /* (r,e,s) == (root, y, x) */
5016  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5017  if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
5018  SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
5019  if (setregid(gid, gid) < 0) rb_sys_fail(0);
5020  SAVED_GROUP_ID = gid;
5021  } else { /* (r,e,s) == (z, y, x) */
5022  if (setregid(0, 0) < 0) rb_sys_fail(0);
5023  SAVED_GROUP_ID = 0;
5024  if (setregid(gid, gid) < 0) rb_sys_fail(0);
5025  SAVED_GROUP_ID = gid;
5026  }
5027  }
5028  } else {
5029  if (setregid(gid, gid) < 0) rb_sys_fail(0);
5030  SAVED_GROUP_ID = gid;
5031  }
5032 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
5033  if (getgid() == gid) {
5034  if (SAVED_GROUP_ID == gid) {
5035  if (setegid(gid) < 0) rb_sys_fail(0);
5036  } else {
5037  if (gid == 0) {
5038  if (setegid(gid) < 0) rb_sys_fail(0);
5039  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5040  SAVED_GROUP_ID = 0;
5041  if (setrgid(0) < 0) rb_sys_fail(0);
5042  } else {
5043  if (setrgid(0) < 0) rb_sys_fail(0);
5044  SAVED_GROUP_ID = 0;
5045  if (setegid(gid) < 0) rb_sys_fail(0);
5046  if (setrgid(gid) < 0) rb_sys_fail(0);
5047  SAVED_GROUP_ID = gid;
5048  }
5049  }
5050  } else {
5051  if (setegid(gid) < 0) rb_sys_fail(0);
5052  if (setrgid(gid) < 0) rb_sys_fail(0);
5053  SAVED_GROUP_ID = gid;
5054  }
5055 #else
5056  rb_notimplement();
5057 #endif
5058  } else { /* unprivileged user */
5059 #if defined(HAVE_SETRESGID)
5060  if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
5061  (getegid() == gid)? (rb_gid_t)-1: gid,
5062  (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
5063  SAVED_GROUP_ID = gid;
5064 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5065  if (SAVED_GROUP_ID == gid) {
5066  if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
5067  (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5068  rb_sys_fail(0);
5069  } else if (getgid() != gid) {
5070  if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5071  rb_sys_fail(0);
5072  SAVED_GROUP_ID = gid;
5073  } else if (/* getgid() == gid && */ getegid() != gid) {
5074  if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
5075  SAVED_GROUP_ID = gid;
5076  if (setregid(gid, -1) < 0) rb_sys_fail(0);
5077  } else { /* getgid() == gid && getegid() == gid */
5078  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5079  if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
5080  SAVED_GROUP_ID = gid;
5081  if (setregid(gid, -1) < 0) rb_sys_fail(0);
5082  }
5083 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
5084  if (SAVED_GROUP_ID == gid) {
5085  if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
5086  if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
5087  } else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
5088  if (getgid() != gid) {
5089  if (setrgid(gid) < 0) rb_sys_fail(0);
5090  SAVED_GROUP_ID = gid;
5091  } else {
5092  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5093  SAVED_GROUP_ID = gid;
5094  if (setrgid(gid) < 0) rb_sys_fail(0);
5095  }
5096  } else if (/* getegid() != gid && */ getgid() == gid) {
5097  if (setegid(gid) < 0) rb_sys_fail(0);
5098  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
5099  SAVED_GROUP_ID = gid;
5100  if (setrgid(gid) < 0) rb_sys_fail(0);
5101  } else {
5102  errno = EPERM;
5103  rb_sys_fail(0);
5104  }
5105 #elif defined HAVE_44BSD_SETGID
5106  if (getgid() == gid) {
5107  /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
5108  if (setgid(gid) < 0) rb_sys_fail(0);
5109  SAVED_GROUP_ID = gid;
5110  } else {
5111  errno = EPERM;
5112  rb_sys_fail(0);
5113  }
5114 #elif defined HAVE_SETEGID
5115  if (getgid() == gid && SAVED_GROUP_ID == gid) {
5116  if (setegid(gid) < 0) rb_sys_fail(0);
5117  } else {
5118  errno = EPERM;
5119  rb_sys_fail(0);
5120  }
5121 #elif defined HAVE_SETGID
5122  if (getgid() == gid && SAVED_GROUP_ID == gid) {
5123  if (setgid(gid) < 0) rb_sys_fail(0);
5124  } else {
5125  errno = EPERM;
5126  rb_sys_fail(0);
5127  }
5128 #else
5129  rb_notimplement();
5130 #endif
5131  }
5132  return id;
5133 }
5134 
5135 
5136 /*
5137  * call-seq:
5138  * Process.euid -> fixnum
5139  * Process::UID.eid -> fixnum
5140  * Process::Sys.geteuid -> fixnum
5141  *
5142  * Returns the effective user ID for this process.
5143  *
5144  * Process.euid #=> 501
5145  */
5146 
5147 static VALUE
5149 {
5150  rb_uid_t euid = geteuid();
5151  return UIDT2NUM(euid);
5152 }
5153 
5154 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
5155 /*
5156  * call-seq:
5157  * Process.euid= integer
5158  *
5159  * Sets the effective user ID for this process. Not available on all
5160  * platforms.
5161  */
5162 
5163 static VALUE
5164 proc_seteuid(VALUE obj, VALUE euid)
5165 {
5166  rb_uid_t uid;
5167 
5168  check_uid_switch();
5169 
5170  uid = NUM2UIDT(euid);
5171 #if defined(HAVE_SETRESUID)
5172  if (setresuid(-1, uid, -1) < 0) rb_sys_fail(0);
5173 #elif defined HAVE_SETREUID
5174  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
5175 #elif defined HAVE_SETEUID
5176  if (seteuid(uid) < 0) rb_sys_fail(0);
5177 #elif defined HAVE_SETUID
5178  if (uid == getuid()) {
5179  if (setuid(uid) < 0) rb_sys_fail(0);
5180  }
5181  else {
5182  rb_notimplement();
5183  }
5184 #else
5185  rb_notimplement();
5186 #endif
5187  return euid;
5188 }
5189 #endif
5190 
5191 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
5192 #define proc_seteuid_m proc_seteuid
5193 #else
5194 #define proc_seteuid_m rb_f_notimplement
5195 #endif
5196 
5197 static rb_uid_t
5198 rb_seteuid_core(rb_uid_t euid)
5199 {
5200  rb_uid_t uid;
5201 
5202  check_uid_switch();
5203 
5204  uid = getuid();
5205 
5206 #if defined(HAVE_SETRESUID)
5207  if (uid != euid) {
5208  if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
5209  SAVED_USER_ID = euid;
5210  } else {
5211  if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
5212  }
5213 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5214  if (setreuid(-1, euid) < 0) rb_sys_fail(0);
5215  if (uid != euid) {
5216  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
5217  if (setreuid(uid,euid) < 0) rb_sys_fail(0);
5218  SAVED_USER_ID = euid;
5219  }
5220 #elif defined HAVE_SETEUID
5221  if (seteuid(euid) < 0) rb_sys_fail(0);
5222 #elif defined HAVE_SETUID
5223  if (geteuid() == 0) rb_sys_fail(0);
5224  if (setuid(euid) < 0) rb_sys_fail(0);
5225 #else
5226  rb_notimplement();
5227 #endif
5228  return euid;
5229 }
5230 
5231 
5232 /*
5233  * call-seq:
5234  * Process::UID.grant_privilege(integer) -> fixnum
5235  * Process::UID.eid= integer -> fixnum
5236  *
5237  * Set the effective user ID, and if possible, the saved user ID of
5238  * the process to the given _integer_. Returns the new
5239  * effective user ID. Not available on all platforms.
5240  *
5241  * [Process.uid, Process.euid] #=> [0, 0]
5242  * Process::UID.grant_privilege(31) #=> 31
5243  * [Process.uid, Process.euid] #=> [0, 31]
5244  */
5245 
5246 static VALUE
5248 {
5250  return id;
5251 }
5252 
5253 
5254 /*
5255  * call-seq:
5256  * Process.egid -> fixnum
5257  * Process::GID.eid -> fixnum
5258  * Process::Sys.geteid -> fixnum
5259  *
5260  * Returns the effective group ID for this process. Not available on
5261  * all platforms.
5262  *
5263  * Process.egid #=> 500
5264  */
5265 
5266 static VALUE
5268 {
5269  rb_gid_t egid = getegid();
5270 
5271  return GIDT2NUM(egid);
5272 }
5273 
5274 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
5275 /*
5276  * call-seq:
5277  * Process.egid = fixnum -> fixnum
5278  *
5279  * Sets the effective group ID for this process. Not available on all
5280  * platforms.
5281  */
5282 
5283 static VALUE
5284 proc_setegid(VALUE obj, VALUE egid)
5285 {
5286  rb_gid_t gid;
5287 
5288  check_gid_switch();
5289 
5290  gid = NUM2GIDT(egid);
5291 #if defined(HAVE_SETRESGID)
5292  if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
5293 #elif defined HAVE_SETREGID
5294  if (setregid(-1, gid) < 0) rb_sys_fail(0);
5295 #elif defined HAVE_SETEGID
5296  if (setegid(gid) < 0) rb_sys_fail(0);
5297 #elif defined HAVE_SETGID
5298  if (gid == getgid()) {
5299  if (setgid(gid) < 0) rb_sys_fail(0);
5300  }
5301  else {
5302  rb_notimplement();
5303  }
5304 #else
5305  rb_notimplement();
5306 #endif
5307  return egid;
5308 }
5309 #endif
5310 
5311 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
5312 #define proc_setegid_m proc_setegid
5313 #else
5314 #define proc_setegid_m rb_f_notimplement
5315 #endif
5316 
5317 static rb_gid_t
5318 rb_setegid_core(rb_gid_t egid)
5319 {
5320  rb_gid_t gid;
5321 
5322  check_gid_switch();
5323 
5324  gid = getgid();
5325 
5326 #if defined(HAVE_SETRESGID)
5327  if (gid != egid) {
5328  if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
5329  SAVED_GROUP_ID = egid;
5330  } else {
5331  if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
5332  }
5333 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5334  if (setregid(-1, egid) < 0) rb_sys_fail(0);
5335  if (gid != egid) {
5336  if (setregid(egid,gid) < 0) rb_sys_fail(0);
5337  if (setregid(gid,egid) < 0) rb_sys_fail(0);
5338  SAVED_GROUP_ID = egid;
5339  }
5340 #elif defined HAVE_SETEGID
5341  if (setegid(egid) < 0) rb_sys_fail(0);
5342 #elif defined HAVE_SETGID
5343  if (geteuid() == 0 /* root user */) rb_sys_fail(0);
5344  if (setgid(egid) < 0) rb_sys_fail(0);
5345 #else
5346  rb_notimplement();
5347 #endif
5348  return egid;
5349 }
5350 
5351 
5352 /*
5353  * call-seq:
5354  * Process::GID.grant_privilege(integer) -> fixnum
5355  * Process::GID.eid = integer -> fixnum
5356  *
5357  * Set the effective group ID, and if possible, the saved group ID of
5358  * the process to the given _integer_. Returns the new
5359  * effective group ID. Not available on all platforms.
5360  *
5361  * [Process.gid, Process.egid] #=> [0, 0]
5362  * Process::GID.grant_privilege(31) #=> 33
5363  * [Process.gid, Process.egid] #=> [0, 33]
5364  */
5365 
5366 static VALUE
5368 {
5370  return id;
5371 }
5372 
5373 
5374 /*
5375  * call-seq:
5376  * Process::UID.re_exchangeable? -> true or false
5377  *
5378  * Returns +true+ if the real and effective user IDs of a
5379  * process may be exchanged on the current platform.
5380  *
5381  */
5382 
5383 static VALUE
5385 {
5386 #if defined(HAVE_SETRESUID)
5387  return Qtrue;
5388 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5389  return Qtrue;
5390 #else
5391  return Qfalse;
5392 #endif
5393 }
5394 
5395 
5396 /*
5397  * call-seq:
5398  * Process::UID.re_exchange -> fixnum
5399  *
5400  * Exchange real and effective user IDs and return the new effective
5401  * user ID. Not available on all platforms.
5402  *
5403  * [Process.uid, Process.euid] #=> [0, 31]
5404  * Process::UID.re_exchange #=> 0
5405  * [Process.uid, Process.euid] #=> [31, 0]
5406  */
5407 
5408 static VALUE
5410 {
5411  rb_uid_t uid, euid;
5412 
5413  check_uid_switch();
5414 
5415  uid = getuid();
5416  euid = geteuid();
5417 
5418 #if defined(HAVE_SETRESUID)
5419  if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
5420  SAVED_USER_ID = uid;
5421 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5422  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
5423  SAVED_USER_ID = uid;
5424 #else
5425  rb_notimplement();
5426 #endif
5427  return UIDT2NUM(uid);
5428 }
5429 
5430 
5431 /*
5432  * call-seq:
5433  * Process::GID.re_exchangeable? -> true or false
5434  *
5435  * Returns +true+ if the real and effective group IDs of a
5436  * process may be exchanged on the current platform.
5437  *
5438  */
5439 
5440 static VALUE
5442 {
5443 #if defined(HAVE_SETRESGID)
5444  return Qtrue;
5445 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5446  return Qtrue;
5447 #else
5448  return Qfalse;
5449 #endif
5450 }
5451 
5452 
5453 /*
5454  * call-seq:
5455  * Process::GID.re_exchange -> fixnum
5456  *
5457  * Exchange real and effective group IDs and return the new effective
5458  * group ID. Not available on all platforms.
5459  *
5460  * [Process.gid, Process.egid] #=> [0, 33]
5461  * Process::GID.re_exchange #=> 0
5462  * [Process.gid, Process.egid] #=> [33, 0]
5463  */
5464 
5465 static VALUE
5467 {
5468  rb_gid_t gid, egid;
5469 
5470  check_gid_switch();
5471 
5472  gid = getgid();
5473  egid = getegid();
5474 
5475 #if defined(HAVE_SETRESGID)
5476  if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
5477  SAVED_GROUP_ID = gid;
5478 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5479  if (setregid(egid,gid) < 0) rb_sys_fail(0);
5480  SAVED_GROUP_ID = gid;
5481 #else
5482  rb_notimplement();
5483 #endif
5484  return GIDT2NUM(gid);
5485 }
5486 
5487 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
5488 
5489 /*
5490  * call-seq:
5491  * Process::UID.sid_available? -> true or false
5492  *
5493  * Returns +true+ if the current platform has saved user
5494  * ID functionality.
5495  *
5496  */
5497 
5498 static VALUE
5500 {
5501 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
5502  return Qtrue;
5503 #else
5504  return Qfalse;
5505 #endif
5506 }
5507 
5508 
5509 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
5510 static VALUE
5511 p_uid_sw_ensure(rb_uid_t id)
5512 {
5513  under_uid_switch = 0;
5514  id = rb_seteuid_core(id);
5515  return UIDT2NUM(id);
5516 }
5517 
5518 
5519 /*
5520  * call-seq:
5521  * Process::UID.switch -> fixnum
5522  * Process::UID.switch {|| block} -> object
5523  *
5524  * Switch the effective and real user IDs of the current process. If
5525  * a <em>block</em> is given, the user IDs will be switched back
5526  * after the block is executed. Returns the new effective user ID if
5527  * called without a block, and the return value of the block if one
5528  * is given.
5529  *
5530  */
5531 
5532 static VALUE
5533 p_uid_switch(VALUE obj)
5534 {
5535  rb_uid_t uid, euid;
5536 
5537  check_uid_switch();
5538 
5539  uid = getuid();
5540  euid = geteuid();
5541 
5542  if (uid != euid) {
5543  proc_seteuid(obj, UIDT2NUM(uid));
5544  if (rb_block_given_p()) {
5545  under_uid_switch = 1;
5546  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
5547  } else {
5548  return UIDT2NUM(euid);
5549  }
5550  } else if (euid != SAVED_USER_ID) {
5551  proc_seteuid(obj, UIDT2NUM(SAVED_USER_ID));
5552  if (rb_block_given_p()) {
5553  under_uid_switch = 1;
5554  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
5555  } else {
5556  return UIDT2NUM(uid);
5557  }
5558  } else {
5559  errno = EPERM;
5560  rb_sys_fail(0);
5561  }
5562 }
5563 #else
5564 static VALUE
5566 {
5567  under_uid_switch = 0;
5568  return p_uid_exchange(obj);
5569 }
5570 
5571 static VALUE
5573 {
5574  rb_uid_t uid, euid;
5575 
5576  check_uid_switch();
5577 
5578  uid = getuid();
5579  euid = geteuid();
5580 
5581  if (uid == euid) {
5582  errno = EPERM;
5583  rb_sys_fail(0);
5584  }
5585  p_uid_exchange(obj);
5586  if (rb_block_given_p()) {
5587  under_uid_switch = 1;
5588  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
5589  } else {
5590  return UIDT2NUM(euid);
5591  }
5592 }
5593 #endif
5594 
5595 
5596 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
5597 
5598 /*
5599  * call-seq:
5600  * Process::GID.sid_available? -> true or false
5601  *
5602  * Returns +true+ if the current platform has saved group
5603  * ID functionality.
5604  *
5605  */
5606 
5607 static VALUE
5609 {
5610 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
5611  return Qtrue;
5612 #else
5613  return Qfalse;
5614 #endif
5615 }
5616 
5617 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
5618 static VALUE
5619 p_gid_sw_ensure(rb_gid_t id)
5620 {
5621  under_gid_switch = 0;
5622  id = rb_setegid_core(id);
5623  return GIDT2NUM(id);
5624 }
5625 
5626 
5627 /*
5628  * call-seq:
5629  * Process::GID.switch -> fixnum
5630  * Process::GID.switch {|| block} -> object
5631  *
5632  * Switch the effective and real group IDs of the current process. If
5633  * a <em>block</em> is given, the group IDs will be switched back
5634  * after the block is executed. Returns the new effective group ID if
5635  * called without a block, and the return value of the block if one
5636  * is given.
5637  *
5638  */
5639 
5640 static VALUE
5641 p_gid_switch(VALUE obj)
5642 {
5643  rb_gid_t gid, egid;
5644 
5645  check_gid_switch();
5646 
5647  gid = getgid();
5648  egid = getegid();
5649 
5650  if (gid != egid) {
5651  proc_setegid(obj, GIDT2NUM(gid));
5652  if (rb_block_given_p()) {
5653  under_gid_switch = 1;
5654  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
5655  } else {
5656  return GIDT2NUM(egid);
5657  }
5658  }
5659  else if (egid != SAVED_GROUP_ID) {
5660  proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
5661  if (rb_block_given_p()) {
5662  under_gid_switch = 1;
5663  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
5664  } else {
5665  return GIDT2NUM(gid);
5666  }
5667  }
5668  else {
5669  errno = EPERM;
5670  rb_sys_fail(0);
5671  }
5672 }
5673 #else
5674 static VALUE
5676 {
5677  under_gid_switch = 0;
5678  return p_gid_exchange(obj);
5679 }
5680 
5681 static VALUE
5683 {
5684  rb_gid_t gid, egid;
5685 
5686  check_gid_switch();
5687 
5688  gid = getgid();
5689  egid = getegid();
5690 
5691  if (gid == egid) {
5692  errno = EPERM;
5693  rb_sys_fail(0);
5694  }
5695  p_gid_exchange(obj);
5696  if (rb_block_given_p()) {
5697  under_gid_switch = 1;
5698  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
5699  } else {
5700  return GIDT2NUM(egid);
5701  }
5702 }
5703 #endif
5704 
5705 
5706 #if defined(HAVE_TIMES)
5707 /*
5708  * call-seq:
5709  * Process.times -> aStructTms
5710  *
5711  * Returns a <code>Tms</code> structure (see <code>Struct::Tms</code>)
5712  * that contains user and system CPU times for this process,
5713  * and also for children processes.
5714  *
5715  * t = Process.times
5716  * [ t.utime, t.stime, t.cutime, t.cstime ] #=> [0.0, 0.02, 0.00, 0.00]
5717  */
5718 
5719 VALUE
5720 rb_proc_times(VALUE obj)
5721 {
5722  const double hertz =
5723 #ifdef HAVE__SC_CLK_TCK
5724  (double)sysconf(_SC_CLK_TCK);
5725 #else
5726 #ifndef HZ
5727 # ifdef CLK_TCK
5728 # define HZ CLK_TCK
5729 # else
5730 # define HZ 60
5731 # endif
5732 #endif /* HZ */
5733  HZ;
5734 #endif
5735  struct tms buf;
5736  volatile VALUE utime, stime, cutime, sctime;
5737 
5738  times(&buf);
5739  return rb_struct_new(rb_cProcessTms,
5740  utime = DBL2NUM(buf.tms_utime / hertz),
5741  stime = DBL2NUM(buf.tms_stime / hertz),
5742  cutime = DBL2NUM(buf.tms_cutime / hertz),
5743  sctime = DBL2NUM(buf.tms_cstime / hertz));
5744 }
5745 #else
5746 #define rb_proc_times rb_f_notimplement
5747 #endif
5748 
5753 
5754 
5755 /*
5756  * The <code>Process</code> module is a collection of methods used to
5757  * manipulate processes.
5758  */
5759 
5760 void
5762 {
5765  rb_define_global_function("exec", rb_f_exec, -1);
5768  rb_define_global_function("system", rb_f_system, -1);
5769  rb_define_global_function("spawn", rb_f_spawn, -1);
5770  rb_define_global_function("sleep", rb_f_sleep, -1);
5771  rb_define_global_function("exit", rb_f_exit, -1);
5772  rb_define_global_function("abort", rb_f_abort, -1);
5773 
5774  rb_mProcess = rb_define_module("Process");
5775 
5776 #ifdef WNOHANG
5777  /* see Process.wait */
5778  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
5779 #else
5780  /* see Process.wait */
5781  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
5782 #endif
5783 #ifdef WUNTRACED
5784  /* see Process.wait */
5785  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
5786 #else
5787  /* see Process.wait */
5788  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
5789 #endif
5790 
5791  rb_define_singleton_method(rb_mProcess, "exec", rb_f_exec, -1);
5792  rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
5793  rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
5794  rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
5795  rb_define_singleton_method(rb_mProcess, "exit", rb_f_exit, -1);
5796  rb_define_singleton_method(rb_mProcess, "abort", rb_f_abort, -1);
5797 
5798  rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1); /* in signal.c */
5799  rb_define_module_function(rb_mProcess, "wait", proc_wait, -1);
5800  rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
5801  rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
5802  rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
5803  rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
5804  rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
5805 
5806  rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
5808 
5815 
5817 
5826 
5827  rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
5828  rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
5829 
5830  rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, 0);
5831  rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, 0);
5832  rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
5833  rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
5834 
5835  rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
5836 
5837  rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
5838  rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
5839 
5840 #ifdef HAVE_GETPRIORITY
5841  /* see Process.setpriority */
5842  rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
5843  /* see Process.setpriority */
5844  rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
5845  /* see Process.setpriority */
5846  rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
5847 #endif
5848 
5849  rb_define_module_function(rb_mProcess, "getrlimit", proc_getrlimit, 1);
5850  rb_define_module_function(rb_mProcess, "setrlimit", proc_setrlimit, -1);
5851 #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
5852  {
5853  VALUE inf = RLIM2NUM(RLIM_INFINITY);
5854 #ifdef RLIM_SAVED_MAX
5855  {
5856  VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
5857  /* see Process.setrlimit */
5858  rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
5859  }
5860 #endif
5861  /* see Process.setrlimit */
5862  rb_define_const(rb_mProcess, "RLIM_INFINITY", inf);
5863 #ifdef RLIM_SAVED_CUR
5864  {
5865  VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
5866  /* see Process.setrlimit */
5867  rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
5868  }
5869 #endif
5870  }
5871 #ifdef RLIMIT_AS
5872  /* Maximum size of the process's virtual memory (address space) in bytes.
5873  *
5874  * see the system getrlimit(2) manual for details.
5875  */
5876  rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
5877 #endif
5878 #ifdef RLIMIT_CORE
5879  /* Maximum size of the core file.
5880  *
5881  * see the system getrlimit(2) manual for details.
5882  */
5883  rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
5884 #endif
5885 #ifdef RLIMIT_CPU
5886  /* CPU time limit in seconds.
5887  *
5888  * see the system getrlimit(2) manual for details.
5889  */
5890  rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
5891 #endif
5892 #ifdef RLIMIT_DATA
5893  /* Maximum size of the process's data segment.
5894  *
5895  * see the system getrlimit(2) manual for details.
5896  */
5897  rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
5898 #endif
5899 #ifdef RLIMIT_FSIZE
5900  /* Maximum size of files that the process may create.
5901  *
5902  * see the system getrlimit(2) manual for details.
5903  */
5904  rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
5905 #endif
5906 #ifdef RLIMIT_MEMLOCK
5907  /* Maximum number of bytes of memory that may be locked into RAM.
5908  *
5909  * see the system getrlimit(2) manual for details.
5910  */
5911  rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
5912 #endif
5913 #ifdef RLIMIT_MSGQUEUE
5914  /* Specifies the limit on the number of bytes that can be allocated
5915  * for POSIX message queues for the real user ID of the calling process.
5916  *
5917  * see the system getrlimit(2) manual for details.
5918  */
5919  rb_define_const(rb_mProcess, "RLIMIT_MSGQUEUE", INT2FIX(RLIMIT_MSGQUEUE));
5920 #endif
5921 #ifdef RLIMIT_NICE
5922  /* Specifies a ceiling to which the process's nice value can be raised.
5923  *
5924  * see the system getrlimit(2) manual for details.
5925  */
5926  rb_define_const(rb_mProcess, "RLIMIT_NICE", INT2FIX(RLIMIT_NICE));
5927 #endif
5928 #ifdef RLIMIT_NOFILE
5929  /* Specifies a value one greater than the maximum file descriptor
5930  * number that can be opened by this process.
5931  *
5932  * see the system getrlimit(2) manual for details.
5933  */
5934  rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
5935 #endif
5936 #ifdef RLIMIT_NPROC
5937  /* The maximum number of processes that can be created for the
5938  * real user ID of the calling process.
5939  *
5940  * see the system getrlimit(2) manual for details.
5941  */
5942  rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
5943 #endif
5944 #ifdef RLIMIT_RSS
5945  /* Specifies the limit (in pages) of the process's resident set.
5946  *
5947  * see the system getrlimit(2) manual for details.
5948  */
5949  rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
5950 #endif
5951 #ifdef RLIMIT_RTPRIO
5952  /* Specifies a ceiling on the real-time priority that may be set for this process.
5953  *
5954  * see the system getrlimit(2) manual for details.
5955  */
5956  rb_define_const(rb_mProcess, "RLIMIT_RTPRIO", INT2FIX(RLIMIT_RTPRIO));
5957 #endif
5958 #ifdef RLIMIT_RTTIME
5959  /* Specifies limit on CPU time this process scheduled under a real-time
5960  * scheduling policy can consume.
5961  *
5962  * see the system getrlimit(2) manual for details.
5963  */
5964  rb_define_const(rb_mProcess, "RLIMIT_RTTIME", INT2FIX(RLIMIT_RTTIME));
5965 #endif
5966 #ifdef RLIMIT_SBSIZE
5967  /* Maximum size of the socket buffer.
5968  */
5969  rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
5970 #endif
5971 #ifdef RLIMIT_SIGPENDING
5972  /* Specifies a limit on the number of signals that may be queued for
5973  * the real user ID of the calling process.
5974  *
5975  * see the system getrlimit(2) manual for details.
5976  */
5977  rb_define_const(rb_mProcess, "RLIMIT_SIGPENDING", INT2FIX(RLIMIT_SIGPENDING));
5978 #endif
5979 #ifdef RLIMIT_STACK
5980  /* Maximum size of the stack, in bytes.
5981  *
5982  * see the system getrlimit(2) manual for details.
5983  */
5984  rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
5985 #endif
5986 #endif
5987 
5988  rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
5989  rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
5990  rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
5991  rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
5992  rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
5993  rb_define_module_function(rb_mProcess, "euid=", proc_seteuid_m, 1);
5994  rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
5995  rb_define_module_function(rb_mProcess, "egid=", proc_setegid_m, 1);
5996  rb_define_module_function(rb_mProcess, "initgroups", proc_initgroups, 2);
5997  rb_define_module_function(rb_mProcess, "groups", proc_getgroups, 0);
5998  rb_define_module_function(rb_mProcess, "groups=", proc_setgroups, 1);
5999  rb_define_module_function(rb_mProcess, "maxgroups", proc_getmaxgroups, 0);
6000  rb_define_module_function(rb_mProcess, "maxgroups=", proc_setmaxgroups, 1);
6001 
6002  rb_define_module_function(rb_mProcess, "daemon", proc_daemon, -1);
6003 
6004  rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
6005 
6006 #if defined(HAVE_TIMES) || defined(_WIN32)
6007  rb_cProcessTms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", NULL);
6008 #endif
6009 
6010  SAVED_USER_ID = geteuid();
6011  SAVED_GROUP_ID = getegid();
6012 
6013  rb_mProcUID = rb_define_module_under(rb_mProcess, "UID");
6014  rb_mProcGID = rb_define_module_under(rb_mProcess, "GID");
6015 
6016  rb_define_module_function(rb_mProcUID, "rid", proc_getuid, 0);
6017  rb_define_module_function(rb_mProcGID, "rid", proc_getgid, 0);
6018  rb_define_module_function(rb_mProcUID, "eid", proc_geteuid, 0);
6019  rb_define_module_function(rb_mProcGID, "eid", proc_getegid, 0);
6020  rb_define_module_function(rb_mProcUID, "change_privilege", p_uid_change_privilege, 1);
6021  rb_define_module_function(rb_mProcGID, "change_privilege", p_gid_change_privilege, 1);
6022  rb_define_module_function(rb_mProcUID, "grant_privilege", p_uid_grant_privilege, 1);
6023  rb_define_module_function(rb_mProcGID, "grant_privilege", p_gid_grant_privilege, 1);
6024  rb_define_alias(rb_singleton_class(rb_mProcUID), "eid=", "grant_privilege");
6025  rb_define_alias(rb_singleton_class(rb_mProcGID), "eid=", "grant_privilege");
6026  rb_define_module_function(rb_mProcUID, "re_exchange", p_uid_exchange, 0);
6027  rb_define_module_function(rb_mProcGID, "re_exchange", p_gid_exchange, 0);
6028  rb_define_module_function(rb_mProcUID, "re_exchangeable?", p_uid_exchangeable, 0);
6029  rb_define_module_function(rb_mProcGID, "re_exchangeable?", p_gid_exchangeable, 0);
6030  rb_define_module_function(rb_mProcUID, "sid_available?", p_uid_have_saved_id, 0);
6031  rb_define_module_function(rb_mProcGID, "sid_available?", p_gid_have_saved_id, 0);
6032  rb_define_module_function(rb_mProcUID, "switch", p_uid_switch, 0);
6033  rb_define_module_function(rb_mProcGID, "switch", p_gid_switch, 0);
6034 
6035  rb_mProcID_Syscall = rb_define_module_under(rb_mProcess, "Sys");
6036 
6037  rb_define_module_function(rb_mProcID_Syscall, "getuid", proc_getuid, 0);
6038  rb_define_module_function(rb_mProcID_Syscall, "geteuid", proc_geteuid, 0);
6039  rb_define_module_function(rb_mProcID_Syscall, "getgid", proc_getgid, 0);
6040  rb_define_module_function(rb_mProcID_Syscall, "getegid", proc_getegid, 0);
6041 
6042  rb_define_module_function(rb_mProcID_Syscall, "setuid", p_sys_setuid, 1);
6043  rb_define_module_function(rb_mProcID_Syscall, "setgid", p_sys_setgid, 1);
6044 
6045  rb_define_module_function(rb_mProcID_Syscall, "setruid", p_sys_setruid, 1);
6046  rb_define_module_function(rb_mProcID_Syscall, "setrgid", p_sys_setrgid, 1);
6047 
6048  rb_define_module_function(rb_mProcID_Syscall, "seteuid", p_sys_seteuid, 1);
6049  rb_define_module_function(rb_mProcID_Syscall, "setegid", p_sys_setegid, 1);
6050 
6051  rb_define_module_function(rb_mProcID_Syscall, "setreuid", p_sys_setreuid, 2);
6052  rb_define_module_function(rb_mProcID_Syscall, "setregid", p_sys_setregid, 2);
6053 
6054  rb_define_module_function(rb_mProcID_Syscall, "setresuid", p_sys_setresuid, 3);
6055  rb_define_module_function(rb_mProcID_Syscall, "setresgid", p_sys_setresgid, 3);
6056  rb_define_module_function(rb_mProcID_Syscall, "issetugid", p_sys_issetugid, 0);
6057 }
6058