summaryrefslogtreecommitdiff
path: root/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'process.c')
-rw-r--r--process.c386
1 files changed, 293 insertions, 93 deletions
diff --git a/process.c b/process.c
index 116a93f..29f61dd 100644
--- a/process.c
+++ b/process.c
@@ -6,7 +6,7 @@
$Date: 1995/01/10 10:42:47 $
created at: Tue Aug 10 14:30:50 JST 1993
- Copyright (C) 1993-1995 Yukihiro Matsumoto
+ Copyright (C) 1993-1996 Yukihiro Matsumoto
************************************************/
@@ -25,7 +25,12 @@ struct timeval {
};
#endif
-#include <sys/resource.h>
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifdef HAVE_GETPRIORITY
+# include <sys/resource.h>
+#endif
#ifdef HAVE_VFORK_H
#include <vfork.h>
#endif
@@ -51,7 +56,7 @@ get_ppid()
#define HAVE_WAITPID
#endif
-static VALUE status;
+VALUE last_status = Qnil;
#if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
static st_table *pid_tbl;
@@ -59,55 +64,72 @@ static st_table *pid_tbl;
# define WAIT_CALL
#endif
-int
-rb_waitpid(pid, flags)
+static int
+rb_waitpid(pid, flags, st)
int pid;
int flags;
+ int *st;
{
- int result, st;
+ int result;
#ifdef HAVE_WAITPID
- result = waitpid(pid, &st, flags);
+ retry:
+ result = waitpid(pid, st, flags);
+ if (result < 0) {
+ if (errno == EINTR) goto retry;
+ return -1;
+ }
#else
#ifdef HAVE_WAIT4
- result = wait4(pid, &st, flags, NULL);
+ retry:
+ result = wait4(pid, st, flags, NULL);
+ if (result < 0) {
+ if (errno == EINTR) goto retry;
+ return -1;
+ }
#else
- if (pid_tbl && st_lookup(pid_tbl, pid, &st)) {
- status = INT2FIX(st);
+ if (pid_tbl && st_lookup(pid_tbl, pid, st)) {
+ last_status = INT2FIX(*st);
st_delete(pid_tbl, &pid, NULL);
return pid;
}
if (flags)
- Fail("Can't do waitpid with flags");
+ Fatal("Can't do waitpid with flags");
for (;;) {
- result = wait(&st);
- if (result < 0) return -1;
+ result = wait(st);
+ if (result < 0) {
+ if (errno != EINTR) continue;
+ return -1;
+ }
if (result == pid) {
break;
}
if (!pid_tbl)
- pid_tbl = st_init_table(ST_NUMCMP, ST_NUMHASH);
+ pid_tbl = st_init_numtable();
st_insert(pid_tbl, pid, st);
}
#endif
#endif
- status = INT2FIX(st);
+ last_status = INT2FIX(*st);
return result;
}
#ifndef WAIT_CALL
-static int wait_pid;
-static int wait_status;
+struct wait_data {
+ int pid;
+ int status;
+}
-static wait_each(key, value)
+static wait_each(key, value, data)
int key, value;
+ struct wait_data *data;
{
- if (wait_status != -1) return ST_STOP;
+ if (data->status != -1) return ST_STOP;
- wait_pid = key;
- wait_status = value;
+ data->pid = key;
+ data->status = value;
return ST_DELETE;
}
#endif
@@ -116,21 +138,22 @@ static VALUE
f_wait()
{
int pid, state;
-
#ifndef WAIT_CALL
- wait_status = -1;
- st_foreach(pid_tbl, wait_each, NULL);
- if (wait_status != -1) {
- status = wait_status;
- return wait_pid;
+ struct wait_data data;
+
+ data.status = -1;
+ st_foreach(pid_tbl, wait_each, &data);
+ if (data.status != -1) {
+ status = data.status;
+ return data.pid;
}
#endif
if ((pid = wait(&state)) < 0) {
if (errno == ECHILD) return Qnil;
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
}
- status = INT2FIX(state);
+ last_status = INT2FIX(state);
return INT2FIX(pid);
}
@@ -138,18 +161,88 @@ static VALUE
f_waitpid(obj, vpid, vflags)
VALUE obj, vpid, vflags;
{
- int pid, flags;
+ int pid, flags, status;
- if (vflags == Qnil) flags = 0;
+ if (NIL_P(vflags)) flags = 0;
else flags = FIX2UINT(vflags);
- if ((pid = rb_waitpid(FIX2UINT(vpid), flags)) < 0)
- rb_sys_fail(Qnil);
+ if ((pid = rb_waitpid(FIX2UINT(vpid), flags, &status)) < 0)
+ rb_sys_fail(0);
return INT2FIX(pid);
}
char *strtok();
+#if defined(THREAD) && defined(HAVE_SETITIMER)
+static void
+before_exec()
+{
+ {
+ struct itimerval tval;
+
+ tval.it_interval.tv_sec = 0;
+ tval.it_interval.tv_usec = 0;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+ }
+}
+
+static void
+after_exec()
+{
+ {
+ struct itimerval tval;
+
+ tval.it_interval.tv_sec = 1;
+ tval.it_interval.tv_usec = 0;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+ }
+}
+#else
+#define before_exec()
+#define after_exec()
+#endif
+
+extern char *dln_find_exe();
+
+static int
+proc_exec_v(argv)
+ char **argv;
+{
+ char *prog;
+
+ prog = dln_find_exe(argv[0], 0);
+ if (!prog) {
+ errno = ENOENT;
+ return -1;
+ }
+ before_exec();
+ execv(prog, argv);
+ after_exec();
+ return -1;
+}
+
+static int
+proc_exec_n(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ char **args;
+ int i;
+
+ args = ALLOCA_N(char*, argc+1);
+ for (i=0; i<argc; i++) {
+ Check_Type(argv[i], T_STRING);
+ args[i] = RSTRING(argv[i])->ptr;
+ }
+ args[i] = 0;
+ if (args[0]) {
+ return proc_exec_v(args);
+ }
+ return -1;
+}
+
int
rb_proc_exec(str)
char *str;
@@ -159,7 +252,13 @@ rb_proc_exec(str)
for (s=str; *s; s++) {
if (*s != ' ' && !isalpha(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
+ before_exec();
+#if defined(MSDOS)
+ system(str);
+#else
execl("/bin/sh", "sh", "-c", str, (char *)NULL);
+#endif
+ after_exec();
return -1;
}
}
@@ -173,19 +272,25 @@ rb_proc_exec(str)
*a = NULL;
}
if (argv[0]) {
- execvp(argv[0], argv);
+ return proc_exec_v(argv);
}
+ errno = ENOENT;
return -1;
}
static VALUE
-f_exec(obj, str)
- VALUE obj;
- struct RString *str;
+f_exec(argc, argv)
+ int argc;
+ VALUE *argv;
{
- Check_Type(str, T_STRING);
- rb_proc_exec(str->ptr);
- rb_sys_fail(str->ptr);
+ if (argc == 1) {
+ Check_Type(argv[0], T_STRING);
+ rb_proc_exec(RSTRING(argv[0])->ptr);
+ }
+ else {
+ proc_exec_n(argc, argv);
+ }
+ rb_sys_fail(RSTRING(argv[0])->ptr);
}
static VALUE
@@ -224,7 +329,6 @@ f_exit_bang(obj, status)
_exit(code);
/* not reached */
- return Qnil;
}
void
@@ -232,12 +336,13 @@ rb_syswait(pid)
int pid;
{
RETSIGTYPE (*hfunc)(), (*ifunc)(), (*qfunc)();
+ int status;
hfunc = signal(SIGHUP, SIG_IGN);
ifunc = signal(SIGINT, SIG_IGN);
qfunc = signal(SIGQUIT, SIG_IGN);
- if (rb_waitpid(pid, 0) < 0) rb_sys_fail("wait");
+ if (rb_waitpid(pid, 0, &status) < 0) rb_sys_fail("wait");
signal(SIGHUP, hfunc);
signal(SIGINT, ifunc);
@@ -245,33 +350,58 @@ rb_syswait(pid)
}
static VALUE
-f_system(obj, str)
- VALUE obj;
- struct RString *str;
+f_system(argc, argv)
+ int argc;
+ VALUE *argv;
{
#ifdef NT
+ VALUE cmd;
+ int state;
+
+ cmd = ary_join(ary_new4(argc, argv), str_new2(" "));
+
+ state = do_spawn(RSTRING(cmd)->ptr);
+ last_status = INT2FIX(state);
+
+ if (state == 0) return TRUE;
+ return FALSE;
+#else
+#if defined(DJGPP)
+ VALUE cmd;
int state;
- Check_Type(str, T_STRING);
- state = do_spawn(str->ptr);
- status = INT2FIX(state);
+ cmd = ary_join(ary_new4(argc, argv), str_new2(" "));
+
+ state = system(RSTRING(cmd)->ptr);
+ last_status = INT2FIX(state);
if (state == 0) return TRUE;
return FALSE;
#else
+ int i;
int pid;
- Check_Type(str, T_STRING);
-
fflush(stdin); /* is it really needed? */
fflush(stdout);
fflush(stderr);
- if (*str->ptr == '\0') return INT2FIX(0);
+ if (argc == 0) {
+ last_status = INT2FIX(0);
+ return INT2FIX(0);
+ }
+
+ for (i=0; i<argc; i++) {
+ Check_Type(argv[i], T_STRING);
+ }
retry:
switch (pid = vfork()) {
case 0:
- rb_proc_exec(str->ptr);
+ if (argc == 1) {
+ rb_proc_exec(RSTRING(argv[0])->ptr);
+ }
+ else {
+ proc_exec_n(argc, argv);
+ }
_exit(127);
break; /* not reached */
@@ -280,62 +410,99 @@ f_system(obj, str)
sleep(5);
goto retry;
}
- rb_sys_fail(str->ptr);
+ rb_sys_fail(0);
break;
default:
rb_syswait(pid);
}
- if (status == INT2FIX(0)) return TRUE;
+ if (last_status == INT2FIX(0)) return TRUE;
return FALSE;
#endif
+#endif
}
+struct timeval time_timeval();
+
VALUE
f_sleep(argc, argv)
int argc;
VALUE *argv;
{
int beg, end;
+ int n;
beg = time(0);
+#ifdef THREAD
if (argc == 0) {
+ thread_sleep();
+ }
+ else if (argc == 1) {
+ thread_wait_for(time_timeval(argv[0]));
+ }
+#else
+ if (argc == 0) {
+ TRAP_BEG;
sleep((32767<<16)+32767);
+ TRAP_END;
}
else if (argc == 1) {
+ struct timeval tv;
+
+ tv = time_timeval(argv[0]);
TRAP_BEG;
- sleep(NUM2INT(argv[0]));
+ sleep(tv.tv_sec);
TRAP_END;
+ if (n<0) rb_sys_fail(0);
}
+#endif
else {
- Fail("wrong # of arguments");
+ ArgError("wrong # of arguments");
}
end = time(0) - beg;
- return int2inum(end);
+ return INT2FIX(end);
}
-#ifndef NT
+#if !defined(NT) && !defined(DJGPP)
+#ifdef _POSIX_SOURCE
+static VALUE
+proc_getpgrp()
+{
+ int pgrp;
+
+ pgrp = getpgrp();
+ if (pgrp < 0) rb_sys_fail(0);
+ return INT2FIX(pgrp);
+}
+
+static VALUE
+proc_setpgrp(obj)
+ VALUE obj;
+{
+ int pgrp;
+
+ if (setpgrp() < 0) rb_sys_fail(0);
+ return Qnil;
+}
+
+#else
+
static VALUE
-proc_getpgrp(argc, argv, obj)
+proc_getpgrp(argc, argv)
int argc;
VALUE *argv;
- VALUE obj;
{
VALUE vpid;
- int pid, pgrp;
+ int pgrp, pid;
rb_scan_args(argc, argv, "01", &vpid);
- if (vpid == Qnil) {
- pid = 0;
- }
- else {
- pid = NUM2INT(vpid);
- }
-
+ if (NIL_P(vpid)) pid = 0;
+ else pid = NUM2INT(vpid);
pgrp = getpgrp(pid);
+ if (pgrp < 0) rb_sys_fail(0);
return INT2FIX(pgrp);
}
@@ -347,11 +514,25 @@ proc_setpgrp(obj, pid, pgrp)
ipid = NUM2INT(pid);
ipgrp = NUM2INT(pgrp);
+ if (setpgrp(ipid, ipgrp) < 0) rb_sys_fail(0);
+ return Qnil;
+}
+#endif
- if (getpgrp(ipid, ipgrp) == -1) rb_sys_fail(Qnil);
+#ifdef HAVE_SETPGID
+static VALUE
+proc_setpgid(obj, pid, pgrp)
+ VALUE obj, pid, pgrp;
+{
+ int ipid, ipgrp;
- return INT2FIX(0);
+ ipid = NUM2INT(pid);
+ ipgrp = NUM2INT(pgrp);
+
+ if (setpgid(ipid, ipgrp) == -1) rb_sys_fail(0);
+ return Qnil;
}
+#endif
static VALUE
proc_getpriority(obj, which, who)
@@ -364,10 +545,10 @@ proc_getpriority(obj, which, who)
iwho = NUM2INT(who);
prio = getpriority(iwhich, iwho);
- if (prio == -1) rb_sys_fail(Qnil);
+ if (prio == -1) rb_sys_fail(0);
return INT2FIX(prio);
#else
- Fail("The getpriority() function is unimplemented on this machine");
+ rb_notimplement();
#endif
}
@@ -383,10 +564,10 @@ proc_setpriority(obj, which, who, prio)
iprio = NUM2INT(prio);
if (setpriority(iwhich, iwho, iprio) == -1)
- rb_sys_fail(Qnil);
+ rb_sys_fail(0);
return INT2FIX(0);
#else
- Fail("The setpriority() function is unimplemented on this machine");
+ rb_notimplement();
#endif
}
#endif
@@ -416,7 +597,7 @@ proc_setuid(obj, id)
if (geteuid() == uid)
setuid(uid);
else
- Fail("getruid not implemented");
+ rb_notimplement();
}
#endif
#endif
@@ -448,7 +629,7 @@ proc_setgid(obj, id)
if (getegid() == gid)
setgid(gid);
else
- Fail("getrgid not implemented");
+ rb_notimplement();
}
#endif
#endif
@@ -468,16 +649,16 @@ proc_seteuid(obj, euid)
VALUE obj, euid;
{
#ifdef HAVE_SETEUID
- if (seteuid(NUM2INT(euid)) == -1) rb_sys_fail(Qnil);
+ if (seteuid(NUM2INT(euid)) == -1) rb_sys_fail(0);
#else
#ifdef HAVE_SETREUID
- if (setreuid(-1, NUM2INT(euid)) == -1) rb_sys_fail(Qnil);
+ if (setreuid(-1, NUM2INT(euid)) == -1) rb_sys_fail(0);
#else
euid = NUM2INT(euid);
if (euid == getuid())
setuid(euid);
else
- Fail("seteuid() not implemented");
+ rb_notimplement();
#endif
#endif
return euid;
@@ -496,16 +677,16 @@ proc_setegid(obj, egid)
VALUE obj, egid;
{
#ifdef HAVE_SETEGID
- if (setegid(NUM2INT(egid)) == -1) rb_sys_fail(Qnil);
+ if (setegid(NUM2INT(egid)) == -1) rb_sys_fail(0);
#else
#ifdef HAVE_SETREGID
- if (setregid(-1, NUM2INT(egid)) == -1) rb_sys_fail(Qnil);
+ if (setregid(-1, NUM2INT(egid)) == -1) rb_sys_fail(0);
#else
egid = NUM2INT(egid);
if (egid == getgid())
setgid(egid);
else
- Fail("setegid() not implemented");
+ rb_notimplement();
#endif
#endif
return egid;
@@ -520,41 +701,60 @@ Init_process()
{
extern VALUE cKernel;
- rb_define_virtual_variable("$$", get_pid, Qnil);
- rb_define_readonly_variable("$?", &status);
+ rb_define_virtual_variable("$$", get_pid, 0);
+ rb_define_readonly_variable("$?", &last_status);
#ifndef NT
- rb_define_private_method(cKernel, "exec", f_exec, 1);
+ rb_define_private_method(cKernel, "exec", f_exec, -1);
rb_define_private_method(cKernel, "fork", f_fork, 0);
rb_define_private_method(cKernel, "exit!", f_exit_bang, 1);
- rb_define_private_method(cKernel, "wait", f_wait, 0);
- rb_define_private_method(cKernel, "waitpid", f_waitpid, 2);
-#endif
- rb_define_private_method(cKernel, "system", f_system, 1);
+ rb_define_private_method(cKernel, "system", f_system, -1);
rb_define_private_method(cKernel, "sleep", f_sleep, -1);
mProcess = rb_define_module("Process");
+#ifdef WNOHANG
+ rb_define_const(mProcess, "WNOHANG", INT2FIX(WNOHANG));
+#else
+ rb_define_const(mProcess, "WNOHANG", INT2FIX(0));
+#endif
+#ifdef WUNTRACED
+ rb_define_const(mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
+#else
+ rb_define_const(mProcess, "WUNTRACED", INT2FIX(0));
+#endif
+#endif
+
#ifndef NT
rb_define_singleton_method(mProcess, "fork", f_fork, 0);
rb_define_singleton_method(mProcess, "exit!", f_exit_bang, 1);
- rb_define_singleton_method(mProcess, "wait", f_wait, 0);
- rb_define_singleton_method(mProcess, "waitpid", f_waitpid, 2);
- rb_define_singleton_method(mProcess, "kill", f_kill, -1);
#endif
+ rb_define_module_function(mProcess, "kill", f_kill, -1);
+ rb_define_module_function(mProcess, "wait", f_wait, 0);
+ rb_define_module_function(mProcess, "waitpid", f_waitpid, 2);
rb_define_module_function(mProcess, "pid", get_pid, 0);
rb_define_module_function(mProcess, "ppid", get_ppid, 0);
-#ifndef NT
+#if !defined(NT) && !defined(DJGPP)
+#ifdef _POSIX_SOURCE
+ rb_define_module_function(mProcess, "getpgrp", proc_getpgrp, 0);
+ rb_define_module_function(mProcess, "setpgrp", proc_setpgrp, 0);
+#else
rb_define_module_function(mProcess, "getpgrp", proc_getpgrp, -1);
rb_define_module_function(mProcess, "setpgrp", proc_setpgrp, 2);
+#endif
+#ifdef HAVE_SETPGID
+ rb_define_module_function(mProcess, "setpgid", proc_setpgid, 2);
+#endif
+#ifdef HAVE_GETPRIORITY
rb_define_module_function(mProcess, "getpriority", proc_getpriority, 2);
rb_define_module_function(mProcess, "setpriority", proc_setpriority, 3);
rb_define_const(mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
rb_define_const(mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
rb_define_const(mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
+#endif
rb_define_module_function(mProcess, "uid", proc_getuid, 0);
rb_define_module_function(mProcess, "uid=", proc_setuid, 1);