Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals

process.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   process.c -
00004 
00005   $Author: akr $
00006   $Date: 2005/11/20 03:30:47 $
00007   created at: Tue Aug 10 14:30:50 JST 1993
00008 
00009   Copyright (C) 1993-2003 Yukihiro Matsumoto
00010   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
00011   Copyright (C) 2000  Information-technology Promotion Agency, Japan
00012 
00013 **********************************************************************/
00014 
00015 #include "ruby.h"
00016 #include "rubysig.h"
00017 #include <stdio.h>
00018 #include <errno.h>
00019 #include <signal.h>
00020 #ifdef HAVE_STDLIB_H
00021 #include <stdlib.h>
00022 #endif
00023 #ifdef HAVE_UNISTD_H
00024 #include <unistd.h>
00025 #endif
00026 #ifdef __DJGPP__
00027 #include <process.h>
00028 #endif
00029 
00030 #include <time.h>
00031 #include <ctype.h>
00032 
00033 #ifndef EXIT_SUCCESS
00034 #define EXIT_SUCCESS 0
00035 #endif
00036 #ifndef EXIT_FAILURE
00037 #define EXIT_FAILURE 1
00038 #endif
00039 
00040 struct timeval rb_time_interval (VALUE);
00041 
00042 #ifdef HAVE_SYS_WAIT_H
00043 # include <sys/wait.h>
00044 #endif
00045 #ifdef HAVE_GETPRIORITY
00046 # include <sys/resource.h>
00047 #endif
00048 #include "st.h"
00049 
00050 #ifdef __EMX__
00051 #undef HAVE_GETPGRP
00052 #endif
00053 
00054 #ifdef HAVE_SYS_TIMES_H
00055 #include <sys/times.h>
00056 #endif
00057 
00058 #ifdef HAVE_GRP_H
00059 #include <grp.h>
00060 #endif
00061 
00062 #if defined(HAVE_TIMES) || defined(_WIN32)
00063 static VALUE S_Tms;
00064 #endif
00065 
00066 #ifndef WIFEXITED
00067 #define WIFEXITED(w)    (((w) & 0xff) == 0)
00068 #endif
00069 #ifndef WIFSIGNALED
00070 #define WIFSIGNALED(w)  (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
00071 #endif
00072 #ifndef WIFSTOPPED
00073 #define WIFSTOPPED(w)   (((w) & 0xff) == 0x7f)
00074 #endif
00075 #ifndef WEXITSTATUS
00076 #define WEXITSTATUS(w)  (((w) >> 8) & 0xff)
00077 #endif
00078 #ifndef WTERMSIG
00079 #define WTERMSIG(w)     ((w) & 0x7f)
00080 #endif
00081 #ifndef WSTOPSIG
00082 #define WSTOPSIG        WEXITSTATUS
00083 #endif
00084 
00085 #if defined(__APPLE__) && ( defined(__MACH__) || defined(__DARWIN__) ) && !defined(__MacOS_X__)
00086 #define __MacOS_X__ 1
00087 #endif
00088 
00089 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
00090 #define HAVE_44BSD_SETUID 1
00091 #define HAVE_44BSD_SETGID 1
00092 #endif
00093 
00094 #ifdef __NetBSD__
00095 #undef HAVE_SETRUID
00096 #undef HAVE_SETRGID
00097 #endif
00098 
00099 #if defined(__MacOS_X__) || defined(__bsdi__)
00100 #define BROKEN_SETREUID 1
00101 #define BROKEN_SETREGID 1
00102 #endif
00103 
00104 #if defined(HAVE_44BSD_SETUID) || defined(__MacOS_X__)
00105 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
00106 #define OBSOLETE_SETREUID 1
00107 #endif
00108 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
00109 #define OBSOLETE_SETREGID 1
00110 #endif
00111 #endif
00112 
00113 
00114 /*
00115  *  call-seq:
00116  *     Process.pid   => fixnum
00117  *
00118  *  Returns the process id of this process. Not available on all
00119  *  platforms.
00120  *
00121  *     Process.pid   #=> 27415
00122  */
00123 
00124 static VALUE
00125 get_pid()
00126 {
00127     rb_secure(2);
00128     return INT2FIX(getpid());
00129 }
00130 
00131 
00132 /*
00133  *  call-seq:
00134  *     Process.ppid   => fixnum
00135  *
00136  *  Returns the process id of the parent of this process. Always
00137  *  returns 0 on NT. Not available on all platforms.
00138  *
00139  *     puts "I am #{Process.pid}"
00140  *     Process.fork { puts "Dad is #{Process.ppid}" }
00141  *
00142  *  <em>produces:</em>
00143  *
00144  *     I am 27417
00145  *     Dad is 27417
00146  */
00147 
00148 static VALUE
00149 get_ppid()
00150 {
00151     rb_secure(2);
00152 #ifdef _WIN32
00153     return INT2FIX(0);
00154 #else
00155     return INT2FIX(getppid());
00156 #endif
00157 }
00158 
00159 
00160 /*********************************************************************
00161  *
00162  * Document-class: Process::Status
00163  *
00164  *  <code>Process::Status</code> encapsulates the information on the
00165  *  status of a running or terminated system process. The built-in
00166  *  variable <code>$?</code> is either +nil+ or a
00167  *  <code>Process::Status</code> object.
00168  *
00169  *     fork { exit 99 }   #=> 26557
00170  *     Process.wait       #=> 26557
00171  *     $?.class           #=> Process::Status
00172  *     $?.to_i            #=> 25344
00173  *     $? >> 8            #=> 99
00174  *     $?.stopped?        #=> false
00175  *     $?.exited?         #=> true
00176  *     $?.exitstatus      #=> 99
00177  *
00178  *  Posix systems record information on processes using a 16-bit
00179  *  integer.  The lower bits record the process status (stopped,
00180  *  exited, signaled) and the upper bits possibly contain additional
00181  *  information (for example the program's return code in the case of
00182  *  exited processes). Pre Ruby 1.8, these bits were exposed directly
00183  *  to the Ruby program. Ruby now encapsulates these in a
00184  *  <code>Process::Status</code> object. To maximize compatibility,
00185  *  however, these objects retain a bit-oriented interface. In the
00186  *  descriptions that follow, when we talk about the integer value of
00187  *  _stat_, we're referring to this 16 bit value.
00188  */
00189 
00190 static VALUE rb_cProcStatus;
00191 VALUE rb_last_status = Qnil;
00192 
00193 static void
00194 last_status_set(status, pid)
00195     int status, pid;
00196 {
00197     rb_last_status = rb_obj_alloc(rb_cProcStatus);
00198     rb_iv_set(rb_last_status, "status", INT2FIX(status));
00199     rb_iv_set(rb_last_status, "pid", INT2FIX(pid));
00200 }
00201 
00202 
00203 /*
00204  *  call-seq:
00205  *     stat.to_i     => fixnum
00206  *     stat.to_int   => fixnum
00207  *
00208  *  Returns the bits in _stat_ as a <code>Fixnum</code>. Poking
00209  *  around in these bits is platform dependent.
00210  *
00211  *     fork { exit 0xab }         #=> 26566
00212  *     Process.wait               #=> 26566
00213  *     sprintf('%04x', $?.to_i)   #=> "ab00"
00214  */
00215 
00216 static VALUE
00217 pst_to_i(st)
00218     VALUE st;
00219 {
00220     return rb_iv_get(st, "status");
00221 }
00222 
00223 
00224 /*
00225  *  call-seq:
00226  *     stat.to_s   => string
00227  *
00228  *  Equivalent to _stat_<code>.to_i.to_s</code>.
00229  */
00230 
00231 static VALUE
00232 pst_to_s(st)
00233     VALUE st;
00234 {
00235     return rb_fix2str(pst_to_i(st), 10);
00236 }
00237 
00238 
00239 /*
00240  *  call-seq:
00241  *     stat.pid   => fixnum
00242  *
00243  *  Returns the process ID that this status object represents.
00244  *
00245  *     fork { exit }   #=> 26569
00246  *     Process.wait    #=> 26569
00247  *     $?.pid          #=> 26569
00248  */
00249 
00250 static VALUE
00251 pst_pid(st)
00252     VALUE st;
00253 {
00254     return rb_iv_get(st, "pid");
00255 }
00256 
00257 
00258 /*
00259  *  call-seq:
00260  *     stat.inspect   => string
00261  *
00262  *  Override the inspection method.
00263  */
00264 
00265 static VALUE
00266 pst_inspect(st)
00267     VALUE st;
00268 {
00269     VALUE pid;
00270     int status;
00271     VALUE str;
00272     char buf[256];
00273 
00274     pid = pst_pid(st);
00275     status = NUM2INT(st);
00276 
00277     snprintf(buf, sizeof(buf), "#<%s: pid=%ld", rb_class2name(CLASS_OF(st)), NUM2LONG(pid));
00278     str = rb_str_new2(buf);
00279     if (WIFSTOPPED(status)) {
00280         int stopsig = WSTOPSIG(status);
00281         const char *signame = ruby_signal_name(stopsig);
00282         if (signame) {
00283             snprintf(buf, sizeof(buf), ",stopped(SIG%s=%d)", signame, stopsig);
00284         }
00285         else {
00286             snprintf(buf, sizeof(buf), ",stopped(%d)", stopsig);
00287         }
00288         rb_str_cat2(str, buf);
00289     }
00290     if (WIFSIGNALED(status)) {
00291         int termsig = WTERMSIG(status);
00292         const char *signame = ruby_signal_name(termsig);
00293         if (signame) {
00294             snprintf(buf, sizeof(buf), ",signaled(SIG%s=%d)", signame, termsig);
00295         }
00296         else {
00297             snprintf(buf, sizeof(buf), ",signaled(%d)", termsig);
00298         }
00299         rb_str_cat2(str, buf);
00300     }
00301     if (WIFEXITED(status)) {
00302         snprintf(buf, sizeof(buf), ",exited(%d)", WEXITSTATUS(status));
00303         rb_str_cat2(str, buf);
00304     }
00305 #ifdef WCOREDUMP
00306     if (WCOREDUMP(status)) {
00307         rb_str_cat2(str, ",coredumped");
00308     }
00309 #endif
00310     rb_str_cat2(str, ">");
00311     return str;
00312 }
00313 
00314 
00315 /*
00316  *  call-seq:
00317  *     stat == other   => true or false
00318  *
00319  *  Returns +true+ if the integer value of _stat_
00320  *  equals <em>other</em>.
00321  */
00322 
00323 static VALUE
00324 pst_equal(st1, st2)
00325     VALUE st1, st2;
00326 {
00327     if (st1 == st2) return Qtrue;
00328     return rb_equal(pst_to_i(st1), st2);
00329 }
00330 
00331 
00332 /*
00333  *  call-seq:
00334  *     stat & num   => fixnum
00335  *
00336  *  Logical AND of the bits in _stat_ with <em>num</em>.
00337  *
00338  *     fork { exit 0x37 }
00339  *     Process.wait
00340  *     sprintf('%04x', $?.to_i)       #=> "3700"
00341  *     sprintf('%04x', $? & 0x1e00)   #=> "1600"
00342  */
00343 
00344 static VALUE
00345 pst_bitand(st1, st2)
00346     VALUE st1, st2;
00347 {
00348     int status = NUM2INT(st1) & NUM2INT(st2);
00349 
00350     return INT2NUM(status);
00351 }
00352 
00353 
00354 /*
00355  *  call-seq:
00356  *     stat >> num   => fixnum
00357  *
00358  *  Shift the bits in _stat_ right <em>num</em> places.
00359  *
00360  *     fork { exit 99 }   #=> 26563
00361  *     Process.wait       #=> 26563
00362  *     $?.to_i            #=> 25344
00363  *     $? >> 8            #=> 99
00364  */
00365 
00366 static VALUE
00367 pst_rshift(st1, st2)
00368     VALUE st1, st2;
00369 {
00370     int status = NUM2INT(st1) >> NUM2INT(st2);
00371 
00372     return INT2NUM(status);
00373 }
00374 
00375 
00376 /*
00377  *  call-seq:
00378  *     stat.stopped?   => true or false
00379  *
00380  *  Returns +true+ if this process is stopped. This is only
00381  *  returned if the corresponding <code>wait</code> call had the
00382  *  <code>WUNTRACED</code> flag set.
00383  */
00384 
00385 static VALUE
00386 pst_wifstopped(st)
00387     VALUE st;
00388 {
00389     int status = NUM2INT(st);
00390 
00391     if (WIFSTOPPED(status))
00392         return Qtrue;
00393     else
00394         return Qfalse;
00395 }
00396 
00397 
00398 /*
00399  *  call-seq:
00400  *     stat.stopsig   => fixnum or nil
00401  *
00402  *  Returns the number of the signal that caused _stat_ to stop
00403  *  (or +nil+ if self is not stopped).
00404  */
00405 
00406 static VALUE
00407 pst_wstopsig(st)
00408     VALUE st;
00409 {
00410     int status = NUM2INT(st);
00411 
00412     if (WIFSTOPPED(status))
00413         return INT2NUM(WSTOPSIG(status));
00414     return Qnil;
00415 }
00416 
00417 
00418 /*
00419  *  call-seq:
00420  *     stat.signaled?   => true or false
00421  *
00422  *  Returns +true+ if _stat_ terminated because of
00423  *  an uncaught signal.
00424  */
00425 
00426 static VALUE
00427 pst_wifsignaled(st)
00428     VALUE st;
00429 {
00430     int status = NUM2INT(st);
00431 
00432     if (WIFSIGNALED(status))
00433         return Qtrue;
00434     else
00435         return Qfalse;
00436 }
00437 
00438 
00439 /*
00440  *  call-seq:
00441  *     stat.termsig   => fixnum or nil
00442  *
00443  *  Returns the number of the signal that caused _stat_ to
00444  *  terminate (or +nil+ if self was not terminated by an
00445  *  uncaught signal).
00446  */
00447 
00448 static VALUE
00449 pst_wtermsig(st)
00450     VALUE st;
00451 {
00452     int status = NUM2INT(st);
00453 
00454     if (WIFSIGNALED(status))
00455         return INT2NUM(WTERMSIG(status));
00456     return Qnil;
00457 }
00458 
00459 
00460 /*
00461  *  call-seq:
00462  *     stat.exited?   => true or false
00463  *
00464  *  Returns +true+ if _stat_ exited normally (for
00465  *  example using an <code>exit()</code> call or finishing the
00466  *  program).
00467  */
00468 
00469 static VALUE
00470 pst_wifexited(st)
00471     VALUE st;
00472 {
00473     int status = NUM2INT(st);
00474 
00475     if (WIFEXITED(status))
00476         return Qtrue;
00477     else
00478         return Qfalse;
00479 }
00480 
00481 
00482 /*
00483  *  call-seq:
00484  *     stat.exitstatus   => fixnum or nil
00485  *
00486  *  Returns the least significant eight bits of the return code of
00487  *  _stat_. Only available if <code>exited?</code> is
00488  *  +true+.
00489  *
00490  *     fork { }           #=> 26572
00491  *     Process.wait       #=> 26572
00492  *     $?.exited?         #=> true
00493  *     $?.exitstatus      #=> 0
00494  *
00495  *     fork { exit 99 }   #=> 26573
00496  *     Process.wait       #=> 26573
00497  *     $?.exited?         #=> true
00498  *     $?.exitstatus      #=> 99
00499  */
00500 
00501 static VALUE
00502 pst_wexitstatus(st)
00503     VALUE st;
00504 {
00505     int status = NUM2INT(st);
00506 
00507     if (WIFEXITED(status))
00508         return INT2NUM(WEXITSTATUS(status));
00509     return Qnil;
00510 }
00511 
00512 
00513 /*
00514  *  call-seq:
00515  *     stat.success?   => true, false or nil
00516  *
00517  *  Returns +true+ if _stat_ is successful, +false+ if not.
00518  *  Returns +nil+ if <code>exited?</code> is not +true+.
00519  */
00520 
00521 static VALUE
00522 pst_success_p(st)
00523     VALUE st;
00524 {
00525     int status = NUM2INT(st);
00526 
00527     if (!WIFEXITED(status))
00528         return Qnil;
00529     return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
00530 }
00531 
00532 
00533 /*
00534  *  call-seq:
00535  *     stat.coredump?   => true or false
00536  *
00537  *  Returns +true+ if _stat_ generated a coredump
00538  *  when it terminated. Not available on all platforms.
00539  */
00540 
00541 static VALUE
00542 pst_wcoredump(st)
00543     VALUE st;
00544 {
00545 #ifdef WCOREDUMP
00546     int status = NUM2INT(st);
00547 
00548     if (WCOREDUMP(status))
00549         return Qtrue;
00550     else
00551         return Qfalse;
00552 #else
00553     return Qfalse;
00554 #endif
00555 }
00556 
00557 #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
00558 #define NO_WAITPID
00559 static st_table *pid_tbl;
00560 #endif
00561 
00562 int
00563 rb_waitpid(pid, st, flags)
00564     int pid;
00565     int *st;
00566     int flags;
00567 {
00568     int result;
00569 #ifndef NO_WAITPID
00570     int oflags = flags;
00571     if (!rb_thread_alone()) {   /* there're other threads to run */
00572         flags |= WNOHANG;
00573     }
00574 
00575   retry:
00576     TRAP_BEG;
00577 #ifdef HAVE_WAITPID
00578     result = waitpid(pid, st, flags);
00579 #else  /* HAVE_WAIT4 */
00580     result = wait4(pid, st, flags, NULL);
00581 #endif
00582     TRAP_END;
00583     if (result < 0) {
00584         if (errno == EINTR) {
00585             rb_thread_polling();
00586             goto retry;
00587         }
00588         return -1;
00589     }
00590     if (result == 0) {
00591         if (oflags & WNOHANG) return 0;
00592         rb_thread_polling();
00593         if (rb_thread_alone()) flags = oflags;
00594         goto retry;
00595     }
00596 #else  /* NO_WAITPID */
00597     if (pid_tbl && st_lookup(pid_tbl, pid, st)) {
00598         last_status_set(*st, pid);
00599         st_delete(pid_tbl, (st_data_t*)&pid, NULL);
00600         return pid;
00601     }
00602 
00603     if (flags) {
00604         rb_raise(rb_eArgError, "can't do waitpid with flags");
00605     }
00606 
00607     for (;;) {
00608         TRAP_BEG;
00609         result = wait(st);
00610         TRAP_END;
00611         if (result < 0) {
00612             if (errno == EINTR) {
00613                 rb_thread_schedule();
00614                 continue;
00615             }
00616             return -1;
00617         }
00618         if (result == pid) {
00619             break;
00620         }
00621         if (!pid_tbl)
00622             pid_tbl = st_init_numtable();
00623         st_insert(pid_tbl, pid, st);
00624         if (!rb_thread_alone()) rb_thread_schedule();
00625     }
00626 #endif
00627     if (result > 0) {
00628         last_status_set(*st, result);
00629     }
00630     return result;
00631 }
00632 
00633 #ifdef NO_WAITPID
00634 struct wait_data {
00635     int pid;
00636     int status;
00637 };
00638 
00639 static int
00640 wait_each(pid, status, data)
00641     int pid, status;
00642     struct wait_data *data;
00643 {
00644     if (data->status != -1) return ST_STOP;
00645 
00646     data->pid = pid;
00647     data->status = status;
00648     return ST_DELETE;
00649 }
00650 
00651 static int
00652 waitall_each(pid, status, ary)
00653     int pid, status;
00654     VALUE ary;
00655 {
00656     last_status_set(status, pid);
00657     rb_ary_push(ary, rb_assoc_new(INT2NUM(pid), rb_last_status));
00658     return ST_DELETE;
00659 }
00660 #endif
00661 
00662 
00663 /* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
00664    has historically been documented as if it didn't take any arguments
00665    despite the fact that it's just an alias for ::waitpid(). The way I
00666    have it below is more truthful, but a little confusing.
00667 
00668    I also took the liberty of putting in the pid values, as they're
00669    pretty useful, and it looked as if the original 'ri' output was
00670    supposed to contain them after "[...]depending on the value of
00671    aPid:".
00672 
00673    The 'ansi' and 'bs' formats of the ri output don't display the
00674    definition list for some reason, but the plain text one does.
00675  */
00676 
00677 /*
00678  *  call-seq:
00679  *     Process.wait()                     => fixnum
00680  *     Process.wait(pid=-1, flags=0)      => fixnum
00681  *     Process.waitpid(pid=-1, flags=0)   => fixnum
00682  *
00683  *  Waits for a child process to exit, returns its process id, and
00684  *  sets <code>$?</code> to a <code>Process::Status</code> object
00685  *  containing information on that process. Which child it waits on
00686  *  depends on the value of _pid_:
00687  *
00688  *  > 0::   Waits for the child whose process ID equals _pid_.
00689  *
00690  *  0::     Waits for any child whose process group ID equals that of the
00691  *          calling process.
00692  *
00693  *  -1::    Waits for any child process (the default if no _pid_ is
00694  *          given).
00695  *
00696  *  < -1::  Waits for any child whose process group ID equals the absolute
00697  *          value of _pid_.
00698  *
00699  *  The _flags_ argument may be a logical or of the flag values
00700  *  <code>Process::WNOHANG</code> (do not block if no child available)
00701  *  or <code>Process::WUNTRACED</code> (return stopped children that
00702  *  haven't been reported). Not all flags are available on all
00703  *  platforms, but a flag value of zero will work on all platforms.
00704  *
00705  *  Calling this method raises a <code>SystemError</code> if there are
00706  *  no child processes. Not available on all platforms.
00707  *
00708  *     include Process
00709  *     fork { exit 99 }                 #=> 27429
00710  *     wait                             #=> 27429
00711  *     $?.exitstatus                    #=> 99
00712  *
00713  *     pid = fork { sleep 3 }           #=> 27440
00714  *     Time.now                         #=> Wed Apr 09 08:57:09 CDT 2003
00715  *     waitpid(pid, Process::WNOHANG)   #=> nil
00716  *     Time.now                         #=> Wed Apr 09 08:57:09 CDT 2003
00717  *     waitpid(pid, 0)                  #=> 27440
00718  *     Time.now                         #=> Wed Apr 09 08:57:12 CDT 2003
00719  */
00720 
00721 static VALUE
00722 proc_wait(argc, argv)
00723     int argc;
00724     VALUE *argv;
00725 {
00726     VALUE vpid, vflags;
00727     int pid, flags, status;
00728 
00729     rb_secure(2);
00730     flags = 0;
00731     rb_scan_args(argc, argv, "02", &vpid, &vflags);
00732     if (argc == 0) {
00733         pid = -1;
00734     }
00735     else {
00736         pid = NUM2INT(vpid);
00737         if (argc == 2 && !NIL_P(vflags)) {
00738             flags = NUM2UINT(vflags);
00739         }
00740     }
00741     if ((pid = rb_waitpid(pid, &status, flags)) < 0)
00742         rb_sys_fail(0);
00743     if (pid == 0) {
00744         return rb_last_status = Qnil;
00745     }
00746     return INT2FIX(pid);
00747 }
00748 
00749 
00750 /*
00751  *  call-seq:
00752  *     Process.wait2(pid=-1, flags=0)      => [pid, status]
00753  *     Process.waitpid2(pid=-1, flags=0)   => [pid, status]
00754  *
00755  *  Waits for a child process to exit (see Process::waitpid for exact
00756  *  semantics) and returns an array containing the process id and the
00757  *  exit status (a <code>Process::Status</code> object) of that
00758  *  child. Raises a <code>SystemError</code> if there are no child
00759  *  processes.
00760  *
00761  *     Process.fork { exit 99 }   #=> 27437
00762  *     pid, status = Process.wait2
00763  *     pid                        #=> 27437
00764  *     status.exitstatus          #=> 99
00765  */
00766 
00767 static VALUE
00768 proc_wait2(argc, argv)
00769     int argc;
00770     VALUE *argv;
00771 {
00772     VALUE pid = proc_wait(argc, argv);
00773     if (NIL_P(pid)) return Qnil;
00774     return rb_assoc_new(pid, rb_last_status);
00775 }
00776 
00777 
00778 /*
00779  *  call-seq:
00780  *     Process.waitall   => [ [pid1,status1], ...]
00781  *
00782  *  Waits for all children, returning an array of
00783  *  _pid_/_status_ pairs (where _status_ is a
00784  *  <code>Process::Status</code> object).
00785  *
00786  *     fork { sleep 0.2; exit 2 }   #=> 27432
00787  *     fork { sleep 0.1; exit 1 }   #=> 27433
00788  *     fork {            exit 0 }   #=> 27434
00789  *     p Process.waitall
00790  *
00791  *  <em>produces</em>:
00792  *
00793  *     [[27434, #<Process::Status: pid=27434,exited(0)>],
00794  *      [27433, #<Process::Status: pid=27433,exited(1)>],
00795  *      [27432, #<Process::Status: pid=27432,exited(2)>]]
00796  */
00797 
00798 static VALUE
00799 proc_waitall()
00800 {
00801     VALUE result;
00802     int pid, status;
00803 
00804     rb_secure(2);
00805     result = rb_ary_new();
00806 #ifdef NO_WAITPID
00807     if (pid_tbl) {
00808         st_foreach(pid_tbl, waitall_each, result);
00809     }
00810 
00811     for (pid = -1;;) {
00812         pid = wait(&status);
00813         if (pid == -1) {
00814             if (errno == ECHILD)
00815                 break;
00816             if (errno == EINTR) {
00817                 rb_thread_schedule();
00818                 continue;
00819             }
00820             rb_sys_fail(0);
00821         }
00822         last_status_set(status, pid);
00823         rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status));
00824     }
00825 #else
00826     rb_last_status = Qnil;
00827     for (pid = -1;;) {
00828         pid = rb_waitpid(-1, &status, 0);
00829         if (pid == -1) {
00830             if (errno == ECHILD)
00831                 break;
00832             rb_sys_fail(0);
00833         }
00834         rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status));
00835     }
00836 #endif
00837     return result;
00838 }
00839 
00840 static VALUE
00841 detach_process_watcher(pid_p)
00842     int *pid_p;
00843 {
00844     int cpid, status;
00845 
00846     for (;;) {
00847         cpid = rb_waitpid(*pid_p, &status, WNOHANG);
00848         if (cpid != 0) return Qnil;
00849         rb_thread_sleep(1);
00850     }
00851 }
00852 
00853 VALUE
00854 rb_detach_process(pid)
00855     int pid;
00856 {
00857     return rb_thread_create(detach_process_watcher, (void*)&pid);
00858 }
00859 
00860 
00861 /*
00862  *  call-seq:
00863  *     Process.detach(pid)   => thread
00864  *
00865  *  Some operating systems retain the status of terminated child
00866  *  processes until the parent collects that status (normally using
00867  *  some variant of <code>wait()</code>. If the parent never collects
00868  *  this status, the child stays around as a <em>zombie</em> process.
00869  *  <code>Process::detach</code> prevents this by setting up a
00870  *  separate Ruby thread whose sole job is to reap the status of the
00871  *  process _pid_ when it terminates. Use <code>detach</code>
00872  *  only when you do not intent to explicitly wait for the child to
00873  *  terminate.  <code>detach</code> only checks the status
00874  *  periodically (currently once each second).
00875  *
00876  *  In this first example, we don't reap the first child process, so
00877  *  it appears as a zombie in the process status display.
00878  *
00879  *     p1 = fork { sleep 0.1 }
00880  *     p2 = fork { sleep 0.2 }
00881  *     Process.waitpid(p2)
00882  *     sleep 2
00883  *     system("ps -ho pid,state -p #{p1}")
00884  *
00885  *  <em>produces:</em>
00886  *
00887  *     27389 Z
00888  *
00889  *  In the next example, <code>Process::detach</code> is used to reap
00890  *  the child automatically.
00891  *
00892  *     p1 = fork { sleep 0.1 }
00893  *     p2 = fork { sleep 0.2 }
00894  *     Process.detach(p1)
00895  *     Process.waitpid(p2)
00896  *     sleep 2
00897  *     system("ps -ho pid,state -p #{p1}")
00898  *
00899  *  <em>(produces no output)</em>
00900  */
00901 
00902 static VALUE
00903 proc_detach(VALUE obj, VALUE pid)
00904 {
00905     rb_secure(2);
00906     return rb_detach_process(NUM2INT(pid));
00907 }
00908 
00909 #ifndef HAVE_STRING_H
00910 char *strtok();
00911 #endif
00912 
00913 #ifdef HAVE_SETITIMER
00914 #define before_exec() rb_thread_stop_timer()
00915 #define after_exec() rb_thread_start_timer()
00916 #else
00917 #define before_exec()
00918 #define after_exec()
00919 #endif
00920 
00921 extern char *dln_find_exe();
00922 
00923 static void
00924 security(str)
00925     char *str;
00926 {
00927     if (rb_env_path_tainted()) {
00928         if (rb_safe_level() > 0) {
00929             rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
00930         }
00931     }
00932 }
00933 
00934 static int
00935 proc_exec_v(argv, prog)
00936     char **argv;
00937     char *prog;
00938 {
00939     if (!prog)
00940         prog = argv[0];
00941     security(prog);
00942     prog = dln_find_exe(prog, 0);
00943     if (!prog)
00944         return -1;
00945 
00946 #if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__) || defined(__EMX__) || defined(OS2)
00947     {
00948 #if defined(__human68k__)
00949 #define COMMAND "command.x"
00950 #endif
00951 #if defined(__EMX__) || defined(OS2) /* OS/2 emx */
00952 #define COMMAND "cmd.exe"
00953 #endif
00954 #if (defined(MSDOS) && !defined(DJGPP))
00955 #define COMMAND "command.com"
00956 #endif
00957         char *extension;
00958 
00959         if ((extension = strrchr(prog, '.')) != NULL && strcasecmp(extension, ".bat") == 0) {
00960             char **new_argv;
00961             char *p;
00962             int n;
00963 
00964             for (n = 0; argv[n]; n++)
00965                 /* no-op */;
00966             new_argv = ALLOCA_N(char*, n + 2);
00967             for (; n > 0; n--)
00968                 new_argv[n + 1] = argv[n];
00969             new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
00970             for (p = new_argv[1]; *p != '\0'; p++)
00971                 if (*p == '/')
00972                     *p = '\\';
00973             new_argv[0] = COMMAND;
00974             argv = new_argv;
00975             prog = dln_find_exe(argv[0], 0);
00976             if (!prog) {
00977                 errno = ENOENT;
00978                 return -1;
00979             }
00980         }
00981     }
00982 #endif /* MSDOS or __human68k__ or __EMX__ */
00983     before_exec();
00984     execv(prog, argv);
00985     after_exec();
00986     return -1;
00987 }
00988 
00989 static int
00990 proc_exec_n(argc, argv, progv)
00991     int argc;
00992     VALUE *argv;
00993     VALUE progv;
00994 {
00995     char *prog = 0;
00996     char **args;
00997     int i;
00998 
00999     if (progv) {
01000         prog = RSTRING(progv)->ptr;
01001     }
01002     args = ALLOCA_N(char*, argc+1);
01003     for (i=0; i<argc; i++) {
01004         SafeStringValue(argv[i]);
01005         args[i] = RSTRING(argv[i])->ptr;
01006     }
01007     args[i] = 0;
01008     if (args[0]) {
01009         return proc_exec_v(args, prog);
01010     }
01011     return -1;
01012 }
01013 
01014 int
01015 rb_proc_exec(str)
01016     const char *str;
01017 {
01018     const char *s = str;
01019     char *ss, *t;
01020     char **argv, **a;
01021 
01022     while (*str && ISSPACE(*str))
01023         str++;
01024 
01025 #ifdef _WIN32
01026     before_exec();
01027     do_spawn(P_OVERLAY, (char *)str);
01028     after_exec();
01029 #else
01030     for (s=str; *s; s++) {
01031         if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
01032 #if defined(MSDOS)
01033             int status;
01034             before_exec();
01035             status = system(str);
01036             after_exec();
01037             if (status != -1)
01038                 exit(status);
01039 #else
01040 #if defined(__human68k__) || defined(__CYGWIN32__) || defined(__EMX__)
01041             char *shell = dln_find_exe("sh", 0);
01042             int status = -1;
01043             before_exec();
01044             if (shell)
01045                 execl(shell, "sh", "-c", str, (char *) NULL);
01046             else
01047                 status = system(str);
01048             after_exec();
01049             if (status != -1)
01050                 exit(status);
01051 #else
01052             before_exec();
01053             execl("/bin/sh", "sh", "-c", str, (char *)NULL);
01054             after_exec();
01055 #endif
01056 #endif
01057             return -1;
01058         }
01059     }
01060     a = argv = ALLOCA_N(char*, (s-str)/2+2);
01061     ss = ALLOCA_N(char, s-str+1);
01062     strcpy(ss, str);
01063     if (*a++ = strtok(ss, " \t")) {
01064         while (t = strtok(NULL, " \t")) {
01065             *a++ = t;
01066         }
01067         *a = NULL;
01068     }
01069     if (argv[0]) {
01070         return proc_exec_v(argv, 0);
01071     }
01072     errno = ENOENT;
01073 #endif  /* _WIN32 */
01074     return -1;
01075 }
01076 
01077 #if defined(__human68k__) || defined(__DJGPP__) || defined(_WIN32)
01078 static int
01079 proc_spawn_v(argv, prog)
01080     char **argv;
01081     char *prog;
01082 {
01083     char *extension;
01084     int status;
01085 
01086     if (!prog)
01087         prog = argv[0];
01088     security(prog);
01089     prog = dln_find_exe(prog, 0);
01090     if (!prog)
01091         return -1;
01092 
01093 #if defined(__human68k__)
01094     if ((extension = strrchr(prog, '.')) != NULL && strcasecmp(extension, ".bat") == 0) {
01095         char **new_argv;
01096         char *p;
01097         int n;
01098 
01099         for (n = 0; argv[n]; n++)
01100             /* no-op */;
01101         new_argv = ALLOCA_N(char*, n + 2);
01102         for (; n > 0; n--)
01103             new_argv[n + 1] = argv[n];
01104         new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
01105         for (p = new_argv[1]; *p != '\0'; p++)
01106             if (*p == '/')
01107                 *p = '\\';
01108         new_argv[0] = COMMAND;
01109         argv = new_argv;
01110         prog = dln_find_exe(argv[0], 0);
01111         if (!prog) {
01112             errno = ENOENT;
01113             return -1;
01114         }
01115     }
01116 #endif
01117     before_exec();
01118 #if defined(_WIN32)
01119     status = do_aspawn(P_WAIT, prog, argv);
01120 #else
01121     status = spawnv(P_WAIT, prog, argv);
01122 #endif
01123     after_exec();
01124     return status;
01125 }
01126 
01127 static int
01128 proc_spawn_n(argc, argv, prog)
01129     int argc;
01130     VALUE *argv;
01131     VALUE prog;
01132 {
01133     char **args;
01134     int i;
01135 
01136     args = ALLOCA_N(char*, argc + 1);
01137     for (i = 0; i < argc; i++) {
01138         SafeStringValue(argv[i]);
01139         args[i] = RSTRING(argv[i])->ptr;
01140     }
01141     if (prog)
01142         SafeStringValue(prog);
01143     args[i] = (char*) 0;
01144     if (args[0])
01145         return proc_spawn_v(args, prog ? RSTRING(prog)->ptr : 0);
01146     return -1;
01147 }
01148 
01149 #if !defined(_WIN32)
01150 static int
01151 proc_spawn(sv)
01152     VALUE sv;
01153 {
01154     char *str;
01155     char *s, *t;
01156     char **argv, **a;
01157     int status;
01158 
01159     SafeStringValue(sv);
01160     str = s = RSTRING(sv)->ptr;
01161     for (s = str; *s; s++) {
01162         if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
01163             char *shell = dln_find_exe("sh", 0);
01164             before_exec();
01165             status = shell?spawnl(P_WAIT,shell,"sh","-c",str,(char*)NULL):system(str);
01166             after_exec();
01167             return status;
01168         }
01169     }
01170     a = argv = ALLOCA_N(char*, (s - str) / 2 + 2);
01171     s = ALLOCA_N(char, s - str + 1);
01172     strcpy(s, str);
01173     if (*a++ = strtok(s, " \t")) {
01174         while (t = strtok(NULL, " \t"))
01175             *a++ = t;
01176         *a = NULL;
01177     }
01178     return argv[0] ? proc_spawn_v(argv, 0) : -1;
01179 }
01180 #endif
01181 #endif
01182 
01183 /*
01184  *  call-seq:
01185  *     exec(command [, arg, ...])
01186  *
01187  *  Replaces the current process by running the given external _command_.
01188  *  If +exec+ is given a single argument, that argument is
01189  *  taken as a line that is subject to shell expansion before being
01190  *  executed. If multiple arguments are given, the second and subsequent
01191  *  arguments are passed as parameters to _command_ with no shell
01192  *  expansion. If the first argument is a two-element array, the first
01193  *  element is the command to be executed, and the second argument is
01194  *  used as the <code>argv[0]</code> value, which may show up in process
01195  *  listings. In MSDOS environments, the command is executed in a
01196  *  subshell; otherwise, one of the <code>exec(2)</code> system calls is
01197  *  used, so the running command may inherit some of the environment of
01198  *  the original program (including open file descriptors).
01199  *
01200  *     exec "echo *"       # echoes list of files in current directory
01201  *     # never get here
01202  *
01203  *
01204  *     exec "echo", "*"    # echoes an asterisk
01205  *     # never get here
01206  */
01207 
01208 VALUE
01209 rb_f_exec(argc, argv)
01210     int argc;
01211     VALUE *argv;
01212 {
01213     VALUE prog = 0;
01214     VALUE tmp;
01215 
01216     if (argc == 0) {
01217         rb_raise(rb_eArgError, "wrong number of arguments");
01218     }
01219 
01220     tmp = rb_check_array_type(argv[0]);
01221     if (!NIL_P(tmp)) {
01222         if (RARRAY(tmp)->len != 2) {
01223             rb_raise(rb_eArgError, "wrong first argument");
01224         }
01225         prog = RARRAY(tmp)->ptr[0];
01226         argv[0] = RARRAY(tmp)->ptr[1];
01227         SafeStringValue(prog);
01228     }
01229     if (argc == 1 && prog == 0) {
01230         VALUE cmd = argv[0];
01231 
01232         SafeStringValue(cmd);
01233         rb_proc_exec(RSTRING(cmd)->ptr);
01234     }
01235     else {
01236         proc_exec_n(argc, argv, prog);
01237     }
01238     rb_sys_fail(RSTRING(argv[0])->ptr);
01239     return Qnil;                /* dummy */
01240 }
01241 
01242 
01243 /*
01244  *  call-seq:
01245  *     Kernel.fork  [{ block }]   => fixnum or nil
01246  *     Process.fork [{ block }]   => fixnum or nil
01247  *
01248  *  Creates a subprocess. If a block is specified, that block is run
01249  *  in the subprocess, and the subprocess terminates with a status of
01250  *  zero. Otherwise, the +fork+ call returns twice, once in
01251  *  the parent, returning the process ID of the child, and once in
01252  *  the child, returning _nil_. The child process can exit using
01253  *  <code>Kernel.exit!</code> to avoid running any
01254  *  <code>at_exit</code> functions. The parent process should
01255  *  use <code>Process.wait</code> to collect the termination statuses
01256  *  of its children or use <code>Process.detach</code> to register
01257  *  disinterest in their status; otherwise, the operating system
01258  *  may accumulate zombie processes.
01259  *
01260  *  The thread calling fork is the only thread in the created child process.
01261  *  fork doesn't copy other threads.
01262  */
01263 
01264 static VALUE
01265 rb_f_fork(obj)
01266     VALUE obj;
01267 {
01268 #if !defined(__human68k__) && !defined(_WIN32) && !defined(__MACOS__) && !defined(__EMX__) && !defined(__VMS)
01269     int pid;
01270 
01271     rb_secure(2);
01272 
01273 #ifndef __VMS
01274     fflush(stdout);
01275     fflush(stderr);
01276 #endif
01277 
01278     switch (pid = fork()) {
01279       case 0:
01280 #ifdef linux
01281         after_exec();
01282 #endif
01283         rb_thread_atfork();
01284         if (rb_block_given_p()) {
01285             int status;
01286 
01287             rb_protect(rb_yield, Qundef, &status);
01288             ruby_stop(status);
01289         }
01290         return Qnil;
01291 
01292       case -1:
01293         rb_sys_fail("fork(2)");
01294         return Qnil;
01295 
01296       default:
01297         return INT2FIX(pid);
01298     }
01299 #else
01300     rb_notimplement();
01301 #endif
01302 }
01303 
01304 
01305 /*
01306  *  call-seq:
01307  *     Process.exit!(fixnum=-1)
01308  *
01309  *  Exits the process immediately. No exit handlers are
01310  *  run. <em>fixnum</em> is returned to the underlying system as the
01311  *  exit status.
01312  *
01313  *     Process.exit!(0)
01314  */
01315 
01316 static VALUE
01317 rb_f_exit_bang(argc, argv, obj)
01318     int argc;
01319     VALUE *argv;
01320     VALUE obj;
01321 {
01322     VALUE status;
01323     int istatus;
01324 
01325     rb_secure(4);
01326     if (rb_scan_args(argc, argv, "01", &status) == 1) {
01327         switch (status) {
01328           case Qtrue:
01329             istatus = EXIT_SUCCESS;
01330             break;
01331           case Qfalse:
01332             istatus = EXIT_FAILURE;
01333             break;
01334           default:
01335             istatus = NUM2INT(status);
01336             break;
01337         }
01338     }
01339     else {
01340         istatus = EXIT_FAILURE;
01341     }
01342     _exit(istatus);
01343 
01344     return Qnil;                /* not reached */
01345 }
01346 
01347 #if defined(sun)
01348 #define signal(a,b) sigset(a,b)
01349 #endif
01350 
01351 void
01352 rb_syswait(pid)
01353     int pid;
01354 {
01355     static int overriding;
01356 #ifdef SIGHUP
01357     RETSIGTYPE (*hfunc)(int);
01358 #endif
01359 #ifdef SIGQUIT
01360     RETSIGTYPE (*qfunc)(int);
01361 #endif
01362     RETSIGTYPE (*ifunc)(int);
01363     int status;
01364     int i, hooked = Qfalse;
01365 
01366     if (!overriding) {
01367 #ifdef SIGHUP
01368         hfunc = signal(SIGHUP, SIG_IGN);
01369 #endif
01370 #ifdef SIGQUIT
01371         qfunc = signal(SIGQUIT, SIG_IGN);
01372 #endif
01373         ifunc = signal(SIGINT, SIG_IGN);
01374         overriding = Qtrue;
01375         hooked = Qtrue;
01376     }
01377 
01378     do {
01379         i = rb_waitpid(pid, &status, 0);
01380     } while (i == -1 && errno == EINTR);
01381 
01382     if (hooked) {
01383 #ifdef SIGHUP
01384         signal(SIGHUP, hfunc);
01385 #endif
01386 #ifdef SIGQUIT
01387         signal(SIGQUIT, qfunc);
01388 #endif
01389         signal(SIGINT, ifunc);
01390         overriding = Qfalse;
01391     }
01392 }
01393 
01394 /*
01395  *  call-seq:
01396  *     system(cmd [, arg, ...])    => true or false
01397  *
01398  *  Executes _cmd_ in a subshell, returning +true+ if
01399  *  the command was found and ran successfully, +false+
01400  *  otherwise. An error status is available in <code>$?</code>. The
01401  *  arguments are processed in the same way as for
01402  *  <code>Kernel::exec</code>.
01403  *
01404  *     system("echo *")
01405  *     system("echo", "*")
01406  *
01407  *  <em>produces:</em>
01408  *
01409  *     config.h main.rb
01410  *     *
01411  */
01412 
01413 static VALUE
01414 rb_f_system(argc, argv)
01415     int argc;
01416     VALUE *argv;
01417 {
01418     int status;
01419 #if defined(__EMX__)
01420     VALUE cmd;
01421 
01422     fflush(stdout);
01423     fflush(stderr);
01424     if (argc == 0) {
01425         rb_last_status = Qnil;
01426         rb_raise(rb_eArgError, "wrong number of arguments");
01427     }
01428 
01429     if (TYPE(argv[0]) == T_ARRAY) {
01430         if (RARRAY(argv[0])->len != 2) {
01431             rb_raise(rb_eArgError, "wrong first argument");
01432         }
01433         argv[0] = RARRAY(argv[0])->ptr[0];
01434     }
01435     cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
01436 
01437     SafeStringValue(cmd);
01438     status = do_spawn(RSTRING(cmd)->ptr);
01439     last_status_set(status, 0);
01440 #elif defined(__human68k__) || defined(__DJGPP__) || defined(_WIN32)
01441     volatile VALUE prog = 0;
01442 
01443     fflush(stdout);
01444     fflush(stderr);
01445     if (argc == 0) {
01446         rb_last_status = Qnil;
01447         rb_raise(rb_eArgError, "wrong number of arguments");
01448     }
01449 
01450     if (TYPE(argv[0]) == T_ARRAY) {
01451         if (RARRAY(argv[0])->len != 2) {
01452             rb_raise(rb_eArgError, "wrong first argument");
01453         }
01454         prog = RARRAY(argv[0])->ptr[0];
01455         argv[0] = RARRAY(argv[0])->ptr[1];
01456     }
01457 
01458     if (argc == 1 && prog == 0) {
01459 #if defined(_WIN32)
01460         SafeStringValue(argv[0]);
01461         status = do_spawn(P_WAIT, RSTRING(argv[0])->ptr);
01462 #else
01463         status = proc_spawn(argv[0]);
01464 #endif
01465     }
01466     else {
01467         status = proc_spawn_n(argc, argv, prog);
01468     }
01469 #if !defined(_WIN32)
01470     last_status_set(status == -1 ? 127 : status, 0);
01471 #endif
01472 #elif defined(__VMS)
01473     VALUE cmd;
01474 
01475     if (argc == 0) {
01476         rb_last_status = Qnil;
01477         rb_raise(rb_eArgError, "wrong number of arguments");
01478     }
01479 
01480     if (TYPE(argv[0]) == T_ARRAY) {
01481         if (RARRAY(argv[0])->len != 2) {
01482             rb_raise(rb_eArgError, "wrong first argument");
01483         }
01484         argv[0] = RARRAY(argv[0])->ptr[0];
01485     }
01486     cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
01487 
01488     SafeStringValue(cmd);
01489     status = system(RSTRING(cmd)->ptr);
01490     last_status_set((status & 0xff) << 8, 0);
01491 #else
01492     volatile VALUE prog = 0;
01493     int pid;
01494     int i;
01495 
01496     fflush(stdout);
01497     fflush(stderr);
01498     if (argc == 0) {
01499         rb_last_status = Qnil;
01500         rb_raise(rb_eArgError, "wrong number of arguments");
01501     }
01502 
01503     if (TYPE(argv[0]) == T_ARRAY) {
01504         if (RARRAY(argv[0])->len != 2) {
01505             rb_raise(rb_eArgError, "wrong first argument");
01506         }
01507         prog = RARRAY(argv[0])->ptr[0];
01508         argv[0] = RARRAY(argv[0])->ptr[1];
01509     }
01510 
01511     if (prog) {
01512         SafeStringValue(prog);
01513     }
01514     for (i = 0; i < argc; i++) {
01515         SafeStringValue(argv[i]);
01516     }
01517   retry:
01518     switch (pid = fork()) {
01519       case 0:
01520         if (argc == 1 && prog == 0) {
01521             rb_proc_exec(RSTRING(argv[0])->ptr);
01522         }
01523         else {
01524             proc_exec_n(argc, argv, prog);
01525         }
01526         _exit(127);
01527         break;                  /* not reached */
01528 
01529       case -1:
01530         if (errno == EAGAIN) {
01531             rb_thread_sleep(1);
01532             goto retry;
01533         }
01534         rb_sys_fail(0);
01535         break;
01536 
01537       default:
01538         rb_syswait(pid);
01539     }
01540 
01541     status = NUM2INT(rb_last_status);
01542 #endif
01543 
01544     if (status == EXIT_SUCCESS) return Qtrue;
01545     return Qfalse;
01546 }
01547 
01548 /*
01549  *  call-seq:
01550  *     sleep([duration])    => fixnum
01551  *
01552  *  Suspends the current thread for _duration_ seconds (which may be
01553  *  any number, including a +Float+ with fractional seconds). Returns the actual
01554  *  number of seconds slept (rounded), which may be less than that asked
01555  *  for if the thread was interrupted by a +SIGALRM+, or if
01556  *  another thread calls <code>Thread#run</code>. Zero arguments
01557  *  causes +sleep+ to sleep forever.
01558  *
01559  *     Time.new    #=> Wed Apr 09 08:56:32 CDT 2003
01560  *     sleep 1.2   #=> 1
01561  *     Time.new    #=> Wed Apr 09 08:56:33 CDT 2003
01562  *     sleep 1.9   #=> 2
01563  *     Time.new    #=> Wed Apr 09 08:56:35 CDT 2003
01564  */
01565 
01566 static VALUE
01567 rb_f_sleep(argc, argv)
01568     int argc;
01569     VALUE *argv;
01570 {
01571     int beg, end;
01572 
01573     beg = time(0);
01574     if (argc == 0) {
01575         rb_thread_sleep_forever();
01576     }
01577     else if (argc == 1) {
01578         rb_thread_wait_for(rb_time_interval(argv[0]));
01579     }
01580     else {
01581         rb_raise(rb_eArgError, "wrong number of arguments");
01582     }
01583 
01584     end = time(0) - beg;
01585 
01586     return INT2FIX(end);
01587 }
01588 
01589 
01590 /*
01591  *  call-seq:
01592  *     Process.getpgrp   => integer
01593  *
01594  *  Returns the process group ID for this process. Not available on
01595  *  all platforms.
01596  *
01597  *     Process.getpgid(0)   #=> 25527
01598  *     Process.getpgrp      #=> 25527
01599  */
01600 
01601 static VALUE
01602 proc_getpgrp()
01603 {
01604     int pgrp;
01605 
01606     rb_secure(2);
01607 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
01608     pgrp = getpgrp();
01609     if (pgrp < 0) rb_sys_fail(0);
01610     return INT2FIX(pgrp);
01611 #else
01612 # ifdef HAVE_GETPGID
01613     pgrp = getpgid(0);
01614     if (pgrp < 0) rb_sys_fail(0);
01615     return INT2FIX(pgrp);
01616 # else
01617     rb_notimplement();
01618 # endif
01619 #endif
01620 }
01621 
01622 
01623 /*
01624  *  call-seq:
01625  *     Process.setpgrp   => 0
01626  *
01627  *  Equivalent to <code>setpgid(0,0)</code>. Not available on all
01628  *  platforms.
01629  */
01630 
01631 static VALUE
01632 proc_setpgrp()
01633 {
01634     rb_secure(2);
01635   /* check for posix setpgid() first; this matches the posix */
01636   /* getpgrp() above.  It appears that configure will set SETPGRP_VOID */
01637   /* even though setpgrp(0,0) would be prefered. The posix call avoids */
01638   /* this confusion. */
01639 #ifdef HAVE_SETPGID
01640     if (setpgid(0,0) < 0) rb_sys_fail(0);
01641 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
01642     if (setpgrp() < 0) rb_sys_fail(0);
01643 #else
01644     rb_notimplement();
01645 #endif
01646     return INT2FIX(0);
01647 }
01648 
01649 
01650 /*
01651  *  call-seq:
01652  *     Process.getpgid(pid)   => integer
01653  *
01654  *  Returns the process group ID for the given process id. Not
01655  *  available on all platforms.
01656  *
01657  *     Process.getpgid(Process.ppid())   #=> 25527
01658  */
01659 
01660 static VALUE
01661 proc_getpgid(obj, pid)
01662     VALUE obj, pid;
01663 {
01664 #if defined(HAVE_GETPGID) && !defined(__CHECKER__)
01665     int i;
01666 
01667     rb_secure(2);
01668     i = getpgid(NUM2INT(pid));
01669     if (i < 0) rb_sys_fail(0);
01670     return INT2NUM(i);
01671 #else
01672     rb_notimplement();
01673 #endif
01674 }
01675 
01676 
01677 /*
01678  *  call-seq:
01679  *     Process.setpgid(pid, integer)   => 0
01680  *
01681  *  Sets the process group ID of _pid_ (0 indicates this
01682  *  process) to <em>integer</em>. Not available on all platforms.
01683  */
01684 
01685 static VALUE
01686 proc_setpgid(obj, pid, pgrp)
01687     VALUE obj, pid, pgrp;
01688 {
01689 #ifdef HAVE_SETPGID
01690     int ipid, ipgrp;
01691 
01692     rb_secure(2);
01693     ipid = NUM2INT(pid);
01694     ipgrp = NUM2INT(pgrp);
01695 
01696     if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
01697     return INT2FIX(0);
01698 #else
01699     rb_notimplement();
01700 #endif
01701 }
01702 
01703 
01704 /*
01705  *  call-seq:
01706  *     Process.setsid   => fixnum
01707  *
01708  *  Establishes this process as a new session and process group
01709  *  leader, with no controlling tty. Returns the session id. Not
01710  *  available on all platforms.
01711  *
01712  *     Process.setsid   #=> 27422
01713  */
01714 
01715 static VALUE
01716 proc_setsid()
01717 {
01718 #if defined(HAVE_SETSID)
01719     int pid;
01720 
01721     rb_secure(2);
01722     pid = setsid();
01723     if (pid < 0) rb_sys_fail(0);
01724     return INT2FIX(pid);
01725 #elif defined(HAVE_SETPGRP) && defined(TIOCNOTTY)
01726   rb_pid_t pid;
01727   int ret;
01728 
01729   rb_secure(2);
01730   pid = getpid();
01731 #if defined(SETPGRP_VOID)
01732   ret = setpgrp();
01733   /* If `pid_t setpgrp(void)' is equivalent to setsid(),
01734      `ret' will be the same value as `pid', and following open() will fail.
01735      In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
01736 #else
01737   ret = setpgrp(0, pid);
01738 #endif
01739   if (ret == -1) rb_sys_fail(0);
01740 
01741   if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
01742     ioctl(fd, TIOCNOTTY, NULL);
01743     close(fd);
01744   }
01745   return INT2FIX(pid);
01746 #else
01747     rb_notimplement();
01748 #endif
01749 }
01750 
01751 
01752 /*
01753  *  call-seq:
01754  *     Process.getpriority(kind, integer)   => fixnum
01755  *
01756  *  Gets the scheduling priority for specified process, process group,
01757  *  or user. <em>kind</em> indicates the kind of entity to find: one
01758  *  of <code>Process::PRIO_PGRP</code>,
01759  *  <code>Process::PRIO_USER</code>, or
01760  *  <code>Process::PRIO_PROCESS</code>. _integer_ is an id
01761  *  indicating the particular process, process group, or user (an id
01762  *  of 0 means _current_). Lower priorities are more favorable
01763  *  for scheduling. Not available on all platforms.
01764  *
01765  *     Process.getpriority(Process::PRIO_USER, 0)      #=> 19
01766  *     Process.getpriority(Process::PRIO_PROCESS, 0)   #=> 19
01767  */
01768 
01769 static VALUE
01770 proc_getpriority(obj, which, who)
01771     VALUE obj, which, who;
01772 {
01773 #ifdef HAVE_GETPRIORITY
01774     int prio, iwhich, iwho;
01775 
01776     rb_secure(2);
01777     iwhich = NUM2INT(which);
01778     iwho   = NUM2INT(who);
01779 
01780     errno = 0;
01781     prio = getpriority(iwhich, iwho);
01782     if (errno) rb_sys_fail(0);
01783     return INT2FIX(prio);
01784 #else
01785     rb_notimplement();
01786 #endif
01787 }
01788 
01789 
01790 /*
01791  *  call-seq:
01792  *     Process.setpriority(kind, integer, priority)   => 0
01793  *
01794  *  See <code>Process#getpriority</code>.
01795  *
01796  *     Process.setpriority(Process::PRIO_USER, 0, 19)      #=> 0
01797  *     Process.setpriority(Process::PRIO_PROCESS, 0, 19)   #=> 0
01798  *     Process.getpriority(Process::PRIO_USER, 0)          #=> 19
01799  *     Process.getpriority(Process::PRIO_PROCESS, 0)       #=> 19
01800  */
01801 
01802 static VALUE
01803 proc_setpriority(obj, which, who, prio)
01804     VALUE obj, which, who, prio;
01805 {
01806 #ifdef HAVE_GETPRIORITY
01807     int iwhich, iwho, iprio;
01808 
01809     rb_secure(2);
01810     iwhich = NUM2INT(which);
01811     iwho   = NUM2INT(who);
01812     iprio  = NUM2INT(prio);
01813 
01814     if (setpriority(iwhich, iwho, iprio) < 0)
01815         rb_sys_fail(0);
01816     return INT2FIX(0);
01817 #else
01818     rb_notimplement();
01819 #endif
01820 }
01821 
01822 static int under_uid_switch = 0;
01823 static void
01824 check_uid_switch()
01825 {
01826     rb_secure(2);
01827     if (under_uid_switch) {
01828         rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
01829     }
01830 }
01831 
01832 static int under_gid_switch = 0;
01833 static void
01834