I still have some process additions that I'd like to see in the standard
Ruby process.c (if only because it feels that they should be standard).
They include the wait-flags, Process.waitall, and now Process.gids/
Process.groups, useful because on many platforms there will be multiple
groups that a user may belong to.
I believe the work I have done will enable these extensions to work on other
systems (that is, e.g., ones without getgroups()). Let me know what you all
think. I also made a change for consistency to file.c, to set the NGROUPS
according to NGROUPS_MAX if possible. Thanks for your time!
--- file.c.orig Fri Oct 20 20:21:21 2000
+++ file.c Fri Oct 20 20:22:11 2000
@@ -390,7 +390,9 @@
return Qtrue;
# ifdef HAVE_GETGROUPS
-# ifndef NGROUPS
+# ifdef NGROUPS_MAX
+# define NGROUPS NGROUPS_MAX
+# else
# define NGROUPS 32
# endif
{
--- process.c.orig Tue Oct 17 14:13:58 2000
+++ process.c Fri Oct 20 20:32:00 2000
@@ -158,6 +158,30 @@
data->status = value;
return ST_DELETE;
}
+
+struct waitall_data {
+ int pid;
+ int status;
+ VALUE ary;
+}
+
+static int
+waitall_each(key, value, data)
+ int key, value;
+ struct wait_data *data;
+{
+ VALUE pid_status_member;
+
+ if (data->status != -1) return ST_STOP;
+
+ data->pid = key;
+ data->status = value;
+ pid_status_member = rb_ary_new2(2);
+ rb_ary_push(pid_status_member, INT2NUM(key));
+ rb_ary_push(pid_status_member, INT2NUM(value));
+ rb_ary_push(data->ary, pid_status_member);
+ return ST_DELETE;
+}
#endif
static VALUE
@@ -230,6 +254,135 @@
return rb_assoc_new(pid, rb_last_status);
}
+static VALUE
+rb_f_waitall()
+{
+ VALUE pid_status_ary, pid_status_member;
+ int pid, state;
+#ifdef NO_WAITPID
+ struct waitall_data data;
+
+ data.ary = pid_status_ary = rb_ary_new();
+ data.status = -1;
+ st_foreach(pid_tbl, waitall_each, &data);
+ if (data.status != -1) {
+ rb_last_status = data.status;
+ return pid_status_ary;
+ }
+
+ for (pid = -1;;) {
+ pid = wait(&state);
+ if (pid == -1) {
+ if (errno == ECHILD)
+ break;
+ if (errno == EINTR) {
+ rb_thread_schedule();
+ continue;
+ }
+ rb_sys_fail(0);
+ }
+ pid_status_member = rb_ary_new2(2);
+ rb_ary_push(pid_status_member, INT2NUM(pid));
+ rb_ary_push(pid_status_member, INT2NUM(state));
+ rb_ary_push(pid_status_ary, pid_status_member);
+ }
+ if (RARRAY(pid_status_ary)->len != 0)
+ rb_last_status = INT2FIX(state);
+#else
+ pid_status_ary = rb_ary_new();
+ for (pid = -1;;) {
+ pid = rb_waitpid(-1, 0, &state);
+ if (pid == -1) {
+ if (errno == ECHILD)
+ break;
+ rb_sys_fail(0);
+ }
+ pid_status_member = rb_ary_new2(2);
+ rb_ary_push(pid_status_member, INT2NUM(pid));
+ rb_ary_push(pid_status_member, INT2NUM(state));
+ rb_ary_push(pid_status_ary, pid_status_member);
+ }
+#endif
+ return pid_status_ary;
+}
+
+static VALUE
+rb_f_wifstopped(obj, statusnum)
+ VALUE obj, statusnum;
+{
+ int status = NUM2INT(statusnum);
+
+ if (WIFSTOPPED(status))
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+static VALUE
+rb_f_wstopsig(obj, statusnum)
+ VALUE obj, statusnum;
+{
+ int status = NUM2INT(statusnum);
+
+ return INT2NUM(WSTOPSIG(status));
+}
+
+static VALUE
+rb_f_wifsignaled(obj, statusnum)
+ VALUE obj, statusnum;
+{
+ int status = NUM2INT(statusnum);
+
+ if (WIFSIGNALED(status))
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+static VALUE
+rb_f_wtermsig(obj, statusnum)
+ VALUE obj, statusnum;
+{
+ int status = NUM2INT(statusnum);
+
+ return INT2NUM(WTERMSIG(status));
+}
+
+static VALUE
+rb_f_wifexited(obj, statusnum)
+ VALUE obj, statusnum;
+{
+ int status = NUM2INT(statusnum);
+
+ if (WIFEXITED(status))
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+static VALUE
+rb_f_wexitstatus(obj, statusnum)
+ VALUE obj, statusnum;
+{
+ int status = NUM2INT(statusnum);
+
+ return INT2NUM(WEXITSTATUS(status));
+}
+
+#ifdef WCOREDUMP
+static VALUE
+rb_f_wcoredump(obj, statusnum)
+ VALUE obj, statusnum;
+{
+ int status = NUM2INT(statusnum);
+
+ if (WCOREDUMP(status))
+ return Qtrue;
+ else
+ return Qfalse;
+}
+#endif
+
char *strtok();
#ifdef HAVE_SETITIMER
@@ -993,6 +1146,33 @@
}
static VALUE
+proc_getgroups(obj)
+ VALUE obj;
+{
+# ifdef HAVE_GETGROUPS
+# ifdef NGROUPS_MAX
+# define NGROUPS NGROUPS_MAX
+# else
+# define NGROUPS 32
+# endif
+ GETGROUPS_T gary[NGROUPS];
+ VALUE groups;
+ int anum, i;
+
+ anum = getgroups(NGROUPS, gary);
+ if (anum == -1)
+ rb_sys_fail(0);
+ groups = rb_ary_new2(anum);
+ for (i = 0; i < anum; i++)
+ rb_ary_push(groups, INT2NUM(gary[i]));
+
+ return groups;
+# else
+ return rb_ary_new3(1, proc_getgid());
+# endif
+}
+
+static VALUE
proc_geteuid(obj)
VALUE obj;
{
@@ -1083,8 +1263,18 @@
#ifndef NT
rb_define_module_function(rb_mProcess, "wait", proc_wait, 0);
rb_define_module_function(rb_mProcess, "wait2", proc_wait2, 0);
+ rb_define_module_function(rb_mProcess, "waitall", rb_f_waitall, 0);
rb_define_module_function(rb_mProcess, "waitpid", proc_waitpid, -1);
rb_define_module_function(rb_mProcess, "waitpid2", proc_waitpid2, -1);
+ rb_define_module_function(rb_mProcess, "wifstopped", rb_f_wifstopped, 1);
+ rb_define_module_function(rb_mProcess, "wstopsig", rb_f_wstopsig, 1);
+ rb_define_module_function(rb_mProcess, "wifsignaled", rb_f_wifsignaled, 1);
+ rb_define_module_function(rb_mProcess, "wtermsig", rb_f_wtermsig, 1);
+ rb_define_module_function(rb_mProcess, "wifexited", rb_f_wifexited, 1);
+ rb_define_module_function(rb_mProcess, "wexitstatus", rb_f_wexitstatus, 1);
+#ifdef WCOREDUMP
+ rb_define_module_function(rb_mProcess, "wcoredump", rb_f_wcoredump, 1);
+#endif
rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
@@ -1114,4 +1304,6 @@
rb_define_module_function(rb_mProcess, "euid=", proc_seteuid, 1);
rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
rb_define_module_function(rb_mProcess, "egid=", proc_setegid, 1);
+ rb_define_module_function(rb_mProcess, "gids", proc_getgroups, 0);
+ rb_define_module_function(rb_mProcess, "groups", proc_getgroups, 0);
}
--
Brian Fundakowski Feldman \ FreeBSD: The Power to Serve! /
green / FreeBSD.org `------------------------------'