summaryrefslogtreecommitdiff
path: root/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'process.c')
-rw-r--r--process.c1007
1 files changed, 1004 insertions, 3 deletions
diff --git a/process.c b/process.c
index 4311032367..af9523f0c4 100644
--- a/process.c
+++ b/process.c
@@ -105,12 +105,40 @@ static VALUE S_Tms;
#endif
#endif
+
+/*
+ * call-seq:
+ * Process.pid => fixnum
+ *
+ * Returns the process id of this process. Not available on all
+ * platforms.
+ *
+ * Process.pid #=> 27415
+ */
+
static VALUE
get_pid()
{
return INT2FIX(getpid());
}
+
+/*
+ * call-seq:
+ * Process.ppid => fixnum
+ *
+ * Returns the process id of the parent of this process. Always
+ * returns 0 on NT. Not available on all platforms.
+ *
+ * puts "I am #{Process.pid}"
+ * Process.fork { puts "Dad is #{Process.ppid}" }
+ *
+ * <em>produces:</em>
+ *
+ * I am 27417
+ * Dad is 27417
+ */
+
static VALUE
get_ppid()
{
@@ -121,6 +149,37 @@ get_ppid()
#endif
}
+
+/*********************************************************************
+ *
+ * Document-class: Process::Status
+ *
+ * <code>Process::Status</code> encapsulates the information on the
+ * status of a running or terminated system process. The built-in
+ * variable <code>$?</code> is either +nil+ or a
+ * <code>Process::Status</code> object.
+ *
+ * fork { exit 99 } #=> 26557
+ * Process.wait #=> 26557
+ * $?.class #=> Process::Status
+ * $?.to_i #=> 25344
+ * $? >> 8 #=> 99
+ * $?.stopped? #=> false
+ * $?.exited? #=> true
+ * $?.exitstatus #=> 99
+ *
+ * Posix systems record information on processes using a 16-bit
+ * integer. The lower bits record the process status (stopped,
+ * exited, signaled) and the upper bits possibly contain additional
+ * information (for example the program's return code in the case of
+ * exited processes). Pre Ruby 1.8, these bits were exposed directly
+ * to the Ruby program. Ruby now encapsulates these in a
+ * <code>Process::Status</code> object. To maximize compatibility,
+ * however, these objects retain a bit-oriented interface. In the
+ * descriptions that follow, when we talk about the integer value of
+ * _stat_, we're referring to this 16 bit value.
+ */
+
static VALUE rb_cProcStatus;
VALUE rb_last_status = Qnil;
@@ -133,6 +192,20 @@ last_status_set(status, pid)
rb_iv_set(rb_last_status, "pid", INT2FIX(pid));
}
+
+/*
+ * call-seq:
+ * stat.to_i => fixnum
+ * stat.to_int => fixnum
+ *
+ * Returns the bits in _stat_ as a <code>Fixnum</code>. Poking
+ * around in these bits is platform dependent.
+ *
+ * fork { exit 0xab } #=> 26566
+ * Process.wait #=> 26566
+ * sprintf('%04x', $?.to_i) #=> "ab00"
+ */
+
static VALUE
pst_to_i(st)
VALUE st;
@@ -140,6 +213,14 @@ pst_to_i(st)
return rb_iv_get(st, "status");
}
+
+/*
+ * call-seq:
+ * stat.to_s => string
+ *
+ * Equivalent to _stat_<code>.to_i.to_s</code>.
+ */
+
static VALUE
pst_to_s(st)
VALUE st;
@@ -147,6 +228,18 @@ pst_to_s(st)
return rb_fix2str(pst_to_i(st), 10);
}
+
+/*
+ * call-seq:
+ * stat.pid => fixnum
+ *
+ * Returns the process ID that this status object represents.
+ *
+ * fork { exit } #=> 26569
+ * Process.wait #=> 26569
+ * $?.pid #=> 26569
+ */
+
static VALUE
pst_pid(st)
VALUE st;
@@ -154,6 +247,14 @@ pst_pid(st)
return rb_iv_get(st, "pid");
}
+
+/*
+ * call-seq:
+ * stat.inspect => string
+ *
+ * Override the inspection method.
+ */
+
static VALUE
pst_inspect(st)
VALUE st;
@@ -203,6 +304,15 @@ pst_inspect(st)
return str;
}
+
+/*
+ * call-seq:
+ * stat == other => true or false
+ *
+ * Returns +true+ if the integer value of _stat_
+ * equals <em>other</em>.
+ */
+
static VALUE
pst_equal(st1, st2)
VALUE st1, st2;
@@ -211,6 +321,19 @@ pst_equal(st1, st2)
return rb_equal(pst_to_i(st1), st2);
}
+
+/*
+ * call-seq:
+ * stat & num => fixnum
+ *
+ * Logical AND of the bits in _stat_ with <em>num</em>.
+ *
+ * fork { exit 0x37 }
+ * Process.wait
+ * sprintf('%04x', $?.to_i) #=> "3700"
+ * sprintf('%04x', $? & 0x1e00) #=> "1600"
+ */
+
static VALUE
pst_bitand(st1, st2)
VALUE st1, st2;
@@ -220,6 +343,19 @@ pst_bitand(st1, st2)
return INT2NUM(status);
}
+
+/*
+ * call-seq:
+ * stat >> num => fixnum
+ *
+ * Shift the bits in _stat_ right <em>num</em> places.
+ *
+ * fork { exit 99 } #=> 26563
+ * Process.wait #=> 26563
+ * $?.to_i #=> 25344
+ * $? >> 8 #=> 99
+ */
+
static VALUE
pst_rshift(st1, st2)
VALUE st1, st2;
@@ -229,6 +365,16 @@ pst_rshift(st1, st2)
return INT2NUM(status);
}
+
+/*
+ * call-seq:
+ * stat.stopped? => true or false
+ *
+ * Returns +true+ if this process is stopped. This is only
+ * returned if the corresponding <code>wait</code> call had the
+ * <code>WUNTRACED</code> flag set.
+ */
+
static VALUE
pst_wifstopped(st)
VALUE st;
@@ -241,6 +387,15 @@ pst_wifstopped(st)
return Qfalse;
}
+
+/*
+ * call-seq:
+ * stat.stopsig => fixnum or nil
+ *
+ * Returns the number of the signal that caused _stat_ to stop
+ * (or +nil+ if self is not stopped).
+ */
+
static VALUE
pst_wstopsig(st)
VALUE st;
@@ -252,6 +407,15 @@ pst_wstopsig(st)
return Qnil;
}
+
+/*
+ * call-seq:
+ * stat.signaled? => true or false
+ *
+ * Returns +true+ if _stat_ terminated because of
+ * an uncaught signal.
+ */
+
static VALUE
pst_wifsignaled(st)
VALUE st;
@@ -264,6 +428,16 @@ pst_wifsignaled(st)
return Qfalse;
}
+
+/*
+ * call-seq:
+ * stat.termsig => fixnum or nil
+ *
+ * Returns the number of the signal that caused _stat_ to
+ * terminate (or +nil+ if self was not terminated by an
+ * uncaught signal).
+ */
+
static VALUE
pst_wtermsig(st)
VALUE st;
@@ -275,6 +449,16 @@ pst_wtermsig(st)
return Qnil;
}
+
+/*
+ * call-seq:
+ * stat.exited? => true or false
+ *
+ * Returns +true+ if _stat_ exited normally (for
+ * example using an <code>exit()</code> call or finishing the
+ * program).
+ */
+
static VALUE
pst_wifexited(st)
VALUE st;
@@ -287,6 +471,26 @@ pst_wifexited(st)
return Qfalse;
}
+
+/*
+ * call-seq:
+ * stat.exitstatus => fixnum or nil
+ *
+ * Returns the least significant eight bits of the return code of
+ * _stat_. Only available if <code>exited?</code> is
+ * +true+.
+ *
+ * fork { } #=> 26572
+ * Process.wait #=> 26572
+ * $?.exited? #=> true
+ * $?.exitstatus #=> 0
+ *
+ * fork { exit 99 } #=> 26573
+ * Process.wait #=> 26573
+ * $?.exited? #=> true
+ * $?.exitstatus #=> 99
+ */
+
static VALUE
pst_wexitstatus(st)
VALUE st;
@@ -298,6 +502,15 @@ pst_wexitstatus(st)
return Qnil;
}
+
+/*
+ * call-seq:
+ * stat.coredump => true or false
+ *
+ * Returns +true+ if _stat_ generated a coredump
+ * when it terminated. Not available on all platforms.
+ */
+
static VALUE
pst_wcoredump(st)
VALUE st;
@@ -419,6 +632,69 @@ waitall_each(pid, status, ary)
}
#endif
+
+/* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
+ has historically been documented as if it didn't take any arguments
+ despite the fact that it's just an alias for ::waitpid(). The way I
+ have it below is more truthful, but a little confusing.
+
+ I also took the liberty of putting in the pid values, as they're
+ pretty useful, and it looked as if the original 'ri' output was
+ supposed to contain them after "[...]depending on the value of
+ aPid:".
+
+ The 'ansi' and 'bs' formats of the ri output don't display the
+ definition list for some reason, but the plain text one does.
+ */
+
+/*
+ * call-seq:
+ * Process.wait() => fixnum
+ * Process.wait(pid=-1, flags=0) => fixnum
+ * Process.waitpid(pid=-1, flags=0) => fixnum
+ *
+ * Waits for a child process to exit, returns its process id, and
+ * sets <code>$?</code> to a <code>Process::Status</code> object
+ * containing information on that process. Which child it waits on
+ * depends on the value of _pid_:
+ *
+ * > 0:: Waits for the child whose process ID equals _pid_.
+ *
+ * 0:: Waits for any child whose process group ID equals that of the
+ * calling process.
+ * adsasdasd sads adada dsa a sad ad asd sad sa dsa dasdsad asd asd
+ * adsasdasd sads adada dsa a sad ad asd sad sa dsa dasdsad asd asd
+ * adsasdasd sads adada dsa a sad ad asd sad sa dsa dasdsad asd asd
+ * adsasdasd sads adada dsa a sad ad asd sad sa dsa dasdsad asd asd
+ *
+ * -1:: Waits for any child process (the default if no _pid_ is
+ * given).
+ *
+ * < -1:: Waits for any child whose process group ID equals the absolute
+ * value of _pid_.
+ *
+ * The _flags_ argument may be a logical or of the flag values
+ * <code>Process::WNOHANG</code> (do not block if no child available)
+ * or <code>Process::WUNTRACED</code> (return stopped children that
+ * haven't been reported). Not all flags are available on all
+ * platforms, but a flag value of zero will work on all platforms.
+ *
+ * Calling this method raises a <code>SystemError</code> if there are
+ * no child processes. Not available on all platforms.
+ *
+ * include Process
+ * fork { exit 99 } #=> 27429
+ * wait #=> 27429
+ * $?.exitstatus #=> 99
+ *
+ * pid = fork { sleep 3 } #=> 27440
+ * Time.now #=> Wed Apr 09 08:57:09 CDT 2003
+ * waitpid(pid, Process::WNOHANG) #=> nil
+ * Time.now #=> Wed Apr 09 08:57:09 CDT 2003
+ * waitpid(pid, 0) #=> 27440
+ * Time.now #=> Wed Apr 09 08:57:12 CDT 2003
+ */
+
static VALUE
proc_wait(argc, argv)
int argc;
@@ -446,6 +722,24 @@ proc_wait(argc, argv)
return INT2FIX(pid);
}
+
+/*
+ * call-seq:
+ * Process.wait2(pid=-1, flags=0) => [pid, status]
+ * Process.waitpid2(pid=-1, flags=0) => [pid, status]
+ *
+ * Waits for a child process to exit (see Process::waitpid for exact
+ * semantics) and returns an array containing the process id and the
+ * exit status (a <code>Process::Status</code> object) of that
+ * child. Raises a <code>SystemError</code> if there are no child
+ * processes.
+ *
+ * Process.fork { exit 99 } #=> 27437
+ * pid, status = Process.wait2
+ * pid #=> 27437
+ * status.exitstatus #=> 99
+ */
+
static VALUE
proc_wait2(argc, argv)
int argc;
@@ -456,6 +750,27 @@ proc_wait2(argc, argv)
return rb_assoc_new(pid, rb_last_status);
}
+
+/*
+ * call-seq:
+ * Process.waitall => [ [pid1,status1], ...]
+ *
+ * Waits for all children, returning an array of
+ * _pid_/_status_ pairs (where _status_ is a
+ * <code>Process::Status</code> object).
+ *
+ * fork { sleep 0.2; exit 2 } #=> 27432
+ * fork { sleep 0.1; exit 1 } #=> 27433
+ * fork { exit 0 } #=> 27434
+ * p Process.waitall
+ *
+ * <em>produces</em>:
+ *
+ * [[27434, #<Process::Status: pid=27434,exited(0)>],
+ * [27433, #<Process::Status: pid=27433,exited(1)>],
+ * [27432, #<Process::Status: pid=27432,exited(2)>]]
+ */
+
static VALUE
proc_waitall()
{
@@ -517,6 +832,48 @@ rb_detach_process(pid)
return rb_thread_create(detach_process_watcer, (void*)&pid);
}
+
+/*
+ * call-seq:
+ * Process.detach(pid) => thread
+ *
+ * Some operating systems retain the status of terminated child
+ * processes until the parent collects that status (normally using
+ * some variant of <code>wait()</code>. If the parent never collects
+ * this status, the child stays around as a <em>zombie</em> process.
+ * <code>Process::detach</code> prevents this by setting up a
+ * separate Ruby thread whose sole job is to reap the status of the
+ * process _pid_ when it terminates. Use <code>detach</code>
+ * only when you do not intent to explicitly wait for the child to
+ * terminate. <code>detach</code> only checks the status
+ * periodically (currently once each second).
+ *
+ * In this first example, we don't reap the first child process, so
+ * it appears as a zombie in the process status display.
+ *
+ * p1 = fork { sleep 0.1 }
+ * p2 = fork { sleep 0.2 }
+ * Process.waitpid(p2)
+ * sleep 2
+ * system("ps -ho pid,state -p #{p1}")
+ *
+ * <em>produces:</em>
+ *
+ * 27389 Z
+ *
+ * In the next example, <code>Process::detach</code> is used to reap
+ * the child automatically.
+ *
+ * p1 = fork { sleep 0.1 }
+ * p2 = fork { sleep 0.2 }
+ * Process.detach(p1)
+ * Process.waitpid(p2)
+ * sleep 2
+ * system("ps -ho pid,state -p #{p1}")
+ *
+ * <em>(produces no output)</em>
+ */
+
static VALUE
proc_detach(obj, pid)
VALUE pid;
@@ -798,6 +1155,31 @@ proc_spawn(sv)
#endif
#endif
+/*
+ * call-seq:
+ * exec(command [, arg, ...])
+ *
+ * Replaces the current process by running the given external _command_.
+ * If +exec+ is given a single argument, that argument is
+ * taken as a line that is subject to shell expansion before being
+ * executed. If multiple arguments are given, the second and subsequent
+ * arguments are passed as parameters to _command_ with no shell
+ * expansion. If the first argument is a two-element array, the first
+ * element is the command to be executed, and the second argument is
+ * used as the <code>argv[0]</code> value, which may show up in process
+ * listings. In MSDOS environments, the command is executed in a
+ * subshell; otherwise, one of the <code>exec(2)</code> system calls is
+ * used, so the running command may inherit some of the environment of
+ * the original program (including open file descriptors).
+ *
+ * exec "echo *" # echoes list of files in current directory
+ * # never get here
+ *
+ *
+ * exec "echo", "*" # echoes an asterisk
+ * # never get here
+ */
+
VALUE
rb_f_exec(argc, argv)
int argc;
@@ -832,6 +1214,14 @@ rb_f_exec(argc, argv)
return Qnil; /* dummy */
}
+
+/*
+ * call-seq:
+ * Process.fork [{ block }] => fixnum or nil
+ *
+ * See <code>Kernel::fork</code>.
+ */
+
static VALUE
rb_f_fork(obj)
VALUE obj;
@@ -866,6 +1256,18 @@ rb_f_fork(obj)
#endif
}
+
+/*
+ * call-seq:
+ * Process.exit!(fixnum=-1)
+ *
+ * Exits the process immediately. No exit handlers are
+ * run. <em>fixnum</em> is returned to the underlying system as the
+ * exit status.
+ *
+ * Process.exit!(0)
+ */
+
static VALUE
rb_f_exit_bang(argc, argv, obj)
int argc;
@@ -934,6 +1336,25 @@ rb_syswait(pid)
}
}
+/*
+ * call-seq:
+ * system(cmd [, arg, ...]) => true or false
+ *
+ * Executes _cmd_ in a subshell, returning +true+ if
+ * the command was found and ran successfully, +false+
+ * otherwise. An error status is available in <code>$?</code>. The
+ * arguments are processed in the same way as for
+ * <code>Kernel::exec</code>.
+ *
+ * system("echo *")
+ * system("echo", "*")
+ *
+ * <em>produces:</em>
+ *
+ * config.h main.rb
+ * *
+ */
+
static VALUE
rb_f_system(argc, argv)
int argc;
@@ -1071,6 +1492,24 @@ rb_f_system(argc, argv)
return Qfalse;
}
+/*
+ * call-seq:
+ * sleep(duration=0) => fixnum
+ *
+ * Suspends the current thread for _duraction_ seconds (which may be
+ * any number, including a +Float+ with fractional seconds). Returns the actual
+ * number of seconds slept (rounded), which may be less than that asked
+ * for if the thread was interrupted by a +SIGALRM+, or if
+ * another thread calls <code>Thread#run</code>. An argument of zero
+ * causes +sleep+ to sleep forever.
+ *
+ * Time.new #=> Wed Apr 09 08:56:32 CDT 2003
+ * sleep 1.2 #=> 1
+ * Time.new #=> Wed Apr 09 08:56:33 CDT 2003
+ * sleep 1.9 #=> 2
+ * Time.new #=> Wed Apr 09 08:56:35 CDT 2003
+ */
+
static VALUE
rb_f_sleep(argc, argv)
int argc;
@@ -1094,6 +1533,18 @@ rb_f_sleep(argc, argv)
return INT2FIX(end);
}
+
+/*
+ * call-seq:
+ * Process.getpgrp => integer
+ *
+ * Returns the process group ID for this process. Not available on
+ * all platforms.
+ *
+ * Process.getpgid(0) #=> 25527
+ * Process.getpgrp #=> 25527
+ */
+
static VALUE
proc_getpgrp()
{
@@ -1114,6 +1565,15 @@ proc_getpgrp()
#endif
}
+
+/*
+ * call-seq:
+ * Process.setpgrp => 0
+ *
+ * Equivalent to <code>setpgid(0,0)</code>. Not available on all
+ * platforms.
+ */
+
static VALUE
proc_setpgrp()
{
@@ -1131,6 +1591,17 @@ proc_setpgrp()
return INT2FIX(0);
}
+
+/*
+ * call-seq:
+ * Process.getpgid(pid) => integer
+ *
+ * Returns the process group ID for the given process id. Not
+ * available on all platforms.
+ *
+ * Process.getpgid(Process.ppid()) #=> 25527
+ */
+
static VALUE
proc_getpgid(obj, pid)
VALUE obj, pid;
@@ -1145,6 +1616,15 @@ proc_getpgid(obj, pid)
#endif
}
+
+/*
+ * call-seq:
+ * Process.setpgid(pid, integer) => 0
+ *
+ * Sets the process group ID of _pid_ (0 indicates this
+ * process) to <em>integer</em>. Not available on all platforms.
+ */
+
static VALUE
proc_setpgid(obj, pid, pgrp)
VALUE obj, pid, pgrp;
@@ -1163,6 +1643,18 @@ proc_setpgid(obj, pid, pgrp)
#endif
}
+
+/*
+ * call-seq:
+ * Process.setsid => fixnum
+ *
+ * Establishes this process as a new session and process group
+ * leader, with no controlling tty. Returns the session id. Not
+ * available on all platforms.
+ *
+ * Process.setsid #=> 27422
+ */
+
static VALUE
proc_setsid()
{
@@ -1199,6 +1691,24 @@ proc_setsid()
#endif
}
+
+/*
+ * call-seq:
+ * Process.getpriority(kind, integer) => fixnum
+ *
+ * Gets the scheduling priority for specified process, process group,
+ * or user. <em>kind</em> indicates the kind of entity to find: one
+ * of <code>Process::PRIO_PGRP</code>,
+ * <code>Process::PRIO_USER</code>, or
+ * <code>Process::PRIO_PROCESS</code>. _integer_ is an id
+ * indicating the particular process, process group, or user (an id
+ * of 0 means _current_). Lower priorities are more favorable
+ * for scheduling. Not available on all platforms.
+ *
+ * Process.getpriority(Process::PRIO_USER, 0) #=> 19
+ * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
+ */
+
static VALUE
proc_getpriority(obj, which, who)
VALUE obj, which, who;
@@ -1218,6 +1728,19 @@ proc_getpriority(obj, which, who)
#endif
}
+
+/*
+ * call-seq:
+ * Process.setpriority(kind, integer, priority) => 0
+ *
+ * See <code>Process#getpriority</code>.
+ *
+ * Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0
+ * Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0
+ * Process.getpriority(Process::PRIO_USER, 0) #=> 19
+ * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
+ */
+
static VALUE
proc_setpriority(obj, which, who, prio)
VALUE obj, which, who, prio;
@@ -1258,6 +1781,27 @@ check_gid_switch()
}
}
+
+/*********************************************************************
+ * Document-class: Process::Sys
+ *
+ * The <code>Process::Sys</code> module contains UID and GID
+ * functions which provide direct bindings to the system calls of the
+ * same names instead of the more-portable versions of the same
+ * functionality found in the <code>Process</code>,
+ * <code>Process::UID</code>, and <code>Process::GID</code> modules.
+ */
+
+
+/*
+ * call-seq:
+ * Process::Sys.setuid(integer) => nil
+ *
+ * Set the user ID of the current process to _integer_. Not
+ * available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setuid(obj, id)
VALUE obj, id;
@@ -1271,6 +1815,17 @@ p_sys_setuid(obj, id)
return Qnil;
}
+
+
+/*
+ * call-seq:
+ * Process::Sys.setruid(integer) => nil
+ *
+ * Set the real user ID of the calling process to _integer_.
+ * Not available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setruid(obj, id)
VALUE obj, id;
@@ -1284,6 +1839,16 @@ p_sys_setruid(obj, id)
return Qnil;
}
+
+/*
+ * call-seq:
+ * Process::Sys.seteuid(integer) => nil
+ *
+ * Set the effective user ID of the calling process to
+ * _integer_. Not available on all platforms.
+ *
+ */
+
static VALUE
p_sys_seteuid(obj, id)
VALUE obj, id;
@@ -1297,6 +1862,18 @@ p_sys_seteuid(obj, id)
return Qnil;
}
+
+/*
+ * call-seq:
+ * Process::Sys.setreuid(rid, eid) => nil
+ *
+ * Sets the (integer) real and/or effective user IDs of the current
+ * process to _rid_ and _eid_, respectively. A value of
+ * <code>-1</code> for either means to leave that ID unchanged. Not
+ * available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setreuid(obj, rid, eid)
VALUE obj, rid, eid;
@@ -1310,6 +1887,18 @@ p_sys_setreuid(obj, rid, eid)
return Qnil;
}
+
+/*
+ * call-seq:
+ * Process::Sys.setresuid(rid, eid, sid) => nil
+ *
+ * Sets the (integer) real, effective, and saved user IDs of the
+ * current process to _rid_, _eid_, and _sid_ respectively. A
+ * value of <code>-1</code> for any value means to
+ * leave that ID unchanged. Not available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setresuid(obj, rid, eid, sid)
VALUE obj, rid, eid, sid;
@@ -1323,6 +1912,18 @@ p_sys_setresuid(obj, rid, eid, sid)
return Qnil;
}
+
+/*
+ * call-seq:
+ * Process.uid => fixnum
+ * Process::UID.rid => fixnum
+ * Process::Sys.getuid => fixnum
+ *
+ * Returns the (real) user ID of this process.
+ *
+ * Process.uid #=> 501
+ */
+
static VALUE
proc_getuid(obj)
VALUE obj;
@@ -1331,6 +1932,15 @@ proc_getuid(obj)
return INT2FIX(uid);
}
+
+/*
+ * call-seq:
+ * Process.uid= integer => numeric
+ *
+ * Sets the (integer) user ID for this process. Not available on all
+ * platforms.
+ */
+
static VALUE
proc_setuid(obj, id)
VALUE obj, id;
@@ -1359,8 +1969,33 @@ proc_setuid(obj, id)
return INT2FIX(uid);
}
+
+/********************************************************************
+ *
+ * Document-class: Process::UID
+ *
+ * The <code>Process::UID</code> module contains a collection of
+ * module functions which can be used to portably get, set, and
+ * switch the current process's real, effective, and saved user IDs.
+ *
+ */
+
static int SAVED_USER_ID;
+
+/*
+ * call-seq:
+ * Process::UID.change_privilege(integer) => fixnum
+ *
+ * Change the current process's real and effective user ID to that
+ * specified by _integer_. Returns the new user ID. Not
+ * available on all platforms.
+ *
+ * [Process.uid, Process.euid] #=> [0, 0]
+ * Process::UID.change_privilege(31) #=> 31
+ * [Process.uid, Process.euid] #=> [31, 31]
+ */
+
static VALUE
p_uid_change_privilege(obj, id)
VALUE obj, id;
@@ -1501,6 +2136,17 @@ p_uid_change_privilege(obj, id)
return INT2FIX(uid);
}
+
+
+/*
+ * call-seq:
+ * Process::Sys.setgid(integer) => nil
+ *
+ * Set the group ID of the current process to _integer_. Not
+ * available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setgid(obj, id)
VALUE obj, id;
@@ -1514,6 +2160,16 @@ p_sys_setgid(obj, id)
return Qnil;
}
+
+/*
+ * call-seq:
+ * Process::Sys.setrgid(integer) => nil
+ *
+ * Set the real group ID of the calling process to _integer_.
+ * Not available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setrgid(obj, id)
VALUE obj, id;
@@ -1527,6 +2183,17 @@ p_sys_setrgid(obj, id)
return Qnil;
}
+
+
+/*
+ * call-seq:
+ * Process::Sys.setegid(integer) => nil
+ *
+ * Set the effective group ID of the calling process to
+ * _integer_. Not available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setegid(obj, id)
VALUE obj, id;
@@ -1540,6 +2207,18 @@ p_sys_setegid(obj, id)
return Qnil;
}
+
+/*
+ * call-seq:
+ * Process::Sys.setregid(rid, eid) => nil
+ *
+ * Sets the (integer) real and/or effective group IDs of the current
+ * process to <em>rid</em> and <em>eid</em>, respectively. A value of
+ * <code>-1</code> for either means to leave that ID unchanged. Not
+ * available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setregid(obj, rid, eid)
VALUE obj, rid, eid;
@@ -1553,6 +2232,17 @@ p_sys_setregid(obj, rid, eid)
return Qnil;
}
+/*
+ * call-seq:
+ * Process::Sys.setresgid(rid, eid, sid) => nil
+ *
+ * Sets the (integer) real, effective, and saved user IDs of the
+ * current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
+ * respectively. A value of <code>-1</code> for any value means to
+ * leave that ID unchanged. Not available on all platforms.
+ *
+ */
+
static VALUE
p_sys_setresgid(obj, rid, eid, sid)
VALUE obj, rid, eid, sid;
@@ -1566,6 +2256,19 @@ p_sys_setresgid(obj, rid, eid, sid)
return Qnil;
}
+
+/*
+ * call-seq:
+ * Process::Sys.issetugid => true or false
+ *
+ * Returns +true+ if the process was created as a result
+ * of an execve(2) system call which had either of the setuid or
+ * setgid bits set (and extra privileges were given as a result) or
+ * if it has changed any of its real, effective or saved user or
+ * group IDs since it began execution.
+ *
+ */
+
static VALUE
p_sys_issetugid(obj)
VALUE obj;
@@ -1582,6 +2285,18 @@ p_sys_issetugid(obj)
#endif
}
+
+/*
+ * call-seq:
+ * Process.gid => fixnum
+ * Process::GID.rid => fixnum
+ * Process::Sys.getgid => fixnum
+ *
+ * Returns the (real) group ID for this process.
+ *
+ * Process.gid #=> 500
+ */
+
static VALUE
proc_getgid(obj)
VALUE obj;
@@ -1590,6 +2305,14 @@ proc_getgid(obj)
return INT2FIX(gid);
}
+
+/*
+ * call-seq:
+ * Process.gid= fixnum => fixnum
+ *
+ * Sets the group ID for this process.
+ */
+
static VALUE
proc_setgid(obj, id)
VALUE obj, id;
@@ -1621,6 +2344,18 @@ proc_setgid(obj, id)
static size_t maxgroups = 32;
+
+/*
+ * call-seq:
+ * Process.groups => array
+ *
+ * Get an <code>Array</code> of the gids of groups in the
+ * supplemental group access list for this process.
+ *
+ * Process.groups #=> [27, 6, 10, 11]
+ *
+ */
+
static VALUE
proc_getgroups(VALUE obj)
{
@@ -1647,6 +2382,20 @@ proc_getgroups(VALUE obj)
#endif
}
+
+/*
+ * call-seq:
+ * Process.groups= array => array
+ *
+ * Set the supplemental group access list to the given
+ * <code>Array</code> of group IDs.
+ *
+ * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
+ * Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11]
+ * Process.groups #=> [27, 6, 10, 11]
+ *
+ */
+
static VALUE
proc_setgroups(VALUE obj, VALUE ary)
{
@@ -1697,6 +2446,24 @@ proc_setgroups(VALUE obj, VALUE ary)
#endif
}
+
+/*
+ * call-seq:
+ * Process.initgroups(username, gid) => array
+ *
+ * Initializes the supplemental group access list by reading the
+ * system group database and using all groups of which the given user
+ * is a member. The group with the specified <em>gid</em> is also
+ * added to the list. Returns the resulting <code>Array</code> of the
+ * gids of all the groups in the supplementary group access list. Not
+ * available on all platforms.
+ *
+ * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
+ * Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
+ * Process.groups #=> [30, 6, 10, 11]
+ *
+ */
+
static VALUE
proc_initgroups(obj, uname, base_grp)
VALUE obj, uname, base_grp;
@@ -1712,6 +2479,17 @@ proc_initgroups(obj, uname, base_grp)
#endif
}
+
+/*
+ * call-seq:
+ * Process.maxgroups => fixnum
+ *
+ * Returns the maximum number of gids allowed in the supplemental
+ * group access list.
+ *
+ * Process.maxgroups #=> 32
+ */
+
static VALUE
proc_getmaxgroups(obj)
VALUE obj;
@@ -1719,6 +2497,15 @@ proc_getmaxgroups(obj)
return INT2FIX(maxgroups);
}
+
+/*
+ * call-seq:
+ * Process.maxgroups= fixnum => fixnum
+ *
+ * Sets the maximum number of gids allowed in the supplemental group
+ * access list.
+ */
+
static VALUE
proc_setmaxgroups(obj, val)
VALUE obj;
@@ -1733,8 +2520,33 @@ proc_setmaxgroups(obj, val)
return INT2FIX(maxgroups);
}
+
+/********************************************************************
+ *
+ * Document-class: Process::GID
+ *
+ * The <code>Process::GID</code> module contains a collection of
+ * module functions which can be used to portably get, set, and
+ * switch the current process's real, effective, and saved group IDs.
+ *
+ */
+
static int SAVED_GROUP_ID;
+
+/*
+ * call-seq:
+ * Process::GID.change_privilege(integer) => fixnum
+ *
+ * Change the current process's real and effective group ID to that
+ * specified by _integer_. Returns the new group ID. Not
+ * available on all platforms.
+ *
+ * [Process.gid, Process.egid] #=> [0, 0]
+ * Process::GID.change_privilege(33) #=> 33
+ * [Process.gid, Process.egid] #=> [33, 33]
+ */
+
static VALUE
p_gid_change_privilege(obj, id)
VALUE obj, id;
@@ -1876,6 +2688,18 @@ p_gid_change_privilege(obj, id)
return INT2FIX(gid);
}
+
+/*
+ * call-seq:
+ * Process.euid => fixnum
+ * Process::UID.eid => fixnum
+ * Process::Sys.geteuid => fixnum
+ *
+ * Returns the effective user ID for this process.
+ *
+ * Process.euid #=> 501
+ */
+
static VALUE
proc_geteuid(obj)
VALUE obj;
@@ -1884,6 +2708,15 @@ proc_geteuid(obj)
return INT2FIX(euid);
}
+
+/*
+ * call-seq:
+ * Process.euid= integer
+ *
+ * Sets the effective user ID for this process. Not available on all
+ * platforms.
+ */
+
static VALUE
proc_seteuid(obj, euid)
VALUE obj, euid;
@@ -1944,6 +2777,21 @@ rb_seteuid_core(euid)
return INT2FIX(euid);
}
+
+/*
+ * call-seq:
+ * Process::UID.grant_privilege(integer) => fixnum
+ * Process::UID.eid= integer => fixnum
+ *
+ * Set the effective user ID, and if possible, the saved user ID of
+ * the process to the given _integer_. Returns the new
+ * effective user ID. Not available on all platforms.
+ *
+ * [Process.uid, Process.euid] #=> [0, 0]
+ * Process::UID.grant_privilege(31) #=> 31
+ * [Process.uid, Process.euid] #=> [0, 31]
+ */
+
static VALUE
p_uid_grant_privilege(obj, id)
VALUE obj, id;
@@ -1951,6 +2799,19 @@ p_uid_grant_privilege(obj, id)
return rb_seteuid_core(NUM2INT(id));
}
+
+/*
+ * call-seq:
+ * Process.egid => fixnum
+ * Process::GID.eid => fixnum
+ * Process::Sys.geteid => fixnum
+ *
+ * Returns the effective group ID for this process. Not available on
+ * all platforms.
+ *
+ * Process.egid #=> 500
+ */
+
static VALUE
proc_getegid(obj)
VALUE obj;
@@ -1960,6 +2821,15 @@ proc_getegid(obj)
return INT2FIX(egid);
}
+
+/*
+ * call-seq:
+ * Process.egid = fixnum => fixnum
+ *
+ * Sets the effective group ID for this process. Not available on all
+ * platforms.
+ */
+
static VALUE
proc_setegid(obj, egid)
VALUE obj, egid;
@@ -2021,6 +2891,21 @@ rb_setegid_core(egid)
return INT2FIX(egid);
}
+
+/*
+ * call-seq:
+ * Process::GID.grant_privilege(integer) => fixnum
+ * Process::GID.eid = integer => fixnum
+ *
+ * Set the effective group ID, and if possible, the saved group ID of
+ * the process to the given _integer_. Returns the new
+ * effective group ID. Not available on all platforms.
+ *
+ * [Process.gid, Process.egid] #=> [0, 0]
+ * Process::GID.grant_privilege(31) #=> 33
+ * [Process.gid, Process.egid] #=> [0, 33]
+ */
+
static VALUE
p_gid_grant_privilege(obj, id)
VALUE obj, id;
@@ -2028,6 +2913,16 @@ p_gid_grant_privilege(obj, id)
return rb_setegid_core(NUM2INT(id));
}
+
+/*
+ * call-seq:
+ * Process::UID.re_exchangeable? => true or false
+ *
+ * Returns +true+ if the real and effective user IDs of a
+ * process may be exchanged on the current platform.
+ *
+ */
+
static VALUE
p_uid_exchangeable()
{
@@ -2040,6 +2935,19 @@ p_uid_exchangeable()
#endif
}
+
+/*
+ * call-seq:
+ * Process::UID.re_exchange => fixnum
+ *
+ * Exchange real and effective user IDs and return the new effective
+ * user ID. Not available on all platforms.
+ *
+ * [Process.uid, Process.euid] #=> [0, 31]
+ * Process::UID.re_exchange #=> 0
+ * [Process.uid, Process.euid] #=> [31, 0]
+ */
+
static VALUE
p_uid_exchange(obj)
VALUE obj;
@@ -2063,6 +2971,16 @@ p_uid_exchange(obj)
return INT2FIX(uid);
}
+
+/*
+ * call-seq:
+ * Process::GID.re_exchangeable? => true or false
+ *
+ * Returns +true+ if the real and effective group IDs of a
+ * process may be exchanged on the current platform.
+ *
+ */
+
static VALUE
p_gid_exchangeable()
{
@@ -2075,6 +2993,19 @@ p_gid_exchangeable()
#endif
}
+
+/*
+ * call-seq:
+ * Process::GID.re_exchange => fixnum
+ *
+ * Exchange real and effective group IDs and return the new effective
+ * group ID. Not available on all platforms.
+ *
+ * [Process.gid, Process.egid] #=> [0, 33]
+ * Process::GID.re_exchange #=> 0
+ * [Process.gid, Process.egid] #=> [33, 0]
+ */
+
static VALUE
p_gid_exchange(obj)
VALUE obj;
@@ -2098,6 +3029,17 @@ p_gid_exchange(obj)
return INT2FIX(gid);
}
+/* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
+
+/*
+ * call-seq:
+ * Process::UID.sid_available? => true or false
+ *
+ * Returns +true+ if the current platform has saved user
+ * ID functionality.
+ *
+ */
+
static VALUE
p_uid_have_saved_id()
{
@@ -2118,6 +3060,20 @@ p_uid_sw_ensure(id)
return rb_seteuid_core(id);
}
+
+/*
+ * call-seq:
+ * Process::UID.switch => fixnum
+ * Process::UID.switch {|| block} => object
+ *
+ * Switch the effective and real user IDs of the current process. If
+ * a <em>block</em> is given, the user IDs will be switched back
+ * after the block is executed. Returns the new effective user ID if
+ * called without a block, and the return value of the block if one
+ * is given.
+ *
+ */
+
static VALUE
p_uid_switch(obj)
VALUE obj;
@@ -2186,6 +3142,18 @@ p_uid_switch(obj)
#endif
}
+
+/* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
+
+/*
+ * call-seq:
+ * Process::GID.sid_available? => true or false
+ *
+ * Returns +true+ if the current platform has saved group
+ * ID functionality.
+ *
+ */
+
static VALUE
p_gid_have_saved_id()
{
@@ -2205,6 +3173,20 @@ p_gid_sw_ensure(id)
return rb_setegid_core(id);
}
+
+/*
+ * call-seq:
+ * Process::GID.switch => fixnum
+ * Process::GID.switch {|| block} => object
+ *
+ * Switch the effective and real group IDs of the current process. If
+ * a <em>block</em> is given, the group IDs will be switched back
+ * after the block is executed. Returns the new effective group ID if
+ * called without a block, and the return value of the block if one
+ * is given.
+ *
+ */
+
static VALUE
p_gid_switch(obj)
VALUE obj;
@@ -2272,6 +3254,19 @@ p_gid_switch(obj)
#endif
}
+
+/*
+ * call-seq:
+ * Process.times => aStructTms
+ *
+ * Returns a <code>Tms</code> structure (see <code>Struct::Tms</code>
+ * on page 388) that contains user and system CPU times for this
+ * process.
+ *
+ * t = Process.times
+ * [ t.utime, t.stime ] #=> [0.0, 0.02]
+ */
+
VALUE
rb_proc_times(obj)
VALUE obj;
@@ -2303,6 +3298,12 @@ VALUE rb_mProcUID;
VALUE rb_mProcGID;
VALUE rb_mProcID_Syscall;
+
+/*
+ * The <code>Process</code> module is a collection of methods used to
+ * manipulate processes.
+ */
+
void
Init_process()
{
@@ -2331,10 +3332,10 @@ Init_process()
rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
- rb_define_singleton_method(rb_mProcess, "exit", rb_f_exit, -1);
- rb_define_singleton_method(rb_mProcess, "abort", rb_f_abort, -1);
+ rb_define_singleton_method(rb_mProcess, "exit", rb_f_exit, -1); // in eval.c
+ rb_define_singleton_method(rb_mProcess, "abort", rb_f_abort, -1); // in eval.c
- rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1);
+ rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1); // in signal.c
rb_define_module_function(rb_mProcess, "wait", proc_wait, -1);
rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);