diff options
Diffstat (limited to 'process.c')
-rw-r--r-- | process.c | 386 |
1 files changed, 293 insertions, 93 deletions
@@ -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); |