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);
1953 #define redirect_dup(oldfd) dup(oldfd)
1956 #if defined(DEBUG_REDIRECT) || defined(_WIN32)
1961 ret =
dup2(oldfd, newfd);
1962 if (newfd >= 0 && newfd <= 2)
1963 SetStdHandle(newfd == 0 ? STD_INPUT_HANDLE : newfd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, (HANDLE)
rb_w32_get_osfhandle(newfd));
1964 #if defined(DEBUG_REDIRECT)
1965 ttyprintf(
"dup2(%d, %d)\n", oldfd, newfd);
1970 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
1973 #if defined(DEBUG_REDIRECT)
1979 ttyprintf(
"close(%d)\n", fd);
1987 ret = open(pathname, flags, perm);
1988 ttyprintf(
"open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
1993 #define redirect_close(fd) close(fd)
1994 #define redirect_open(pathname, flags, perm) open((pathname), (flags), (perm))
2003 if (save_fd == -1) {
2011 if (
NIL_P(newary)) {
2019 if (
NIL_P(newary)) {
2054 return *(
int*)a - *(
int*)b;
2060 return *(
int*)b - *(
int*)a;
2077 pairs = (
struct fd_pair *)
malloc(
sizeof(
struct fd_pair) * n);
2078 if (pairs ==
NULL) {
2084 for (i = 0; i < n; i++) {
2088 pairs[
i].older_index = -1;
2093 qsort(pairs, n,
sizeof(
struct fd_pair),
intcmp);
2095 qsort(pairs, n,
sizeof(
struct fd_pair),
intrcmp);
2098 for (i = 0; i < n; i++) {
2099 int newfd = pairs[
i].newfd;
2100 struct fd_pair key, *found;
2102 found = bsearch(&key, pairs, n,
sizeof(
struct fd_pair),
intcmp);
2103 pairs[
i].num_newer = 0;
2105 while (pairs < found && (found-1)->oldfd == newfd)
2107 while (found < pairs+n && found->oldfd == newfd) {
2108 pairs[
i].num_newer++;
2109 found->older_index =
i;
2116 for (i = 0; i < n; i++) {
2118 while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
2127 pairs[j].oldfd = -1;
2128 j = pairs[j].older_index;
2130 pairs[j].num_newer--;
2135 for (i = 0; i < n; i++) {
2137 if (pairs[i].oldfd == -1)
2139 if (pairs[i].oldfd == pairs[i].newfd) {
2141 int fd = pairs[
i].oldfd;
2142 ret =
fcntl(fd, F_GETFD);
2144 ERRMSG(
"fcntl(F_GETFD)");
2147 if (ret & FD_CLOEXEC) {
2149 ret =
fcntl(fd, F_SETFD, ret);
2151 ERRMSG(
"fcntl(F_SETFD)");
2156 pairs[
i].oldfd = -1;
2159 if (extra_fd == -1) {
2161 if (extra_fd == -1) {
2175 pairs[
i].oldfd = extra_fd;
2176 j = pairs[
i].older_index;
2177 pairs[
i].older_index = -1;
2185 pairs[j].oldfd = -1;
2186 j = pairs[j].older_index;
2189 if (extra_fd != -1) {
2297 run_exec_pgroup(
VALUE obj,
VALUE save,
char *errmsg,
size_t errmsg_buflen)
2315 ret = setpgid(getpid(), pgroup);
2316 if (ret == -1)
ERRMSG(
"setpgid");
2321 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2323 run_exec_rlimit(
VALUE ary,
VALUE save,
char *errmsg,
size_t errmsg_buflen)
2337 RLIM2NUM(rlim.rlim_cur),
2338 RLIM2NUM(rlim.rlim_max)));
2340 if (
NIL_P(newary)) {
2346 rlim.rlim_cur = NUM2RLIM(
RARRAY_PTR(elt)[1]);
2347 rlim.rlim_max = NUM2RLIM(
RARRAY_PTR(elt)[2]);
2364 if (!
RTEST(options))
2378 if (run_exec_pgroup(obj, soptions, errmsg, errmsg_buflen) == -1)
2383 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2386 if (run_exec_rlimit(obj, soptions, errmsg, errmsg_buflen) == -1)
2414 if (!
NIL_P(soptions)) {
2429 mode_t oldmask = umask(mask);
2430 if (!
NIL_P(soptions))
2436 if (
run_exec_dup2(obj, soptions, errmsg, errmsg_buflen) == -1)
2442 if (!
NIL_P(soptions))
2443 rb_warn(
"cannot close fd before spawn");
2459 if (
run_exec_open(obj, soptions, errmsg, errmsg_buflen) == -1)
2483 const char *prog = e->
prog;
2501 #if !defined FD_CLOEXEC && !defined HAVE_SPAWNV
2502 char errmsg[80] = {
'\0' };
2506 fprintf(stderr,
"%s\n", errmsg);
2509 fprintf(stderr,
"%s:%d: command not found: %s\n",
2521 rb_exec_atfork(
void*
arg,
char *errmsg,
size_t errmsg_buflen)
2530 #if SIZEOF_INT == SIZEOF_LONG
2531 #define proc_syswait (VALUE (*)(VALUE))rb_syswait
2534 proc_syswait(
VALUE pid)
2543 move_fds_to_avoid_crash(
int *fdp,
int n,
VALUE fds)
2547 for (i = 0; i < n; i++) {
2554 ret =
fcntl(fdp[i], F_DUPFD, min);
2566 pipe_nocrash(
int filedes[2],
VALUE fds)
2574 if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
2584 struct chfunc_protect_t {
2585 int (*
chfunc)(
void*,
char *, size_t);
2594 struct chfunc_protect_t *
p = (
struct chfunc_protect_t *)arg;
2596 return (
VALUE)(*p->chfunc)(p->arg, p->errmsg, p->buflen);
2628 char *errmsg,
size_t errmsg_buflen)
2637 #define prefork() ( \
2638 rb_io_flush(rb_stdout), \
2639 rb_io_flush(rb_stderr) \
2645 if (pipe_nocrash(ep, fds))
return -1;
2646 if (
fcntl(ep[1], F_SETFD, FD_CLOEXEC)) {
2652 for (;
before_fork(), (pid = fork()) < 0; prefork()) {
2656 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
2659 if (!status && !
chfunc) {
2665 if (status) *status =
state;
2666 if (!state)
continue;
2681 struct chfunc_protect_t arg;
2684 arg.errmsg = errmsg;
2685 arg.buflen = errmsg_buflen;
2691 if (write(ep[1], &state,
sizeof(state)) ==
sizeof(state) && state) {
2698 if (write(ep[1], &err,
sizeof(err)) < 0) err =
errno;
2699 if (errmsg && 0 < errmsg_buflen) {
2700 errmsg[errmsg_buflen-1] =
'\0';
2701 errmsg_buflen =
strlen(errmsg);
2702 if (errmsg_buflen > 0 &&write(ep[1], errmsg, errmsg_buflen) < 0)
2707 #if EXIT_SUCCESS == 127
2720 if ((read(ep[0], &state,
sizeof(state))) ==
sizeof(state) && state) {
2725 #define READ_FROM_CHILD(ptr, len) \
2726 (NIL_P(io) ? read(ep[0], (ptr), (len)) : rb_io_bufread(io, (ptr), (len)))
2727 if ((size = READ_FROM_CHILD(&err,
sizeof(err))) < 0) {
2730 if (size ==
sizeof(err) &&
2731 errmsg && 0 < errmsg_buflen) {
2732 ssize_t ret = READ_FROM_CHILD(errmsg, errmsg_buflen-1);
2741 if (state || size) {
2758 struct chfunc_wrapper_t {
2764 chfunc_wrapper(
void *arg_,
char *errmsg,
size_t errmsg_buflen)
2766 struct chfunc_wrapper_t *arg = arg_;
2767 return arg->chfunc(arg->arg);
2774 struct chfunc_wrapper_t warg;
2777 return rb_fork_err(status, chfunc_wrapper, &warg, fds, NULL, 0);
2780 return rb_fork_err(status, NULL, NULL, fds, NULL, 0);
2787 #if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
2838 #define rb_f_fork rb_f_notimplement
2859 if (argc > 0 &&
rb_scan_args(argc, argv,
"01", &status) == 1) {
2943 if (argc > 0 &&
rb_scan_args(argc, argv,
"01", &status) == 1) {
2953 #if EXIT_SUCCESS != 0
3004 static int overriding;
3006 RETSIGTYPE (*hfunc)(int) = 0;
3009 RETSIGTYPE (*qfunc)(int) = 0;
3011 RETSIGTYPE (*ifunc)(int) = 0;
3017 hfunc =
signal(SIGHUP, SIG_IGN);
3020 qfunc =
signal(SIGQUIT, SIG_IGN);
3029 }
while (i == -1 &&
errno == EINTR);
3062 #if !defined HAVE_FORK || USE_SPAWNV
3068 #if defined HAVE_FORK && !USE_SPAWNV
3077 if (prog && argc) argv[0] =
prog;
3078 # if defined HAVE_SPAWNV
3083 pid = proc_spawn_n(argc, argv, prog, earg->
options);
3085 # if defined(_WIN32)
3102 char *errmsg,
size_t errmsg_buflen)
3160 #if defined(SIGCLD) && !defined(SIGCHLD)
3161 # define SIGCHLD SIGCLD
3165 RETSIGTYPE (*
chfunc)(int);
3170 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3442 const char *prog = errmsg;
3443 if (!prog[0] && !(prog = earg.
prog) && earg.
argc) {
3448 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3481 else if (argc == 1) {
3488 end = time(0) - beg;
3494 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
3512 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
3523 #define proc_getpgrp rb_f_notimplement
3527 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
3546 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
3552 #define proc_setpgrp rb_f_notimplement
3556 #if defined(HAVE_GETPGID)
3578 #define proc_getpgid rb_f_notimplement
3594 rb_pid_t ipid, ipgrp;
3604 #define proc_setpgid rb_f_notimplement
3608 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
3609 #if !defined(HAVE_SETSID)
3610 static rb_pid_t ruby_setsid(
void);
3611 #define setsid() ruby_setsid()
3635 #if !defined(HAVE_SETSID)
3636 #define HAVE_SETSID 1
3644 #if defined(SETPGRP_VOID)
3650 ret = setpgrp(0, pid);
3652 if (ret == -1)
return -1;
3654 if ((fd = open(
"/dev/tty", O_RDWR)) >= 0) {
3656 ioctl(fd, TIOCNOTTY, NULL);
3663 #define proc_setsid rb_f_notimplement
3667 #ifdef HAVE_GETPRIORITY
3688 int prio, iwhich, iwho;
3695 prio = getpriority(iwhich, iwho);
3700 #define proc_getpriority rb_f_notimplement
3704 #ifdef HAVE_GETPRIORITY
3720 int iwhich, iwho, iprio;
3727 if (setpriority(iwhich, iwho, iprio) < 0)
3732 #define proc_setpriority rb_f_notimplement
3735 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
3737 rlimit_resource_name2int(
const char *
name,
int casetype)
3741 #define RESCHECK(r) \
3743 if (STRCASECMP(name, #r) == 0) { \
3744 resource = RLIMIT_##r; \
3778 #ifdef RLIMIT_MEMLOCK
3781 #ifdef RLIMIT_MSGQUEUE
3787 #ifdef RLIMIT_NOFILE
3802 #ifdef RLIMIT_RTPRIO
3805 #ifdef RLIMIT_RTTIME
3814 #ifdef RLIMIT_SBSIZE
3817 #ifdef RLIMIT_SIGPENDING
3818 RESCHECK(SIGPENDING);
3827 for (p = name; *
p; p++)
3833 for (p = name; *
p; p++)
3839 rb_bug(
"unexpected casetype");
3846 rlimit_type_by_hname(
const char *
name)
3848 return rlimit_resource_name2int(name, 0);
3852 rlimit_type_by_lname(
const char *
name)
3854 return rlimit_resource_name2int(name, 1);
3858 rlimit_resource_type(
VALUE rtype)
3864 switch (
TYPE(rtype)) {
3884 r = rlimit_type_by_hname(name);
3892 rlimit_resource_value(
VALUE rval)
3897 switch (
TYPE(rval)) {
3914 return NUM2RLIM(rval);
3917 #ifdef RLIM_INFINITY
3918 if (strcmp(name,
"INFINITY") == 0)
return RLIM_INFINITY;
3920 #ifdef RLIM_SAVED_MAX
3921 if (strcmp(name,
"SAVED_MAX") == 0)
return RLIM_SAVED_MAX;
3923 #ifdef RLIM_SAVED_CUR
3924 if (strcmp(name,
"SAVED_CUR") == 0)
return RLIM_SAVED_CUR;
3930 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
3958 if (
getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
3961 return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
3964 #define proc_getrlimit rb_f_notimplement
3967 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
4022 VALUE resource, rlim_cur, rlim_max;
4027 rb_scan_args(argc, argv,
"21", &resource, &rlim_cur, &rlim_max);
4028 if (rlim_max ==
Qnil)
4029 rlim_max = rlim_cur;
4031 rlim.rlim_cur = rlimit_resource_value(rlim_cur);
4032 rlim.rlim_max = rlimit_resource_value(rlim_max);
4034 if (
setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4040 #define proc_setrlimit rb_f_notimplement
4048 if (under_uid_switch) {
4058 if (under_gid_switch) {
4075 #if defined HAVE_SETUID
4093 #define p_sys_setuid rb_f_notimplement
4097 #if defined HAVE_SETRUID
4115 #define p_sys_setruid rb_f_notimplement
4119 #if defined HAVE_SETEUID
4137 #define p_sys_seteuid rb_f_notimplement
4141 #if defined HAVE_SETREUID
4161 #define p_sys_setreuid rb_f_notimplement
4165 #if defined HAVE_SETRESUID
4185 #define p_sys_setresuid rb_f_notimplement
4208 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
4225 #if defined(HAVE_SETRESUID)
4227 #elif defined HAVE_SETREUID
4229 #elif defined HAVE_SETRUID
4231 #elif defined HAVE_SETUID
4244 #define proc_setuid rb_f_notimplement
4260 #ifdef BROKEN_SETREUID
4262 setreuid(rb_uid_t ruid, rb_uid_t euid)
4264 if (ruid != (rb_uid_t)-1 && ruid !=
getuid()) {
4265 if (euid == (rb_uid_t)-1) euid =
geteuid();
4266 if (
setuid(ruid) < 0)
return -1;
4268 if (euid != (rb_uid_t)-1 && euid !=
geteuid()) {
4269 if (seteuid(euid) < 0)
return -1;
4298 #if defined(HAVE_SETRESUID)
4300 SAVED_USER_ID = uid;
4301 #elif defined(HAVE_SETUID)
4303 SAVED_USER_ID = uid;
4304 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
4306 if (SAVED_USER_ID == uid) {
4310 if (setreuid(-1, SAVED_USER_ID) < 0)
rb_sys_fail(0);
4311 if (setreuid(SAVED_USER_ID, 0) < 0)
rb_sys_fail(0);
4314 SAVED_USER_ID = uid;
4319 SAVED_USER_ID = uid;
4324 SAVED_USER_ID = uid;
4326 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
4328 if (SAVED_USER_ID == uid) {
4340 SAVED_USER_ID = uid;
4346 SAVED_USER_ID = uid;
4352 #if defined(HAVE_SETRESUID)
4353 if (setresuid((
getuid() == uid)? (rb_uid_t)-1: uid,
4354 (
geteuid() == uid)? (rb_uid_t)-1: uid,
4355 (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0)
rb_sys_fail(0);
4356 SAVED_USER_ID = uid;
4357 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
4358 if (SAVED_USER_ID == uid) {
4359 if (setreuid((
getuid() == uid)? (rb_uid_t)-1: uid,
4360 (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
4362 }
else if (
getuid() != uid) {
4363 if (setreuid(uid, (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
4365 SAVED_USER_ID = uid;
4366 }
else if (
geteuid() != uid) {
4368 SAVED_USER_ID = uid;
4371 if (setreuid(-1, SAVED_USER_ID) < 0)
rb_sys_fail(0);
4372 if (setreuid(SAVED_USER_ID, uid) < 0)
rb_sys_fail(0);
4373 SAVED_USER_ID = uid;
4376 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
4377 if (SAVED_USER_ID == uid) {
4380 }
else if (
geteuid() == uid) {
4383 SAVED_USER_ID = uid;
4386 SAVED_USER_ID = uid;
4389 }
else if (
getuid() == uid) {
4392 SAVED_USER_ID = uid;
4398 #elif defined HAVE_44BSD_SETUID
4402 SAVED_USER_ID = uid;
4407 #elif defined HAVE_SETEUID
4408 if (
getuid() == uid && SAVED_USER_ID == uid) {
4414 #elif defined HAVE_SETUID
4415 if (
getuid() == uid && SAVED_USER_ID == uid) {
4430 #if defined HAVE_SETGID
4448 #define p_sys_setgid rb_f_notimplement
4452 #if defined HAVE_SETRGID
4470 #define p_sys_setrgid rb_f_notimplement
4474 #if defined HAVE_SETEGID
4492 #define p_sys_setegid rb_f_notimplement
4496 #if defined HAVE_SETREGID
4516 #define p_sys_setregid rb_f_notimplement
4519 #if defined HAVE_SETRESGID
4539 #define p_sys_setresgid rb_f_notimplement
4543 #if defined HAVE_ISSETUGID
4567 #define p_sys_issetugid rb_f_notimplement
4590 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
4606 #if defined(HAVE_SETRESGID)
4608 #elif defined HAVE_SETREGID
4610 #elif defined HAVE_SETRGID
4612 #elif defined HAVE_SETGID
4625 #define proc_setgid rb_f_notimplement
4629 #if defined(HAVE_SETGROUPS) || defined(HAVE_GETGROUPS)
4650 #define RB_MAX_GROUPS (65536)
4651 static int _maxgroups = -1;
4652 static int get_sc_ngroups_max(
void)
4654 #ifdef _SC_NGROUPS_MAX
4655 return (
int)sysconf(_SC_NGROUPS_MAX);
4656 #elif defined(NGROUPS_MAX)
4657 return (
int)NGROUPS_MAX;
4662 static int maxgroups(
void)
4664 if (_maxgroups < 0) {
4665 _maxgroups = get_sc_ngroups_max();
4667 _maxgroups = RB_MAX_GROUPS;
4676 #ifdef HAVE_GETGROUPS
4695 ngroups = getgroups(0, NULL);
4699 groups =
ALLOCA_N(rb_gid_t, ngroups);
4701 ngroups = getgroups(ngroups, groups);
4706 for (i = 0; i < ngroups; i++)
4712 #define proc_getgroups rb_f_notimplement
4716 #ifdef HAVE_SETGROUPS
4735 #ifdef HAVE_GETGRNAM_R
4736 long getgr_buf_len = sysconf(_SC_GETGR_R_SIZE_MAX);
4739 if (getgr_buf_len < 0)
4740 getgr_buf_len = 4096;
4741 getgr_buf =
ALLOCA_N(
char, getgr_buf_len);
4747 if (ngroups > maxgroups())
4750 groups =
ALLOCA_N(rb_gid_t, ngroups);
4752 for (i = 0; i < ngroups; i++) {
4770 #ifdef HAVE_GETGRNAM_R
4771 ret = getgrnam_r(grpname, &grp, getgr_buf, getgr_buf_len, &p);
4775 p = getgrnam(grpname);
4781 groups[
i] = p->gr_gid;
4786 if (setgroups(ngroups, groups) == -1)
4792 #define proc_setgroups rb_f_notimplement
4796 #ifdef HAVE_INITGROUPS
4823 #define proc_initgroups rb_f_notimplement
4826 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
4843 #define proc_getmaxgroups rb_f_notimplement
4846 #ifdef HAVE_SETGROUPS
4859 int ngroups_max = get_sc_ngroups_max();
4864 if (ngroups > RB_MAX_GROUPS)
4865 ngroups = RB_MAX_GROUPS;
4867 if (ngroups_max > 0 && ngroups > ngroups_max)
4868 ngroups = ngroups_max;
4870 _maxgroups = ngroups;
4875 #define proc_setmaxgroups rb_f_notimplement
4878 #if defined(HAVE_DAEMON) || (defined(HAVE_FORK) && defined(HAVE_SETSID))
4879 static int rb_daemon(
int nochdir,
int noclose);
4898 VALUE nochdir, noclose;
4905 n = rb_daemon(
RTEST(nochdir),
RTEST(noclose));
4911 rb_daemon(
int nochdir,
int noclose)
4916 err = daemon(nochdir, noclose);
4922 #define fork_daemon() \
4923 switch (rb_fork(0, 0, 0, Qnil)) { \
4924 case -1: return -1; \
4925 case 0: rb_thread_atfork(); break; \
4926 default: _exit(EXIT_SUCCESS); \
4931 if (setsid() < 0)
return -1;
4939 if (!noclose && (n = open(
"/dev/null", O_RDWR, 0)) != -1) {
4951 #define proc_daemon rb_f_notimplement
4966 #ifdef BROKEN_SETREGID
4968 setregid(rb_gid_t rgid, rb_gid_t egid)
4970 if (rgid != (rb_gid_t)-1 && rgid !=
getgid()) {
4971 if (egid == (rb_gid_t)-1) egid =
getegid();
4972 if (
setgid(rgid) < 0)
return -1;
4974 if (egid != (rb_gid_t)-1 && egid !=
getegid()) {
4975 if (setegid(egid) < 0)
return -1;
5004 #if defined(HAVE_SETRESGID)
5006 SAVED_GROUP_ID = gid;
5007 #elif defined HAVE_SETGID
5009 SAVED_GROUP_ID = gid;
5010 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5012 if (SAVED_GROUP_ID == gid) {
5016 if (setregid(-1, SAVED_GROUP_ID) < 0)
rb_sys_fail(0);
5017 if (setregid(SAVED_GROUP_ID, 0) < 0)
rb_sys_fail(0);
5020 SAVED_GROUP_ID = gid;
5025 SAVED_GROUP_ID = gid;
5030 SAVED_GROUP_ID = gid;
5032 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
5034 if (SAVED_GROUP_ID == gid) {
5047 SAVED_GROUP_ID = gid;
5053 SAVED_GROUP_ID = gid;
5059 #if defined(HAVE_SETRESGID)
5060 if (setresgid((
getgid() == gid)? (rb_gid_t)-1: gid,
5061 (
getegid() == gid)? (rb_gid_t)-1: gid,
5062 (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0)
rb_sys_fail(0);
5063 SAVED_GROUP_ID = gid;
5064 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5065 if (SAVED_GROUP_ID == gid) {
5066 if (setregid((
getgid() == gid)? (rb_uid_t)-1: gid,
5067 (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5069 }
else if (
getgid() != gid) {
5070 if (setregid(gid, (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5072 SAVED_GROUP_ID = gid;
5073 }
else if (
getegid() != gid) {
5075 SAVED_GROUP_ID = gid;
5078 if (setregid(-1, SAVED_GROUP_ID) < 0)
rb_sys_fail(0);
5079 if (setregid(SAVED_GROUP_ID, gid) < 0)
rb_sys_fail(0);
5080 SAVED_GROUP_ID = gid;
5083 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
5084 if (SAVED_GROUP_ID == gid) {
5087 }
else if (
getegid() == gid) {
5090 SAVED_GROUP_ID = gid;
5093 SAVED_GROUP_ID = gid;
5096 }
else if (
getgid() == gid) {
5099 SAVED_GROUP_ID = gid;
5105 #elif defined HAVE_44BSD_SETGID
5109 SAVED_GROUP_ID = gid;
5114 #elif defined HAVE_SETEGID
5115 if (
getgid() == gid && SAVED_GROUP_ID == gid) {
5121 #elif defined HAVE_SETGID
5122 if (
getgid() == gid && SAVED_GROUP_ID == gid) {
5154 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
5171 #if defined(HAVE_SETRESUID)
5173 #elif defined HAVE_SETREUID
5175 #elif defined HAVE_SETEUID
5177 #elif defined HAVE_SETUID
5191 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
5192 #define proc_seteuid_m proc_seteuid
5194 #define proc_seteuid_m rb_f_notimplement
5206 #if defined(HAVE_SETRESUID)
5209 SAVED_USER_ID = euid;
5213 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5218 SAVED_USER_ID = euid;
5220 #elif defined HAVE_SETEUID
5222 #elif defined HAVE_SETUID
5274 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
5291 #if defined(HAVE_SETRESGID)
5293 #elif defined HAVE_SETREGID
5295 #elif defined HAVE_SETEGID
5297 #elif defined HAVE_SETGID
5311 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
5312 #define proc_setegid_m proc_setegid
5314 #define proc_setegid_m rb_f_notimplement
5326 #if defined(HAVE_SETRESGID)
5329 SAVED_GROUP_ID = egid;
5333 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5338 SAVED_GROUP_ID = egid;
5340 #elif defined HAVE_SETEGID
5342 #elif defined HAVE_SETGID
5386 #if defined(HAVE_SETRESUID)
5388 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5418 #if defined(HAVE_SETRESUID)
5419 if (setresuid(euid, uid, uid) < 0)
rb_sys_fail(0);
5420 SAVED_USER_ID = uid;
5421 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5423 SAVED_USER_ID = uid;
5443 #if defined(HAVE_SETRESGID)
5445 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5475 #if defined(HAVE_SETRESGID)
5476 if (setresgid(egid, gid, gid) < 0)
rb_sys_fail(0);
5477 SAVED_GROUP_ID = gid;
5478 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5480 SAVED_GROUP_ID = gid;
5501 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
5509 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
5513 under_uid_switch = 0;
5545 under_uid_switch = 1;
5550 }
else if (euid != SAVED_USER_ID) {
5551 proc_seteuid(obj,
UIDT2NUM(SAVED_USER_ID));
5553 under_uid_switch = 1;
5567 under_uid_switch = 0;
5587 under_uid_switch = 1;
5610 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
5617 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
5621 under_gid_switch = 0;
5653 under_gid_switch = 1;
5659 else if (egid != SAVED_GROUP_ID) {
5660 proc_setegid(obj,
GIDT2NUM(SAVED_GROUP_ID));
5662 under_gid_switch = 1;
5677 under_gid_switch = 0;
5697 under_gid_switch = 1;
5706 #if defined(HAVE_TIMES)
5722 const double hertz =
5723 #ifdef HAVE__SC_CLK_TCK
5724 (double)sysconf(_SC_CLK_TCK);
5736 volatile VALUE utime, stime, cutime, sctime;
5746 #define rb_proc_times rb_f_notimplement
5840 #ifdef HAVE_GETPRIORITY
5851 #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
5853 VALUE inf = RLIM2NUM(RLIM_INFINITY);
5854 #ifdef RLIM_SAVED_MAX
5856 VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
5863 #ifdef RLIM_SAVED_CUR
5865 VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
5906 #ifdef RLIMIT_MEMLOCK
5913 #ifdef RLIMIT_MSGQUEUE
5928 #ifdef RLIMIT_NOFILE
5951 #ifdef RLIMIT_RTPRIO
5958 #ifdef RLIMIT_RTTIME
5966 #ifdef RLIMIT_SBSIZE
5971 #ifdef RLIMIT_SIGPENDING
6006 #if defined(HAVE_TIMES) || defined(_WIN32)