40 #define EXIT_SUCCESS 0
43 #define EXIT_FAILURE 1
46 #ifdef HAVE_SYS_WAIT_H
47 # include <sys/wait.h>
49 #ifdef HAVE_SYS_RESOURCE_H
50 # include <sys/resource.h>
52 #ifdef HAVE_SYS_PARAM_H
53 # include <sys/param.h>
56 # define MAXPATHLEN 1024
66 #ifdef HAVE_SYS_TIMES_H
67 #include <sys/times.h>
74 #if defined(HAVE_TIMES) || defined(_WIN32)
75 static VALUE rb_cProcessTms;
79 #define WIFEXITED(w) (((w) & 0xff) == 0)
82 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
85 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
88 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
91 #define WTERMSIG(w) ((w) & 0x7f)
94 #define WSTOPSIG WEXITSTATUS
97 #if defined(__APPLE__) && ( defined(__MACH__) || defined(__DARWIN__) ) && !defined(__MacOS_X__)
101 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
102 #define HAVE_44BSD_SETUID 1
103 #define HAVE_44BSD_SETGID 1
111 #ifdef BROKEN_SETREUID
112 #define setreuid ruby_setreuid
113 int setreuid(rb_uid_t ruid, rb_uid_t euid);
115 #ifdef BROKEN_SETREGID
116 #define setregid ruby_setregid
117 int setregid(rb_gid_t rgid, rb_gid_t egid);
120 #if defined(HAVE_44BSD_SETUID) || defined(__MacOS_X__)
121 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
122 #define OBSOLETE_SETREUID 1
124 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
125 #define OBSOLETE_SETREGID 1
129 #define preserving_errno(stmts) \
130 do {int saved_errno = errno; stmts; errno = saved_errno;} while (0)
247 #define PST2INT(st) NUM2INT(pst_to_i(st))
274 rb_str_catf(str,
" stopped SIG%s (signal %d)", signame, stopsig);
284 rb_str_catf(str,
" SIG%s (signal %d)", signame, termsig);
294 if (WCOREDUMP(status)) {
371 if (st1 == st2)
return Qtrue;
582 if (WCOREDUMP(status))
591 #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
630 struct waitpid_arg *
arg = data;
633 #if defined NO_WAITPID
635 #elif defined HAVE_WAITPID
636 result =
waitpid(arg->pid, arg->st, arg->flags);
638 result = wait4(arg->pid, arg->st, arg->flags,
NULL);
649 struct waitpid_arg arg;
658 if (
errno == EINTR) {
667 if (pid == (rb_pid_t)-1) {
669 data.
pid = (rb_pid_t)-1;
672 if (data.status != -1) {
677 else if (
st_delete(pid_tbl, &piddata, &status)) {
691 if (
errno == EINTR) {
697 if (result == pid || pid == (rb_pid_t)-1) {
786 if (argc == 2 && !
NIL_P(vflags)) {
790 if ((pid =
rb_waitpid(pid, &status, flags)) < 0)
873 if (
errno == EINTR) {
908 while ((cpid =
rb_waitpid(pid, &status, 0)) == 0) {
978 #ifndef HAVE_STRING_H
985 static RETSIGTYPE (*saved_sigpipe_handler)(int) = 0;
988 #if defined(POSIX_SIGNAL)
989 # define signal(a,b) posix_signal((a),(b))
993 static RETSIGTYPE sig_do_nothing(
int sig)
1013 saved_sigpipe_handler =
signal(SIGPIPE, sig_do_nothing);
1032 signal(SIGPIPE, saved_sigpipe_handler);
1039 #define before_fork() before_exec()
1040 #define after_fork() (GET_THREAD()->thrown_errinfo = 0, after_exec())
1055 #define try_with_sh(prog, argv) ((saved_errno == ENOEXEC) ? exec_with_sh((prog), (argv)) : (void)0)
1057 exec_with_sh(
const char *prog,
char **
argv)
1059 *argv = (
char *)prog;
1060 *--argv = (
char *)
"sh";
1061 execv(
"/bin/sh", argv);
1063 #define ARGV_COUNT(n) ((n)+1)
1065 #define try_with_sh(prog, argv) (void)0
1066 #define ARGV_COUNT(n) (n)
1068 #define ARGV_SIZE(n) (sizeof(char*) * ARGV_COUNT(n))
1069 #define ALLOC_ARGV(n, v) ALLOCV_N(char*, (v), ARGV_COUNT(n))
1070 #define ALLOC_ARGV_WITH_STR(n, v, s, l) \
1071 (char **)(((s) = ALLOCV_N(char, (v), ARGV_SIZE(n) + (l)) + ARGV_SIZE(n)) - ARGV_SIZE(n))
1077 #if defined(__EMX__) || defined(OS2)
1078 char **new_argv =
NULL;
1089 #if defined(__EMX__) || defined(OS2)
1091 #define COMMAND "cmd.exe"
1098 for (n = 0; argv[n]; n++)
1100 new_argv =
ALLOC_N(
char*, n + 2);
1102 new_argv[n + 1] = argv[n];
1103 new_argv[1] = strcpy(
ALLOC_N(
char,
strlen(argv[0]) + 1), argv[0]);
1104 for (p = new_argv[1]; *p !=
'\0'; p++)
1107 new_argv[0] = COMMAND;
1120 #if defined(__EMX__) || defined(OS2)
1138 for (i=0; i<
argc; i++) {
1153 const char *s = str;
1169 for (s=str; *s; s++) {
1171 const char *
p, *nl =
NULL;
1172 for (p = s;
ISSPACE(*p); p++) {
1173 if (*p ==
'\n') nl =
p;
1178 if (*s !=
' ' && !
ISALPHA(*s) &&
strchr(
"*?{}[]<>()~&|\\$;'`\"\n",*s)) {
1179 #if defined(__CYGWIN32__) || defined(__EMX__)
1185 execl(shell,
"sh",
"-c", str, (
char *)
NULL);
1187 status = system(str);
1193 execl(
"/bin/sh",
"sh",
"-c", str, (
char *)
NULL);
1200 memcpy(ss, str, s-str);
1202 if ((*a++ =
strtok(ss,
" \t")) != 0) {
1235 #define HAVE_SPAWNV 1
1238 #if !defined(HAVE_FORK) && defined(HAVE_SPAWNV)
1239 # define USE_SPAWNV 1
1241 # define USE_SPAWNV 0
1244 # define P_NOWAIT _P_NOWAIT
1249 #define proc_spawn_v(argv, prog) rb_w32_aspawn(P_NOWAIT, (prog), (argv))
1252 proc_spawn_v(
char **
argv,
char *prog)
1265 status = spawnv(
P_NOWAIT, prog, (
const char **)argv);
1266 if (status == -1 &&
errno == ENOEXEC) {
1267 *argv = (
char *)prog;
1268 *--argv = (
char *)
"sh";
1269 status = spawnv(
P_NOWAIT,
"/bin/sh", (
const char **)argv);
1271 if (status == -1)
errno = ENOEXEC;
1287 for (i = 0; i <
argc; i++) {
1290 args[
i] = (
char*) 0;
1295 flags = CREATE_NEW_PROCESS_GROUP;
1299 pid = proc_spawn_v(args, prog ?
RSTRING_PTR(prog) : 0);
1307 #define proc_spawn(str) rb_w32_spawn(P_NOWAIT, (str), 0)
1310 proc_spawn(
char *str)
1318 for (s = str; *s; s++) {
1319 if (*s !=
' ' && !
ISALPHA(*s) &&
strchr(
"*?{}[]<>()~&|\\$;'`\"\n",*s)) {
1322 status = spawnl(
P_NOWAIT, (shell ? shell :
"/bin/sh"),
"sh",
"-c", str, (
char*)NULL);
1330 if (*a++ =
strtok(s,
" \t")) {
1331 while (t =
strtok(NULL,
" \t"))
1335 status = argv[0] ? proc_spawn_v(argv, 0) : -1;
1383 else if (fd >= 3 && iskey) {
1395 VALUE path, flags, perm;
1398 switch (
TYPE(val)) {
1462 flags =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
1494 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1495 static int rlimit_type_by_lname(
const char *
name);
1503 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1509 switch (
TYPE(key)) {
1519 else if (val ==
Qtrue)
1542 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1543 if (strncmp(
"rlimit_",
rb_id2name(
id), 7) == 0 &&
1544 (rtype = rlimit_type_by_lname(
rb_id2name(
id)+7)) != -1) {
1546 VALUE tmp, softlim, hardlim;
1571 if (
id ==
rb_intern(
"unsetenv_others")) {
1593 else if (
id ==
rb_intern(
"close_others")) {
1646 int index, maxhint = -1;
1693 if (oldfd != lastfd) {
1756 const char *
name = 0;
1775 for (i = 0; i <
argc; i++) {
1792 *opthash_ret =
hash;
1807 prog = (*argv_p)[0];
1808 if (accept_shell && *argc_p == 1) {
1824 if (!
NIL_P(opthash)) {
1842 prog =
rb_exec_getargs(&argc, &argv, accept_shell, &env, &opthash, e);
1901 #define CHILD_ERRMSG_BUFLEN 80
1916 #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
1919 #if defined(DEBUG_REDIRECT)
1924 ttyprintf(
const char *fmt, ...)
1930 tty = fopen(
"con",
"w");
1932 tty = fopen(
"/dev/tty",
"w");
1938 vfprintf(tty, fmt, ap);
1949 ttyprintf(
"dup(%d) => %d\n", oldfd, ret);
1957 ret =
dup2(oldfd, newfd);
1958 ttyprintf(
"dup2(%d, %d)\n", oldfd, newfd);
1967 ttyprintf(
"close(%d)\n", fd);
1975 ret = open(pathname, flags, perm);
1976 ttyprintf(
"open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
1981 #define redirect_dup(oldfd) dup(oldfd)
1982 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
1983 #define redirect_close(fd) close(fd)
1984 #define redirect_open(pathname, flags, perm) open((pathname), (flags), (perm))
1993 if (save_fd == -1) {
2001 if (
NIL_P(newary)) {
2009 if (
NIL_P(newary)) {
2044 return *(
int*)a - *(
int*)b;
2050 return *(
int*)b - *(
int*)a;
2067 pairs = (
struct fd_pair *)
malloc(
sizeof(
struct fd_pair) * n);
2068 if (pairs ==
NULL) {
2074 for (i = 0; i < n; i++) {
2078 pairs[
i].older_index = -1;
2083 qsort(pairs, n,
sizeof(
struct fd_pair),
intcmp);
2085 qsort(pairs, n,
sizeof(
struct fd_pair),
intrcmp);
2088 for (i = 0; i < n; i++) {
2089 int newfd = pairs[
i].newfd;
2090 struct fd_pair key, *found;
2092 found = bsearch(&key, pairs, n,
sizeof(
struct fd_pair),
intcmp);
2093 pairs[
i].num_newer = 0;
2095 while (pairs < found && (found-1)->oldfd == newfd)
2097 while (found < pairs+n && found->oldfd == newfd) {
2098 pairs[
i].num_newer++;
2099 found->older_index =
i;
2106 for (i = 0; i < n; i++) {
2108 while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
2117 pairs[j].oldfd = -1;
2118 j = pairs[j].older_index;
2120 pairs[j].num_newer--;
2125 for (i = 0; i < n; i++) {
2127 if (pairs[i].oldfd == -1)
2129 if (pairs[i].oldfd == pairs[i].newfd) {
2131 int fd = pairs[
i].oldfd;
2132 ret =
fcntl(fd, F_GETFD);
2134 ERRMSG(
"fcntl(F_GETFD)");
2137 if (ret & FD_CLOEXEC) {
2139 ret =
fcntl(fd, F_SETFD, ret);
2141 ERRMSG(
"fcntl(F_SETFD)");
2146 pairs[
i].oldfd = -1;
2149 if (extra_fd == -1) {
2151 if (extra_fd == -1) {
2165 pairs[
i].oldfd = extra_fd;
2166 j = pairs[
i].older_index;
2167 pairs[
i].older_index = -1;
2175 pairs[j].oldfd = -1;
2176 j = pairs[j].older_index;
2179 if (extra_fd != -1) {
2287 run_exec_pgroup(
VALUE obj,
VALUE save,
char *errmsg,
size_t errmsg_buflen)
2305 ret = setpgid(getpid(), pgroup);
2306 if (ret == -1)
ERRMSG(
"setpgid");
2311 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2313 run_exec_rlimit(
VALUE ary,
VALUE save,
char *errmsg,
size_t errmsg_buflen)
2327 RLIM2NUM(rlim.rlim_cur),
2328 RLIM2NUM(rlim.rlim_max)));
2330 if (
NIL_P(newary)) {
2336 rlim.rlim_cur = NUM2RLIM(
RARRAY_PTR(elt)[1]);
2337 rlim.rlim_max = NUM2RLIM(
RARRAY_PTR(elt)[2]);
2354 if (!
RTEST(options))
2368 if (run_exec_pgroup(obj, soptions, errmsg, errmsg_buflen) == -1)
2373 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2376 if (run_exec_rlimit(obj, soptions, errmsg, errmsg_buflen) == -1)
2404 if (!
NIL_P(soptions)) {
2419 mode_t oldmask = umask(mask);
2420 if (!
NIL_P(soptions))
2426 if (
run_exec_dup2(obj, soptions, errmsg, errmsg_buflen) == -1)
2432 if (!
NIL_P(soptions))
2433 rb_warn(
"cannot close fd before spawn");
2449 if (
run_exec_open(obj, soptions, errmsg, errmsg_buflen) == -1)
2473 const char *prog = e->
prog;
2491 #if !defined FD_CLOEXEC && !defined HAVE_SPAWNV
2492 char errmsg[80] = {
'\0' };
2496 fprintf(stderr,
"%s\n", errmsg);
2499 fprintf(stderr,
"%s:%d: command not found: %s\n",
2511 rb_exec_atfork(
void*
arg,
char *errmsg,
size_t errmsg_buflen)
2520 #if SIZEOF_INT == SIZEOF_LONG
2521 #define proc_syswait (VALUE (*)(VALUE))rb_syswait
2524 proc_syswait(
VALUE pid)
2533 move_fds_to_avoid_crash(
int *fdp,
int n,
VALUE fds)
2537 for (i = 0; i < n; i++) {
2544 ret =
fcntl(fdp[i], F_DUPFD, min);
2556 pipe_nocrash(
int filedes[2],
VALUE fds)
2564 if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
2574 struct chfunc_protect_t {
2575 int (*
chfunc)(
void*,
char *, size_t);
2584 struct chfunc_protect_t *
p = (
struct chfunc_protect_t *)arg;
2586 return (
VALUE)(*p->chfunc)(p->arg, p->errmsg, p->buflen);
2618 char *errmsg,
size_t errmsg_buflen)
2627 #define prefork() ( \
2628 rb_io_flush(rb_stdout), \
2629 rb_io_flush(rb_stderr) \
2635 if (pipe_nocrash(ep, fds))
return -1;
2636 if (
fcntl(ep[1], F_SETFD, FD_CLOEXEC)) {
2642 for (;
before_fork(), (pid = fork()) < 0; prefork()) {
2646 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
2649 if (!status && !
chfunc) {
2655 if (status) *status =
state;
2656 if (!state)
continue;
2671 struct chfunc_protect_t arg;
2674 arg.errmsg = errmsg;
2675 arg.buflen = errmsg_buflen;
2681 if (write(ep[1], &state,
sizeof(state)) ==
sizeof(state) && state) {
2688 if (write(ep[1], &err,
sizeof(err)) < 0) err =
errno;
2689 if (errmsg && 0 < errmsg_buflen) {
2690 errmsg[errmsg_buflen-1] =
'\0';
2691 errmsg_buflen =
strlen(errmsg);
2692 if (errmsg_buflen > 0 &&write(ep[1], errmsg, errmsg_buflen) < 0)
2697 #if EXIT_SUCCESS == 127
2710 if ((read(ep[0], &state,
sizeof(state))) ==
sizeof(state) && state) {
2715 #define READ_FROM_CHILD(ptr, len) \
2716 (NIL_P(io) ? read(ep[0], (ptr), (len)) : rb_io_bufread(io, (ptr), (len)))
2717 if ((size = READ_FROM_CHILD(&err,
sizeof(err))) < 0) {
2720 if (size ==
sizeof(err) &&
2721 errmsg && 0 < errmsg_buflen) {
2722 ssize_t ret = READ_FROM_CHILD(errmsg, errmsg_buflen-1);
2731 if (state || size) {
2748 struct chfunc_wrapper_t {
2754 chfunc_wrapper(
void *arg_,
char *errmsg,
size_t errmsg_buflen)
2756 struct chfunc_wrapper_t *arg = arg_;
2757 return arg->chfunc(arg->arg);
2764 struct chfunc_wrapper_t warg;
2767 return rb_fork_err(status, chfunc_wrapper, &warg, fds, NULL, 0);
2770 return rb_fork_err(status, NULL, NULL, fds, NULL, 0);
2777 #if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
2828 #define rb_f_fork rb_f_notimplement
2849 if (argc > 0 &&
rb_scan_args(argc, argv,
"01", &status) == 1) {
2933 if (argc > 0 &&
rb_scan_args(argc, argv,
"01", &status) == 1) {
2943 #if EXIT_SUCCESS != 0
2994 static int overriding;
2996 RETSIGTYPE (*hfunc)(int) = 0;
2999 RETSIGTYPE (*qfunc)(int) = 0;
3001 RETSIGTYPE (*ifunc)(int) = 0;
3007 hfunc =
signal(SIGHUP, SIG_IGN);
3010 qfunc =
signal(SIGQUIT, SIG_IGN);
3019 }
while (i == -1 &&
errno == EINTR);
3052 #if !defined HAVE_FORK || USE_SPAWNV
3058 #if defined HAVE_FORK && !USE_SPAWNV
3067 if (prog && argc) argv[0] =
prog;
3068 # if defined HAVE_SPAWNV
3073 pid = proc_spawn_n(argc, argv, prog, earg->
options);
3075 # if defined(_WIN32)
3092 char *errmsg,
size_t errmsg_buflen)
3150 #if defined(SIGCLD) && !defined(SIGCHLD)
3151 # define SIGCHLD SIGCLD
3155 RETSIGTYPE (*
chfunc)(int);
3160 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3432 const char *prog = errmsg;
3433 if (!prog[0] && !(prog = earg.
prog) && earg.
argc) {
3438 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3471 else if (argc == 1) {
3478 end = time(0) - beg;
3484 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
3502 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
3513 #define proc_getpgrp rb_f_notimplement
3517 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
3536 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
3542 #define proc_setpgrp rb_f_notimplement
3546 #if defined(HAVE_GETPGID)
3568 #define proc_getpgid rb_f_notimplement
3584 rb_pid_t ipid, ipgrp;
3594 #define proc_setpgid rb_f_notimplement
3598 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
3599 #if !defined(HAVE_SETSID)
3600 static rb_pid_t ruby_setsid(
void);
3601 #define setsid() ruby_setsid()
3625 #if !defined(HAVE_SETSID)
3626 #define HAVE_SETSID 1
3634 #if defined(SETPGRP_VOID)
3640 ret = setpgrp(0, pid);
3642 if (ret == -1)
return -1;
3644 if ((fd = open(
"/dev/tty", O_RDWR)) >= 0) {
3646 ioctl(fd, TIOCNOTTY, NULL);
3653 #define proc_setsid rb_f_notimplement
3657 #ifdef HAVE_GETPRIORITY
3678 int prio, iwhich, iwho;
3685 prio = getpriority(iwhich, iwho);
3690 #define proc_getpriority rb_f_notimplement
3694 #ifdef HAVE_GETPRIORITY
3710 int iwhich, iwho, iprio;
3717 if (setpriority(iwhich, iwho, iprio) < 0)
3722 #define proc_setpriority rb_f_notimplement
3725 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
3727 rlimit_resource_name2int(
const char *
name,
int casetype)
3731 #define RESCHECK(r) \
3733 if (STRCASECMP(name, #r) == 0) { \
3734 resource = RLIMIT_##r; \
3768 #ifdef RLIMIT_MEMLOCK
3771 #ifdef RLIMIT_MSGQUEUE
3777 #ifdef RLIMIT_NOFILE
3792 #ifdef RLIMIT_RTPRIO
3795 #ifdef RLIMIT_RTTIME
3804 #ifdef RLIMIT_SBSIZE
3807 #ifdef RLIMIT_SIGPENDING
3808 RESCHECK(SIGPENDING);
3817 for (p = name; *
p; p++)
3823 for (p = name; *
p; p++)
3829 rb_bug(
"unexpected casetype");
3836 rlimit_type_by_hname(
const char *
name)
3838 return rlimit_resource_name2int(name, 0);
3842 rlimit_type_by_lname(
const char *
name)
3844 return rlimit_resource_name2int(name, 1);
3848 rlimit_resource_type(
VALUE rtype)
3854 switch (
TYPE(rtype)) {
3874 r = rlimit_type_by_hname(name);
3882 rlimit_resource_value(
VALUE rval)
3887 switch (
TYPE(rval)) {
3904 return NUM2RLIM(rval);
3907 #ifdef RLIM_INFINITY
3908 if (strcmp(name,
"INFINITY") == 0)
return RLIM_INFINITY;
3910 #ifdef RLIM_SAVED_MAX
3911 if (strcmp(name,
"SAVED_MAX") == 0)
return RLIM_SAVED_MAX;
3913 #ifdef RLIM_SAVED_CUR
3914 if (strcmp(name,
"SAVED_CUR") == 0)
return RLIM_SAVED_CUR;
3920 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
3948 if (
getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
3951 return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
3954 #define proc_getrlimit rb_f_notimplement
3957 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
4012 VALUE resource, rlim_cur, rlim_max;
4017 rb_scan_args(argc, argv,
"21", &resource, &rlim_cur, &rlim_max);
4018 if (rlim_max ==
Qnil)
4019 rlim_max = rlim_cur;
4021 rlim.rlim_cur = rlimit_resource_value(rlim_cur);
4022 rlim.rlim_max = rlimit_resource_value(rlim_max);
4024 if (
setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4030 #define proc_setrlimit rb_f_notimplement
4038 if (under_uid_switch) {
4048 if (under_gid_switch) {
4065 #if defined HAVE_SETUID
4083 #define p_sys_setuid rb_f_notimplement
4087 #if defined HAVE_SETRUID
4105 #define p_sys_setruid rb_f_notimplement
4109 #if defined HAVE_SETEUID
4127 #define p_sys_seteuid rb_f_notimplement
4131 #if defined HAVE_SETREUID
4151 #define p_sys_setreuid rb_f_notimplement
4155 #if defined HAVE_SETRESUID
4175 #define p_sys_setresuid rb_f_notimplement
4198 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
4215 #if defined(HAVE_SETRESUID)
4217 #elif defined HAVE_SETREUID
4219 #elif defined HAVE_SETRUID
4221 #elif defined HAVE_SETUID
4234 #define proc_setuid rb_f_notimplement
4250 #ifdef BROKEN_SETREUID
4252 setreuid(rb_uid_t ruid, rb_uid_t euid)
4254 if (ruid != (rb_uid_t)-1 && ruid !=
getuid()) {
4255 if (euid == (rb_uid_t)-1) euid =
geteuid();
4256 if (
setuid(ruid) < 0)
return -1;
4258 if (euid != (rb_uid_t)-1 && euid !=
geteuid()) {
4259 if (seteuid(euid) < 0)
return -1;
4288 #if defined(HAVE_SETRESUID)
4290 SAVED_USER_ID = uid;
4291 #elif defined(HAVE_SETUID)
4293 SAVED_USER_ID = uid;
4294 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
4296 if (SAVED_USER_ID == uid) {
4300 if (setreuid(-1, SAVED_USER_ID) < 0)
rb_sys_fail(0);
4301 if (setreuid(SAVED_USER_ID, 0) < 0)
rb_sys_fail(0);
4304 SAVED_USER_ID = uid;
4309 SAVED_USER_ID = uid;
4314 SAVED_USER_ID = uid;
4316 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
4318 if (SAVED_USER_ID == uid) {
4330 SAVED_USER_ID = uid;
4336 SAVED_USER_ID = uid;
4342 #if defined(HAVE_SETRESUID)
4343 if (setresuid((
getuid() == uid)? (rb_uid_t)-1: uid,
4344 (
geteuid() == uid)? (rb_uid_t)-1: uid,
4345 (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0)
rb_sys_fail(0);
4346 SAVED_USER_ID = uid;
4347 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
4348 if (SAVED_USER_ID == uid) {
4349 if (setreuid((
getuid() == uid)? (rb_uid_t)-1: uid,
4350 (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
4352 }
else if (
getuid() != uid) {
4353 if (setreuid(uid, (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
4355 SAVED_USER_ID = uid;
4356 }
else if (
geteuid() != uid) {
4358 SAVED_USER_ID = uid;
4361 if (setreuid(-1, SAVED_USER_ID) < 0)
rb_sys_fail(0);
4362 if (setreuid(SAVED_USER_ID, uid) < 0)
rb_sys_fail(0);
4363 SAVED_USER_ID = uid;
4366 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
4367 if (SAVED_USER_ID == uid) {
4370 }
else if (
geteuid() == uid) {
4373 SAVED_USER_ID = uid;
4376 SAVED_USER_ID = uid;
4379 }
else if (
getuid() == uid) {
4382 SAVED_USER_ID = uid;
4388 #elif defined HAVE_44BSD_SETUID
4392 SAVED_USER_ID = uid;
4397 #elif defined HAVE_SETEUID
4398 if (
getuid() == uid && SAVED_USER_ID == uid) {
4404 #elif defined HAVE_SETUID
4405 if (
getuid() == uid && SAVED_USER_ID == uid) {
4420 #if defined HAVE_SETGID
4438 #define p_sys_setgid rb_f_notimplement
4442 #if defined HAVE_SETRGID
4460 #define p_sys_setrgid rb_f_notimplement
4464 #if defined HAVE_SETEGID
4482 #define p_sys_setegid rb_f_notimplement
4486 #if defined HAVE_SETREGID
4506 #define p_sys_setregid rb_f_notimplement
4509 #if defined HAVE_SETRESGID
4529 #define p_sys_setresgid rb_f_notimplement
4533 #if defined HAVE_ISSETUGID
4557 #define p_sys_issetugid rb_f_notimplement
4580 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
4596 #if defined(HAVE_SETRESGID)
4598 #elif defined HAVE_SETREGID
4600 #elif defined HAVE_SETRGID
4602 #elif defined HAVE_SETGID
4615 #define proc_setgid rb_f_notimplement
4619 #if defined(HAVE_SETGROUPS) || defined(HAVE_GETGROUPS)
4640 #define RB_MAX_GROUPS (65536)
4641 static int _maxgroups = -1;
4642 static int get_sc_ngroups_max(
void)
4644 #ifdef _SC_NGROUPS_MAX
4645 return (
int)sysconf(_SC_NGROUPS_MAX);
4646 #elif defined(NGROUPS_MAX)
4647 return (
int)NGROUPS_MAX;
4652 static int maxgroups(
void)
4654 if (_maxgroups < 0) {
4655 _maxgroups = get_sc_ngroups_max();
4657 _maxgroups = RB_MAX_GROUPS;
4666 #ifdef HAVE_GETGROUPS
4685 ngroups = getgroups(0, NULL);
4689 groups =
ALLOCA_N(rb_gid_t, ngroups);
4691 ngroups = getgroups(ngroups, groups);
4696 for (i = 0; i < ngroups; i++)
4702 #define proc_getgroups rb_f_notimplement
4706 #ifdef HAVE_SETGROUPS
4725 #ifdef HAVE_GETGRNAM_R
4726 long getgr_buf_len = sysconf(_SC_GETGR_R_SIZE_MAX);
4729 if (getgr_buf_len < 0)
4730 getgr_buf_len = 4096;
4731 getgr_buf =
ALLOCA_N(
char, getgr_buf_len);
4737 if (ngroups > maxgroups())
4740 groups =
ALLOCA_N(rb_gid_t, ngroups);
4742 for (i = 0; i < ngroups; i++) {
4760 #ifdef HAVE_GETGRNAM_R
4761 ret = getgrnam_r(grpname, &grp, getgr_buf, getgr_buf_len, &p);
4765 p = getgrnam(grpname);
4771 groups[
i] = p->gr_gid;
4776 if (setgroups(ngroups, groups) == -1)
4782 #define proc_setgroups rb_f_notimplement
4786 #ifdef HAVE_INITGROUPS
4813 #define proc_initgroups rb_f_notimplement
4816 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
4833 #define proc_getmaxgroups rb_f_notimplement
4836 #ifdef HAVE_SETGROUPS
4849 int ngroups_max = get_sc_ngroups_max();
4854 if (ngroups > RB_MAX_GROUPS)
4855 ngroups = RB_MAX_GROUPS;
4857 if (ngroups_max > 0 && ngroups > ngroups_max)
4858 ngroups = ngroups_max;
4860 _maxgroups = ngroups;
4865 #define proc_setmaxgroups rb_f_notimplement
4868 #if defined(HAVE_DAEMON) || (defined(HAVE_FORK) && defined(HAVE_SETSID))
4869 static int rb_daemon(
int nochdir,
int noclose);
4888 VALUE nochdir, noclose;
4895 n = rb_daemon(
RTEST(nochdir),
RTEST(noclose));
4901 rb_daemon(
int nochdir,
int noclose)
4906 err = daemon(nochdir, noclose);
4935 if (!noclose && (n = open(
"/dev/null", O_RDWR, 0)) != -1) {
4947 #define proc_daemon rb_f_notimplement
4962 #ifdef BROKEN_SETREGID
4964 setregid(rb_gid_t rgid, rb_gid_t egid)
4966 if (rgid != (rb_gid_t)-1 && rgid !=
getgid()) {
4967 if (egid == (rb_gid_t)-1) egid =
getegid();
4968 if (
setgid(rgid) < 0)
return -1;
4970 if (egid != (rb_gid_t)-1 && egid !=
getegid()) {
4971 if (setegid(egid) < 0)
return -1;
5000 #if defined(HAVE_SETRESGID)
5002 SAVED_GROUP_ID = gid;
5003 #elif defined HAVE_SETGID
5005 SAVED_GROUP_ID = gid;
5006 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5008 if (SAVED_GROUP_ID == gid) {
5012 if (setregid(-1, SAVED_GROUP_ID) < 0)
rb_sys_fail(0);
5013 if (setregid(SAVED_GROUP_ID, 0) < 0)
rb_sys_fail(0);
5016 SAVED_GROUP_ID = gid;
5021 SAVED_GROUP_ID = gid;
5026 SAVED_GROUP_ID = gid;
5028 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
5030 if (SAVED_GROUP_ID == gid) {
5043 SAVED_GROUP_ID = gid;
5049 SAVED_GROUP_ID = gid;
5055 #if defined(HAVE_SETRESGID)
5056 if (setresgid((
getgid() == gid)? (rb_gid_t)-1: gid,
5057 (
getegid() == gid)? (rb_gid_t)-1: gid,
5058 (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0)
rb_sys_fail(0);
5059 SAVED_GROUP_ID = gid;
5060 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5061 if (SAVED_GROUP_ID == gid) {
5062 if (setregid((
getgid() == gid)? (rb_uid_t)-1: gid,
5063 (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5065 }
else if (
getgid() != gid) {
5066 if (setregid(gid, (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5068 SAVED_GROUP_ID = gid;
5069 }
else if (
getegid() != gid) {
5071 SAVED_GROUP_ID = gid;
5074 if (setregid(-1, SAVED_GROUP_ID) < 0)
rb_sys_fail(0);
5075 if (setregid(SAVED_GROUP_ID, gid) < 0)
rb_sys_fail(0);
5076 SAVED_GROUP_ID = gid;
5079 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
5080 if (SAVED_GROUP_ID == gid) {
5083 }
else if (
getegid() == gid) {
5086 SAVED_GROUP_ID = gid;
5089 SAVED_GROUP_ID = gid;
5092 }
else if (
getgid() == gid) {
5095 SAVED_GROUP_ID = gid;
5101 #elif defined HAVE_44BSD_SETGID
5105 SAVED_GROUP_ID = gid;
5110 #elif defined HAVE_SETEGID
5111 if (
getgid() == gid && SAVED_GROUP_ID == gid) {
5117 #elif defined HAVE_SETGID
5118 if (
getgid() == gid && SAVED_GROUP_ID == gid) {
5150 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
5167 #if defined(HAVE_SETRESUID)
5169 #elif defined HAVE_SETREUID
5171 #elif defined HAVE_SETEUID
5173 #elif defined HAVE_SETUID
5187 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
5188 #define proc_seteuid_m proc_seteuid
5190 #define proc_seteuid_m rb_f_notimplement
5202 #if defined(HAVE_SETRESUID)
5205 SAVED_USER_ID = euid;
5209 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5214 SAVED_USER_ID = euid;
5216 #elif defined HAVE_SETEUID
5218 #elif defined HAVE_SETUID
5270 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
5287 #if defined(HAVE_SETRESGID)
5289 #elif defined HAVE_SETREGID
5291 #elif defined HAVE_SETEGID
5293 #elif defined HAVE_SETGID
5307 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
5308 #define proc_setegid_m proc_setegid
5310 #define proc_setegid_m rb_f_notimplement
5322 #if defined(HAVE_SETRESGID)
5325 SAVED_GROUP_ID = egid;
5329 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5334 SAVED_GROUP_ID = egid;
5336 #elif defined HAVE_SETEGID
5338 #elif defined HAVE_SETGID
5382 #if defined(HAVE_SETRESUID)
5384 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5414 #if defined(HAVE_SETRESUID)
5415 if (setresuid(euid, uid, uid) < 0)
rb_sys_fail(0);
5416 SAVED_USER_ID = uid;
5417 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5419 SAVED_USER_ID = uid;
5439 #if defined(HAVE_SETRESGID)
5441 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5471 #if defined(HAVE_SETRESGID)
5472 if (setresgid(egid, gid, gid) < 0)
rb_sys_fail(0);
5473 SAVED_GROUP_ID = gid;
5474 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5476 SAVED_GROUP_ID = gid;
5497 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
5505 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
5509 under_uid_switch = 0;
5541 under_uid_switch = 1;
5546 }
else if (euid != SAVED_USER_ID) {
5547 proc_seteuid(obj,
UIDT2NUM(SAVED_USER_ID));
5549 under_uid_switch = 1;
5563 under_uid_switch = 0;
5583 under_uid_switch = 1;
5606 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
5613 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
5617 under_gid_switch = 0;
5649 under_gid_switch = 1;
5655 else if (egid != SAVED_GROUP_ID) {
5656 proc_setegid(obj,
GIDT2NUM(SAVED_GROUP_ID));
5658 under_gid_switch = 1;
5673 under_gid_switch = 0;
5693 under_gid_switch = 1;
5702 #if defined(HAVE_TIMES)
5718 const double hertz =
5719 #ifdef HAVE__SC_CLK_TCK
5720 (double)sysconf(_SC_CLK_TCK);
5732 volatile VALUE utime, stime, cutime, sctime;
5742 #define rb_proc_times rb_f_notimplement
5836 #ifdef HAVE_GETPRIORITY
5847 #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
5849 VALUE inf = RLIM2NUM(RLIM_INFINITY);
5850 #ifdef RLIM_SAVED_MAX
5852 VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
5859 #ifdef RLIM_SAVED_CUR
5861 VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
5902 #ifdef RLIMIT_MEMLOCK
5909 #ifdef RLIMIT_MSGQUEUE
5924 #ifdef RLIMIT_NOFILE
5947 #ifdef RLIMIT_RTPRIO
5954 #ifdef RLIMIT_RTTIME
5962 #ifdef RLIMIT_SBSIZE
5967 #ifdef RLIMIT_SIGPENDING
6002 #if defined(HAVE_TIMES) || defined(_WIN32)