41 #define EXIT_SUCCESS 0
44 #define EXIT_FAILURE 1
47 #ifdef HAVE_SYS_WAIT_H
48 # include <sys/wait.h>
50 #ifdef HAVE_SYS_RESOURCE_H
51 # include <sys/resource.h>
53 #ifdef HAVE_SYS_PARAM_H
54 # include <sys/param.h>
57 # define MAXPATHLEN 1024
66 #if defined(__native_client__) && defined(NACL_NEWLIB)
72 #ifdef HAVE_SYS_TIMES_H
73 #include <sys/times.h>
83 #define numberof(array) (int)(sizeof(array)/sizeof((array)[0]))
85 #if defined(HAVE_TIMES) || defined(_WIN32)
86 static VALUE rb_cProcessTms;
90 #define WIFEXITED(w) (((w) & 0xff) == 0)
93 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
96 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
99 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
102 #define WTERMSIG(w) ((w) & 0x7f)
105 #define WSTOPSIG WEXITSTATUS
108 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
109 #define HAVE_44BSD_SETUID 1
110 #define HAVE_44BSD_SETGID 1
118 #ifdef BROKEN_SETREUID
119 #define setreuid ruby_setreuid
120 int setreuid(rb_uid_t ruid, rb_uid_t euid);
122 #ifdef BROKEN_SETREGID
123 #define setregid ruby_setregid
124 int setregid(rb_gid_t rgid, rb_gid_t egid);
127 #if defined(HAVE_44BSD_SETUID) || defined(__APPLE__)
128 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
129 #define OBSOLETE_SETREUID 1
131 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
132 #define OBSOLETE_SETREGID 1
136 #define preserving_errno(stmts) \
137 do {int saved_errno = errno; stmts; errno = saved_errno;} while (0)
143 #define p_uid_from_name p_uid_from_name
144 #define p_gid_from_name p_gid_from_name
147 #if defined(HAVE_PWD_H)
148 # if defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
149 # define USE_GETPWNAM_R 1
151 # ifdef USE_GETPWNAM_R
152 # define PREPARE_GETPWNAM \
153 long getpw_buf_len = sysconf(_SC_GETPW_R_SIZE_MAX); \
154 char *getpw_buf = ALLOCA_N(char, (getpw_buf_len < 0 ? (getpw_buf_len = 4096) : getpw_buf_len));
155 # define OBJ2UID(id) obj2uid((id), getpw_buf, getpw_buf_len)
156 static rb_uid_t obj2uid(
VALUE id,
char *getpw_buf,
size_t getpw_buf_len);
158 # define PREPARE_GETPWNAM
159 # define OBJ2UID(id) obj2uid((id))
160 static rb_uid_t obj2uid(
VALUE id);
163 # define PREPARE_GETPWNAM
164 # define OBJ2UID(id) NUM2UIDT(id)
165 # ifdef p_uid_from_name
166 # undef p_uid_from_name
167 # define p_uid_from_name rb_f_notimplement
171 #if defined(HAVE_GRP_H)
172 # if defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
173 # define USE_GETGRNAM_R
175 # ifdef USE_GETGRNAM_R
176 # define PREPARE_GETGRNAM \
177 long getgr_buf_len = sysconf(_SC_GETGR_R_SIZE_MAX); \
178 char *getgr_buf = ALLOCA_N(char, (getgr_buf_len < 0 ? (getgr_buf_len = 4096) : getgr_buf_len));
179 # define OBJ2GID(id) obj2gid((id), getgr_buf, getgr_buf_len)
180 static rb_gid_t obj2gid(
VALUE id,
char *getgr_buf,
size_t getgr_buf_len);
182 # define PREPARE_GETGRNAM
183 # define OBJ2GID(id) obj2gid((id))
184 static rb_gid_t obj2gid(
VALUE id);
187 # define PREPARE_GETGRNAM
188 # define OBJ2GID(id) NUM2GIDT(id)
189 # ifdef p_gid_from_name
190 # undef p_gid_from_name
191 # define p_gid_from_name rb_f_notimplement
309 #define PST2INT(st) NUM2INT(pst_to_i(st))
336 rb_str_catf(str,
" stopped SIG%s (signal %d)", signame, stopsig);
346 rb_str_catf(str,
" SIG%s (signal %d)", signame, termsig);
356 if (WCOREDUMP(status)) {
433 if (st1 == st2)
return Qtrue;
644 if (WCOREDUMP(status))
653 #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
692 struct waitpid_arg *arg = data;
695 #if defined NO_WAITPID
697 #elif defined HAVE_WAITPID
698 result =
waitpid(arg->pid, arg->st, arg->flags);
700 result = wait4(arg->pid, arg->st, arg->flags,
NULL);
703 return (
void *)(
VALUE)result;
711 struct waitpid_arg arg;
720 if (
errno == EINTR) {
729 if (pid == (rb_pid_t)-1) {
731 data.
pid = (rb_pid_t)-1;
734 if (data.status != -1) {
739 else if (
st_delete(pid_tbl, &piddata, &status)) {
753 if (
errno == EINTR) {
759 if (result == pid || pid == (rb_pid_t)-1) {
848 if (argc == 2 && !
NIL_P(vflags)) {
852 if ((pid =
rb_waitpid(pid, &status, flags)) < 0)
934 if (
errno == EINTR) {
966 rb_pid_t cpid,
pid = (rb_pid_t)(
VALUE)arg;
969 while ((cpid =
rb_waitpid(pid, &status, 0)) == 0) {
1042 static RETSIGTYPE (*saved_sigpipe_handler)(int) = 0;
1047 sig_do_nothing(
int sig)
1063 saved_sigpipe_handler =
signal(SIGPIPE, sig_do_nothing);
1094 signal(SIGPIPE, saved_sigpipe_handler);
1114 #define before_fork() before_exec()
1115 #define after_fork() (rb_threadptr_pending_interrupt_clear(GET_THREAD()), after_exec())
1129 #if defined(HAVE_FORK) && !defined(__native_client__)
1132 #define try_with_sh(prog, argv, envp) ((saved_errno == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0)
1134 exec_with_sh(
const char *prog,
char **
argv,
char **envp)
1136 *argv = (
char *)prog;
1137 *--argv = (
char *)
"sh";
1139 execve(
"/bin/sh", argv, envp);
1141 execv(
"/bin/sh", argv);
1145 #define try_with_sh(prog, argv, envp) (void)0
1152 #ifdef __native_client__
1158 # if defined(__EMX__) || defined(OS2)
1159 char **new_argv =
NULL;
1169 # if defined(__EMX__) || defined(OS2)
1171 # define COMMAND "cmd.exe"
1178 for (n = 0; argv[n]; n++)
1180 new_argv =
ALLOC_N(
char*, n + 2);
1182 new_argv[n + 1] = argv[n];
1183 new_argv[1] = strcpy(
ALLOC_N(
char,
strlen(argv[0]) + 1), argv[0]);
1184 for (p = new_argv[1]; *p !=
'\0'; p++)
1187 new_argv[0] = COMMAND;
1199 execve(prog, argv, envp);
1203 # if defined(__EMX__) || defined(OS2)
1236 #define ARGV_COUNT(n) ((n)+1)
1237 #define ARGV_SIZE(n) (sizeof(char*) * ARGV_COUNT(n))
1238 #define ALLOC_ARGV(n, v) ALLOCV_N(char*, (v), ARGV_COUNT(n))
1246 for (i=0; i<
argc; i++) {
1265 #ifdef __native_client__
1272 while (*s ==
' ' || *s ==
'\t' || *s ==
'\n')
1284 #if defined(__CYGWIN32__) || defined(__EMX__)
1290 execl(shell,
"sh",
"-c", str, (
char *)
NULL);
1292 status = system(str);
1298 execle(
"/bin/sh",
"sh",
"-c", str, (
char *)
NULL, (
char **)
RSTRING_PTR(envp_str));
1300 execl(
"/bin/sh",
"sh",
"-c", str, (
char *)
NULL);
1360 #define HAVE_SPAWNV 1
1363 #if !defined(HAVE_FORK) && defined(HAVE_SPAWNV)
1364 # define USE_SPAWNV 1
1366 # define USE_SPAWNV 0
1369 # define P_NOWAIT _P_NOWAIT
1374 #define proc_spawn_cmd_internal(argv, prog) rb_w32_aspawn(P_NOWAIT, (prog), (argv))
1377 proc_spawn_cmd_internal(
char **argv,
char *prog)
1390 status = spawnv(
P_NOWAIT, prog, (
const char **)argv);
1391 if (status == -1 &&
errno == ENOEXEC) {
1392 *argv = (
char *)prog;
1393 *--argv = (
char *)
"sh";
1394 status = spawnv(
P_NOWAIT,
"/bin/sh", (
const char **)argv);
1396 if (status == -1)
errno = ENOEXEC;
1412 flags = CREATE_NEW_PROCESS_GROUP;
1416 pid = proc_spawn_cmd_internal(argv, prog ?
RSTRING_PTR(prog) : 0);
1423 #define proc_spawn_sh(str) rb_w32_spawn(P_NOWAIT, (str), 0)
1426 proc_spawn_sh(
char *str)
1433 status = spawnl(
P_NOWAIT, (shell ? shell :
"/bin/sh"),
"sh",
"-c", str, (
char*)
NULL);
1482 else if (fd >= 3 && iskey) {
1515 VALUE path, flags, perm;
1519 switch (
TYPE(val)) {
1583 flags =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
1595 if (!
NIL_P(val))
goto io;
1601 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1602 static int rlimit_type_by_lname(
const char *
name);
1611 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1617 switch (
TYPE(key)) {
1628 else if (val ==
Qtrue)
1651 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
1652 if (strncmp(
"rlimit_",
rb_id2name(
id), 7) == 0 &&
1653 (rtype = rlimit_type_by_lname(
rb_id2name(
id)+7)) != -1) {
1655 VALUE tmp, softlim, hardlim;
1680 if (
id ==
rb_intern(
"unsetenv_others")) {
1703 else if (
id ==
rb_intern(
"close_others")) {
1735 "uid option is unimplemented on this machine");
1751 "gid option is unimplemented on this machine");
1801 VALUE execarg_obj = args[0];
1803 VALUE nonopts = args[1];
1871 if (oldfd != lastfd) {
1902 args[0] = execarg_obj;
1944 const char *
name = 0;
1961 for (i = 0; i <
argc; i++) {
1978 *opthash_ret =
hash;
1993 prog = (*argv_p)[0];
1994 if (accept_shell && *argc_p == 1) {
2012 int ret = strncmp(word->
ptr, el, word->
len);
2013 if (!ret && ((
const char *)el)[word->
len]) ret = -1;
2026 if (!
NIL_P(opthash)) {
2036 eargp->
invoke.
sh.shell_script = prog;
2042 static const char posix_sh_cmds[][9] = {
2101 if (*p ==
' ' || *p ==
'\t') {
2102 if (first.
ptr && !first.
len) first.
len = p - first.
ptr;
2105 if (!first.
ptr) first.
ptr =
p;
2107 if (!has_meta &&
strchr(
"*?{}[]<>()~&|\\$;'`\"\n#", *p))
2113 else if (*p ==
'/') {
2120 if (!has_meta && first.
ptr) {
2121 if (!first.
len) first.
len = p - first.
ptr;
2122 if (first.
len > 0 && first.
len <=
sizeof(posix_sh_cmds[0]) &&
2135 while (*p ==
' ' || *p ==
'\t')
2139 while (*p && *p !=
' ' && *p !=
'\t')
2152 const char *abspath;
2165 for (i = 0; i <
argc; i++) {
2173 const char *
p, *ep, *null=
NULL;
2257 int unsetenv_others;
2273 if (unsetenv_others || envopts !=
Qfalse) {
2276 if (unsetenv_others) {
2389 VALUE execarg_obj, fail_str;
2391 #define CHILD_ERRMSG_BUFLEN 80
2399 #if defined(__APPLE__) || defined(__HAIKU__)
2411 #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
2414 #if defined(DEBUG_REDIRECT)
2419 ttyprintf(
const char *fmt, ...)
2425 tty = fopen(
"con",
"w");
2427 tty = fopen(
"/dev/tty",
"w");
2433 vfprintf(tty, fmt, ap);
2444 ttyprintf(
"dup(%d) => %d\n", oldfd, ret);
2448 #define redirect_dup(oldfd) dup(oldfd)
2451 #if defined(DEBUG_REDIRECT) || defined(_WIN32)
2456 ret =
dup2(oldfd, newfd);
2457 if (newfd >= 0 && newfd <= 2)
2458 SetStdHandle(newfd == 0 ? STD_INPUT_HANDLE : newfd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, (HANDLE)
rb_w32_get_osfhandle(newfd));
2459 #if defined(DEBUG_REDIRECT)
2460 ttyprintf(
"dup2(%d, %d)\n", oldfd, newfd);
2465 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
2468 #if defined(DEBUG_REDIRECT)
2474 ttyprintf(
"close(%d)\n", fd);
2482 ret = open(pathname, flags, perm);
2483 ttyprintf(
"open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
2488 #define redirect_close(fd) close(fd)
2489 #define redirect_open(pathname, flags, perm) open((pathname), (flags), (perm))
2498 if (save_fd == -1) {
2527 return *(
int*)a - *(
int*)b;
2533 return *(
int*)b - *(
int*)a;
2562 for (i = 0; i < n; i++) {
2576 for (i = 0; i < n; i++) {
2583 while (pairs < found && (found-1)->
oldfd == newfd)
2585 while (found < pairs+n && found->
oldfd == newfd) {
2594 for (i = 0; i < n; i++) {
2596 while (j != -1 && pairs[j].
oldfd != -1 && pairs[j].
num_newer == 0) {
2605 pairs[j].
oldfd = -1;
2613 for (i = 0; i < n; i++) {
2615 if (pairs[i].
oldfd == -1)
2620 ret =
fcntl(fd, F_GETFD);
2622 ERRMSG(
"fcntl(F_GETFD)");
2625 if (ret & FD_CLOEXEC) {
2627 ret =
fcntl(fd, F_SETFD, ret);
2629 ERRMSG(
"fcntl(F_SETFD)");
2637 if (extra_fd == -1) {
2639 if (extra_fd == -1) {
2653 pairs[
i].
oldfd = extra_fd;
2663 pairs[j].
oldfd = -1;
2667 if (extra_fd != -1) {
2777 run_exec_pgroup(
const struct rb_execarg *eargp,
struct rb_execarg *sargp,
char *errmsg,
size_t errmsg_buflen)
2801 ret = setpgid(getpid(), pgroup);
2802 if (ret == -1)
ERRMSG(
"setpgid");
2807 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2810 run_exec_rlimit(
VALUE ary,
struct rb_execarg *sargp,
char *errmsg,
size_t errmsg_buflen)
2824 RLIM2NUM(rlim.rlim_cur),
2825 RLIM2NUM(rlim.rlim_max)));
2832 rlim.rlim_cur = NUM2RLIM(
RARRAY_PTR(elt)[1]);
2833 rlim.rlim_max = NUM2RLIM(
RARRAY_PTR(elt)[2]);
2843 #if !defined(HAVE_FORK)
2884 if (run_exec_pgroup(eargp, sargp, errmsg, errmsg_buflen) == -1)
2889 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
2892 if (run_exec_rlimit(obj, sargp, errmsg, errmsg_buflen) == -1)
2897 #if !defined(HAVE_FORK)
2937 rb_warn(
"cannot close fd before spawn");
3021 #if !defined(HAVE_FORK)
3022 struct rb_execarg sarg, *
const sargp = &sarg;
3037 char *abspath =
NULL;
3042 #if !defined(HAVE_FORK)
3070 #if !defined FD_CLOEXEC && !defined HAVE_SPAWNV
3071 char errmsg[80] = {
'\0' };
3075 fprintf(stderr,
"%s\n", errmsg);
3078 fprintf(stderr,
"%s:%d: command not found: %s\n",
3080 RSTRING_PTR(e->use_shell ? e->invoke.sh.shell_script : e->invoke.cmd.command_name));
3092 rb_exec_atfork(
void* arg,
char *errmsg,
size_t errmsg_buflen)
3099 #if SIZEOF_INT == SIZEOF_LONG
3100 #define proc_syswait (VALUE (*)(VALUE))rb_syswait
3103 proc_syswait(
VALUE pid)
3111 move_fds_to_avoid_crash(
int *fdp,
int n,
VALUE fds)
3115 for (i = 0; i < n; i++) {
3134 pipe_nocrash(
int filedes[2],
VALUE fds)
3142 if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
3152 struct chfunc_protect_t {
3153 int (*
chfunc)(
void*,
char *, size_t);
3160 chfunc_protect(
VALUE arg)
3162 struct chfunc_protect_t *
p = (
struct chfunc_protect_t *)arg;
3164 return (
VALUE)(*p->chfunc)(p->arg, p->errmsg, p->buflen);
3198 retry_fork(
int *status,
int *ep,
int chfunc_is_async_signal_safe)
3203 #define prefork() ( \
3204 rb_io_flush(rb_stdout), \
3205 rb_io_flush(rb_stderr) \
3210 if (!chfunc_is_async_signal_safe)
3215 if (!chfunc_is_async_signal_safe)
3222 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
3225 if (!status && !ep) {
3231 if (status) *status = state;
3232 if (!state)
continue;
3246 send_child_error(
int fd,
int state,
char *errmsg,
size_t errmsg_buflen,
int chfunc_is_async_signal_safe)
3251 if (!chfunc_is_async_signal_safe) {
3252 if (write(fd, &state,
sizeof(state)) ==
sizeof(state) && state) {
3260 if (write(fd, &err,
sizeof(err)) < 0) err =
errno;
3261 if (errmsg && 0 < errmsg_buflen) {
3262 errmsg[errmsg_buflen-1] =
'\0';
3263 errmsg_buflen =
strlen(errmsg);
3264 if (errmsg_buflen > 0 && write(fd, errmsg, errmsg_buflen) < 0)
3271 recv_child_error(
int fd,
int *statep,
VALUE *excp,
int *errp,
char *errmsg,
size_t errmsg_buflen,
int chfunc_is_async_signal_safe)
3277 if (!chfunc_is_async_signal_safe) {
3278 if ((read(fd, &state,
sizeof(state))) ==
sizeof(state) && state) {
3283 if (!*statep && state) *statep = state;
3286 #define READ_FROM_CHILD(ptr, len) \
3287 (NIL_P(io) ? read(fd, (ptr), (len)) : rb_io_bufread(io, (ptr), (len)))
3288 if ((size = READ_FROM_CHILD(&err,
sizeof(err))) < 0) {
3292 if (size ==
sizeof(err) &&
3293 errmsg && 0 < errmsg_buflen) {
3294 ssize_t ret = READ_FROM_CHILD(errmsg, errmsg_buflen-1);
3307 rb_fork_internal(
int *status,
int (*
chfunc)(
void*,
char *,
size_t),
void *charg,
3308 int chfunc_is_async_signal_safe,
VALUE fds,
3309 char *errmsg,
size_t errmsg_buflen)
3317 if (status) *status = 0;
3330 if (pipe_nocrash(ep, fds))
return -1;
3331 pid = retry_fork(status, ep, chfunc_is_async_signal_safe);
3338 if (chfunc_is_async_signal_safe)
3339 ret =
chfunc(charg, errmsg, errmsg_buflen);
3341 struct chfunc_protect_t arg;
3344 arg.errmsg = errmsg;
3345 arg.buflen = errmsg_buflen;
3349 send_child_error(ep[1], state, errmsg, errmsg_buflen, chfunc_is_async_signal_safe);
3350 #if EXIT_SUCCESS == 127
3357 error_occured = recv_child_error(ep[0], &state, &exc, &err, errmsg, errmsg_buflen, chfunc_is_async_signal_safe);
3358 if (state || error_occured) {
3361 if (state) *status = state;
3375 rb_fork_err(
int *status,
int (*
chfunc)(
void*,
char *,
size_t),
void *charg,
VALUE fds,
3376 char *errmsg,
size_t errmsg_buflen)
3378 return rb_fork_internal(status,
chfunc, charg,
FALSE, fds, errmsg, errmsg_buflen);
3383 char *errmsg,
size_t errmsg_buflen)
3385 return rb_fork_internal(status,
chfunc, charg,
TRUE, fds, errmsg, errmsg_buflen);
3388 struct chfunc_wrapper_t {
3394 chfunc_wrapper(
void *arg_,
char *errmsg,
size_t errmsg_buflen)
3396 struct chfunc_wrapper_t *arg = arg_;
3397 return arg->chfunc(arg->arg);
3401 rb_fork(
int *status,
int (*
chfunc)(
void*),
void *charg,
VALUE fds)
3404 struct chfunc_wrapper_t warg;
3407 return rb_fork_internal(status, chfunc_wrapper, &warg,
FALSE, fds,
NULL, 0);
3423 #if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
3474 #define rb_f_fork rb_f_notimplement
3491 #if EXIT_SUCCESS != 0
3518 if (argc > 0 &&
rb_scan_args(argc, argv,
"01", &status) == 1) {
3592 if (argc > 0 &&
rb_scan_args(argc, argv,
"01", &status) == 1) {
3653 #if !defined HAVE_FORK || USE_SPAWNV
3658 #if defined HAVE_FORK && !USE_SPAWNV
3671 # if defined HAVE_SPAWNV
3677 pid = proc_spawn_cmd(argv, prog, eargp);
3679 # if defined(_WIN32)
3764 #if defined(SIGCLD) && !defined(SIGCHLD)
3765 # define SIGCHLD SIGCLD
3769 RETSIGTYPE (*
chfunc)(int);
3775 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
3779 if (ret == (rb_pid_t)-1)
3780 rb_sys_fail(
"Another thread waited the process started by system().");
4048 VALUE execarg_obj, fail_str;
4060 const char *prog = errmsg;
4066 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
4104 end = time(0) - beg;
4110 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
4128 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
4139 #define proc_getpgrp rb_f_notimplement
4143 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
4162 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
4168 #define proc_setpgrp rb_f_notimplement
4172 #if defined(HAVE_GETPGID)
4194 #define proc_getpgid rb_f_notimplement
4210 rb_pid_t ipid, ipgrp;
4220 #define proc_setpgid rb_f_notimplement
4254 #define proc_getsid rb_f_notimplement
4258 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
4259 #if !defined(HAVE_SETSID)
4260 static rb_pid_t ruby_setsid(
void);
4261 #define setsid() ruby_setsid()
4285 #if !defined(HAVE_SETSID)
4286 #define HAVE_SETSID 1
4294 #if defined(SETPGRP_VOID)
4300 ret = setpgrp(0, pid);
4302 if (ret == -1)
return -1;
4313 #define proc_setsid rb_f_notimplement
4317 #ifdef HAVE_GETPRIORITY
4338 int prio, iwhich, iwho;
4345 prio = getpriority(iwhich, iwho);
4350 #define proc_getpriority rb_f_notimplement
4354 #ifdef HAVE_GETPRIORITY
4370 int iwhich, iwho, iprio;
4377 if (setpriority(iwhich, iwho, iprio) < 0)
4382 #define proc_setpriority rb_f_notimplement
4385 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
4387 rlimit_resource_name2int(
const char *
name,
int casetype)
4391 #define RESCHECK(r) \
4393 if (STRCASECMP(name, #r) == 0) { \
4394 resource = RLIMIT_##r; \
4428 #ifdef RLIMIT_MEMLOCK
4431 #ifdef RLIMIT_MSGQUEUE
4437 #ifdef RLIMIT_NOFILE
4452 #ifdef RLIMIT_RTPRIO
4455 #ifdef RLIMIT_RTTIME
4464 #ifdef RLIMIT_SBSIZE
4467 #ifdef RLIMIT_SIGPENDING
4468 RESCHECK(SIGPENDING);
4477 for (p = name; *
p; p++)
4483 for (p = name; *
p; p++)
4489 rb_bug(
"unexpected casetype");
4496 rlimit_type_by_hname(
const char *
name)
4498 return rlimit_resource_name2int(name, 0);
4502 rlimit_type_by_lname(
const char *
name)
4504 return rlimit_resource_name2int(name, 1);
4508 rlimit_resource_type(
VALUE rtype)
4514 switch (
TYPE(rtype)) {
4534 r = rlimit_type_by_hname(name);
4544 rlimit_resource_value(
VALUE rval)
4549 switch (
TYPE(rval)) {
4566 return NUM2RLIM(rval);
4569 #ifdef RLIM_INFINITY
4570 if (strcmp(name,
"INFINITY") == 0)
return RLIM_INFINITY;
4572 #ifdef RLIM_SAVED_MAX
4573 if (strcmp(name,
"SAVED_MAX") == 0)
return RLIM_SAVED_MAX;
4575 #ifdef RLIM_SAVED_CUR
4576 if (strcmp(name,
"SAVED_CUR") == 0)
return RLIM_SAVED_CUR;
4584 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
4612 if (
getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4615 return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
4618 #define proc_getrlimit rb_f_notimplement
4621 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
4676 VALUE resource, rlim_cur, rlim_max;
4681 rb_scan_args(argc, argv,
"21", &resource, &rlim_cur, &rlim_max);
4682 if (rlim_max ==
Qnil)
4683 rlim_max = rlim_cur;
4685 rlim.rlim_cur = rlimit_resource_value(rlim_cur);
4686 rlim.rlim_max = rlimit_resource_value(rlim_max);
4688 if (
setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4694 #define proc_setrlimit rb_f_notimplement
4702 if (under_uid_switch) {
4712 if (under_gid_switch) {
4728 #if defined(HAVE_PWD_H)
4731 # ifdef USE_GETPWNAM_R
4732 ,
char *getpw_buf,
size_t getpw_buf_len
4744 struct passwd *pwptr;
4745 #ifdef USE_GETPWNAM_R
4746 struct passwd pwbuf;
4747 if (getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr))
4750 pwptr = getpwnam(usrname);
4753 #ifndef USE_GETPWNAM_R
4758 uid = pwptr->pw_uid;
4759 #ifndef USE_GETPWNAM_R
4766 # ifdef p_uid_from_name
4776 #if defined(HAVE_GRP_H)
4779 # ifdef USE_GETGRNAM_R
4780 ,
char *getgr_buf,
size_t getgr_buf_len
4792 struct group *grptr;
4793 #ifdef USE_GETGRNAM_R
4795 if (getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr))
4798 grptr = getgrnam(grpname);
4801 #ifndef USE_GETGRNAM_R
4806 gid = grptr->gr_gid;
4807 #ifndef USE_GETGRNAM_R
4814 # ifdef p_gid_from_name
4824 #if defined HAVE_SETUID
4843 #define p_sys_setuid rb_f_notimplement
4847 #if defined HAVE_SETRUID
4866 #define p_sys_setruid rb_f_notimplement
4870 #if defined HAVE_SETEUID
4889 #define p_sys_seteuid rb_f_notimplement
4893 #if defined HAVE_SETREUID
4914 #define p_sys_setreuid rb_f_notimplement
4918 #if defined HAVE_SETRESUID
4939 #define p_sys_setresuid rb_f_notimplement
4962 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
4980 #if defined(HAVE_SETRESUID)
4982 #elif defined HAVE_SETREUID
4984 #elif defined HAVE_SETRUID
4986 #elif defined HAVE_SETUID
4999 #define proc_setuid rb_f_notimplement
5015 #ifdef BROKEN_SETREUID
5017 setreuid(rb_uid_t ruid, rb_uid_t euid)
5019 if (ruid != (rb_uid_t)-1 && ruid !=
getuid()) {
5020 if (euid == (rb_uid_t)-1) euid =
geteuid();
5021 if (
setuid(ruid) < 0)
return -1;
5023 if (euid != (rb_uid_t)-1 && euid !=
geteuid()) {
5024 if (
seteuid(euid) < 0)
return -1;
5054 #if defined(HAVE_SETRESUID)
5056 SAVED_USER_ID = uid;
5057 #elif defined(HAVE_SETUID)
5059 SAVED_USER_ID = uid;
5060 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5062 if (SAVED_USER_ID == uid) {
5067 if (setreuid(-1, SAVED_USER_ID) < 0)
rb_sys_fail(0);
5068 if (setreuid(SAVED_USER_ID, 0) < 0)
rb_sys_fail(0);
5071 SAVED_USER_ID = uid;
5077 SAVED_USER_ID = uid;
5083 SAVED_USER_ID = uid;
5085 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
5087 if (SAVED_USER_ID == uid) {
5101 SAVED_USER_ID = uid;
5108 SAVED_USER_ID = uid;
5116 #if defined(HAVE_SETRESUID)
5117 if (setresuid((
getuid() == uid)? (rb_uid_t)-1: uid,
5118 (
geteuid() == uid)? (rb_uid_t)-1: uid,
5119 (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0)
rb_sys_fail(0);
5120 SAVED_USER_ID = uid;
5121 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5122 if (SAVED_USER_ID == uid) {
5123 if (setreuid((
getuid() == uid)? (rb_uid_t)-1: uid,
5124 (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5127 else if (
getuid() != uid) {
5128 if (setreuid(uid, (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5130 SAVED_USER_ID = uid;
5134 SAVED_USER_ID = uid;
5138 if (setreuid(-1, SAVED_USER_ID) < 0)
rb_sys_fail(0);
5139 if (setreuid(SAVED_USER_ID, uid) < 0)
rb_sys_fail(0);
5140 SAVED_USER_ID = uid;
5143 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
5144 if (SAVED_USER_ID == uid) {
5151 SAVED_USER_ID = uid;
5155 SAVED_USER_ID = uid;
5159 else if (
getuid() == uid) {
5162 SAVED_USER_ID = uid;
5169 #elif defined HAVE_44BSD_SETUID
5173 SAVED_USER_ID = uid;
5179 #elif defined HAVE_SETEUID
5180 if (
getuid() == uid && SAVED_USER_ID == uid) {
5187 #elif defined HAVE_SETUID
5188 if (
getuid() == uid && SAVED_USER_ID == uid) {
5204 #if defined HAVE_SETGID
5223 #define p_sys_setgid rb_f_notimplement
5227 #if defined HAVE_SETRGID
5246 #define p_sys_setrgid rb_f_notimplement
5250 #if defined HAVE_SETEGID
5269 #define p_sys_setegid rb_f_notimplement
5273 #if defined HAVE_SETREGID
5294 #define p_sys_setregid rb_f_notimplement
5297 #if defined HAVE_SETRESGID
5318 #define p_sys_setresgid rb_f_notimplement
5322 #if defined HAVE_ISSETUGID
5347 #define p_sys_issetugid rb_f_notimplement
5370 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
5387 #if defined(HAVE_SETRESGID)
5389 #elif defined HAVE_SETREGID
5391 #elif defined HAVE_SETRGID
5393 #elif defined HAVE_SETGID
5406 #define proc_setgid rb_f_notimplement
5410 #if defined(HAVE_SETGROUPS) || defined(HAVE_GETGROUPS)
5431 static int _maxgroups = -1;
5433 get_sc_ngroups_max(
void)
5435 #ifdef _SC_NGROUPS_MAX
5436 return (
int)sysconf(_SC_NGROUPS_MAX);
5437 #elif defined(NGROUPS_MAX)
5438 return (
int)NGROUPS_MAX;
5446 if (_maxgroups < 0) {
5447 _maxgroups = get_sc_ngroups_max();
5458 #ifdef HAVE_GETGROUPS
5477 ngroups = getgroups(0,
NULL);
5481 groups =
ALLOCA_N(rb_gid_t, ngroups);
5483 ngroups = getgroups(ngroups, groups);
5488 for (i = 0; i < ngroups; i++)
5494 #define proc_getgroups rb_f_notimplement
5498 #ifdef HAVE_SETGROUPS
5522 if (ngroups > maxgroups())
5525 groups =
ALLOCA_N(rb_gid_t, ngroups);
5527 for (i = 0; i < ngroups; i++) {
5533 if (setgroups(ngroups, groups) == -1)
5539 #define proc_setgroups rb_f_notimplement
5543 #ifdef HAVE_INITGROUPS
5571 #define proc_initgroups rb_f_notimplement
5574 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
5591 #define proc_getmaxgroups rb_f_notimplement
5594 #ifdef HAVE_SETGROUPS
5607 int ngroups_max = get_sc_ngroups_max();
5615 if (ngroups_max > 0 && ngroups > ngroups_max)
5616 ngroups = ngroups_max;
5618 _maxgroups = ngroups;
5623 #define proc_setmaxgroups rb_f_notimplement
5626 #if defined(HAVE_DAEMON) || (defined(HAVE_FORK) && defined(HAVE_SETSID))
5627 static int rb_daemon(
int nochdir,
int noclose);
5646 VALUE nochdir, noclose;
5653 n = rb_daemon(
RTEST(nochdir),
RTEST(noclose));
5659 rb_daemon(
int nochdir,
int noclose)
5664 err = daemon(nochdir, noclose);
5670 #define fork_daemon() \
5671 switch (rb_fork_ruby(NULL)) { \
5672 case -1: return -1; \
5673 case 0: rb_thread_atfork(); break; \
5674 default: _exit(EXIT_SUCCESS); \
5679 if (setsid() < 0)
return -1;
5687 if (!noclose && (n =
rb_cloexec_open(
"/dev/null", O_RDWR, 0)) != -1) {
5699 #define proc_daemon rb_f_notimplement
5714 #ifdef BROKEN_SETREGID
5716 setregid(rb_gid_t rgid, rb_gid_t egid)
5718 if (rgid != (rb_gid_t)-1 && rgid !=
getgid()) {
5719 if (egid == (rb_gid_t)-1) egid =
getegid();
5720 if (
setgid(rgid) < 0)
return -1;
5722 if (egid != (rb_gid_t)-1 && egid !=
getegid()) {
5723 if (
setegid(egid) < 0)
return -1;
5753 #if defined(HAVE_SETRESGID)
5755 SAVED_GROUP_ID = gid;
5756 #elif defined HAVE_SETGID
5758 SAVED_GROUP_ID = gid;
5759 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5761 if (SAVED_GROUP_ID == gid) {
5766 if (setregid(-1, SAVED_GROUP_ID) < 0)
rb_sys_fail(0);
5767 if (setregid(SAVED_GROUP_ID, 0) < 0)
rb_sys_fail(0);
5770 SAVED_GROUP_ID = gid;
5776 SAVED_GROUP_ID = gid;
5782 SAVED_GROUP_ID = gid;
5784 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
5786 if (SAVED_GROUP_ID == gid) {
5801 SAVED_GROUP_ID = gid;
5808 SAVED_GROUP_ID = gid;
5815 #if defined(HAVE_SETRESGID)
5816 if (setresgid((
getgid() == gid)? (rb_gid_t)-1: gid,
5817 (
getegid() == gid)? (rb_gid_t)-1: gid,
5818 (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0)
rb_sys_fail(0);
5819 SAVED_GROUP_ID = gid;
5820 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
5821 if (SAVED_GROUP_ID == gid) {
5822 if (setregid((
getgid() == gid)? (rb_uid_t)-1: gid,
5823 (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5826 else if (
getgid() != gid) {
5827 if (setregid(gid, (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
5829 SAVED_GROUP_ID = gid;
5833 SAVED_GROUP_ID = gid;
5837 if (setregid(-1, SAVED_GROUP_ID) < 0)
rb_sys_fail(0);
5838 if (setregid(SAVED_GROUP_ID, gid) < 0)
rb_sys_fail(0);
5839 SAVED_GROUP_ID = gid;
5842 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
5843 if (SAVED_GROUP_ID == gid) {
5850 SAVED_GROUP_ID = gid;
5854 SAVED_GROUP_ID = gid;
5858 else if (
getgid() == gid) {
5861 SAVED_GROUP_ID = gid;
5868 #elif defined HAVE_44BSD_SETGID
5872 SAVED_GROUP_ID = gid;
5878 #elif defined HAVE_SETEGID
5879 if (
getgid() == gid && SAVED_GROUP_ID == gid) {
5886 #elif defined HAVE_SETGID
5887 if (
getgid() == gid && SAVED_GROUP_ID == gid) {
5921 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
5923 proc_seteuid(rb_uid_t uid)
5925 #if defined(HAVE_SETRESUID)
5927 #elif defined HAVE_SETREUID
5929 #elif defined HAVE_SETEUID
5931 #elif defined HAVE_SETUID
5944 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
5962 #define proc_seteuid_m rb_f_notimplement
5968 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
5974 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
5978 #if defined(HAVE_SETRESUID)
5981 SAVED_USER_ID = euid;
5986 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
5991 SAVED_USER_ID = euid;
5993 #elif defined HAVE_SETEUID
5995 #elif defined HAVE_SETUID
6048 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
6060 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6067 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6071 #if defined(HAVE_SETRESGID)
6073 #elif defined HAVE_SETREGID
6075 #elif defined HAVE_SETEGID
6077 #elif defined HAVE_SETGID
6091 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
6092 #define proc_setegid_m proc_setegid
6094 #define proc_setegid_m rb_f_notimplement
6100 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6106 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6110 #if defined(HAVE_SETRESGID)
6113 SAVED_GROUP_ID = egid;
6118 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6123 SAVED_GROUP_ID = egid;
6125 #elif defined HAVE_SETEGID
6127 #elif defined HAVE_SETGID
6172 #if defined(HAVE_SETRESUID)
6174 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6198 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6205 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
6209 #if defined(HAVE_SETRESUID)
6210 if (setresuid(euid, uid, uid) < 0)
rb_sys_fail(0);
6211 SAVED_USER_ID = uid;
6212 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6214 SAVED_USER_ID = uid;
6234 #if defined(HAVE_SETRESGID)
6236 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6260 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6267 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
6271 #if defined(HAVE_SETRESGID)
6272 if (setresgid(egid, gid, gid) < 0)
rb_sys_fail(0);
6273 SAVED_GROUP_ID = gid;
6274 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
6276 SAVED_GROUP_ID = gid;
6297 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
6305 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
6309 under_uid_switch = 0;
6341 under_uid_switch = 1;
6348 else if (euid != SAVED_USER_ID) {
6349 proc_seteuid(SAVED_USER_ID);
6351 under_uid_switch = 1;
6369 under_uid_switch = 0;
6389 under_uid_switch = 1;
6413 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
6420 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
6424 under_gid_switch = 0;
6456 under_gid_switch = 1;
6463 else if (egid != SAVED_GROUP_ID) {
6464 proc_setegid(obj,
GIDT2NUM(SAVED_GROUP_ID));
6466 under_gid_switch = 1;
6484 under_gid_switch = 0;
6504 under_gid_switch = 1;
6514 #if defined(HAVE_TIMES)
6530 const double hertz =
6531 #ifdef HAVE__SC_CLK_TCK
6532 (double)sysconf(_SC_CLK_TCK);
6554 #define rb_proc_times rb_f_notimplement
6649 #ifdef HAVE_GETPRIORITY
6660 #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
6662 VALUE inf = RLIM2NUM(RLIM_INFINITY);
6663 #ifdef RLIM_SAVED_MAX
6665 VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
6672 #ifdef RLIM_SAVED_CUR
6674 VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
6715 #ifdef RLIMIT_MEMLOCK
6722 #ifdef RLIMIT_MSGQUEUE
6737 #ifdef RLIMIT_NOFILE
6760 #ifdef RLIMIT_RTPRIO
6767 #ifdef RLIMIT_RTTIME
6775 #ifdef RLIMIT_SBSIZE
6780 #ifdef RLIMIT_SIGPENDING
6815 #if defined(HAVE_TIMES) || defined(_WIN32)
6843 #ifdef p_uid_from_name
6846 #ifdef p_gid_from_name
static VALUE p_uid_have_saved_id(void)
static int run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
struct timeval rb_time_interval(VALUE num)
void rb_syswait(rb_pid_t pid)
void rb_thread_schedule(void)
static VALUE rb_cProcessStatus
#define RUBY_VM_CHECK_INTS(th)
#define redirect_close(fd)
static void before_exec_async_signal_safe(void)
RUBY_EXTERN VALUE rb_cData
static VALUE proc_getgid(VALUE obj)
void rb_thread_atfork(void)
static void check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
static int run_exec_open(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
VALUE rb_ary_new4(long n, const VALUE *elts)
static VALUE rb_check_argv(int argc, VALUE *argv)
VALUE rb_ary_entry(VALUE ary, long offset)
void rb_bug(const char *fmt,...)
static VALUE check_exec_fds(struct rb_execarg *eargp)
static void rb_check_exec_options(VALUE opthash, VALUE execarg_obj)
size_t strlen(const char *)
void rb_update_max_fd(int fd)
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
#define redirect_open(pathname, flags, perm)
static VALUE save_env_i(VALUE i, VALUE ary, int argc, VALUE *argv)
rb_pid_t rb_spawn_err(int argc, VALUE *argv, char *errmsg, size_t errmsg_buflen)
void ruby_finalize(void)
Runs the VM finalization processes.
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
static VALUE hide_obj(VALUE obj)
static VALUE p_uid_exchange(VALUE obj)
static void after_exec(void)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
static VALUE rb_f_system(int argc, VALUE *argv)
int rb_io_modestr_oflags(const char *modestr)
static int under_gid_switch
static VALUE pst_bitand(VALUE st1, VALUE st2)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
static VALUE p_uid_exchangeable(void)
static VALUE pst_to_s(VALUE st)
int rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
static VALUE detach_process_pid(VALUE thread)
int st_insert(st_table *, st_data_t, st_data_t)
static long run_exec_dup2_tmpbuf_size(long n)
struct rb_execarg::@87::@89 cmd
int rb_env_path_tainted(void)
#define TypedData_Get_Struct(obj, type, data_type, sval)
unsigned unsetenv_others_given
static int check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
static int check_exec_fds_1(struct rb_execarg *eargp, VALUE h, int maxhint, VALUE ary)
static rb_gid_t SAVED_GROUP_ID
SOCKET rb_w32_get_osfhandle(int)
static VALUE p_uid_sw_ensure(VALUE obj)
int execl(const char *path, const char *arg0,...)
static VALUE proc_waitall(void)
static int run_exec_dup2_child(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
VALUE rb_struct_new(VALUE,...)
int rb_proc_exec(const char *str)
VALUE rb_ary_push(VALUE ary, VALUE item)
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
int rb_proc_exec_n(int argc, VALUE *argv, const char *prog)
int rb_thread_alone(void)
rb_pid_t rb_w32_aspawn_flags(int, const char *, char *const *, DWORD)
static VALUE p_gid_have_saved_id(void)
static VALUE p_gid_exchangeable(void)
rb_pid_t rb_fork_ruby(int *status)
void rb_str_set_len(VALUE, long)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_raise(VALUE exc, const char *fmt,...)
static int run_exec_dup2(VALUE ary, VALUE tmpbuf, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
rb_pid_t rb_waitpid(rb_pid_t pid, int *st, int flags)
static void check_gid_switch(void)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
int rb_exec(const struct rb_exec_arg *e)
static VALUE p_gid_change_privilege(VALUE obj, VALUE id)
VALUE rb_ary_new3(long n,...)
static VALUE check_exec_redirect_fd(VALUE v, int iskey)
VALUE rb_f_exit(int argc, VALUE *argv)
void rb_gc_mark(VALUE ptr)
static VALUE pst_equal(VALUE st1, VALUE st2)
int setrlimit(int resource, const struct rlimit *rlp)
static int rb_exec_without_timer_thread(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
static void rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VALUE execarg_obj)
static VALUE pst_success_p(VALUE st)
static VALUE proc_wait(int argc, VALUE *argv)
static void * rb_waitpid_blocking(void *data)
VALUE rb_block_call(VALUE, ID, int, VALUE *, VALUE(*)(ANYARGS), VALUE)
static const rb_data_type_t exec_arg_data_type
int rb_exec_err(const struct rb_exec_arg *e, char *errmsg, size_t errmsg_buflen)
static VALUE pst_wtermsig(VALUE st)
void rb_undef_method(VALUE klass, const char *name)
#define GetOpenFile(obj, fp)
void rb_thread_start_timer_thread(void)
static VALUE pst_wstopsig(VALUE st)
VALUE rb_thread_local_aref(VALUE, ID)
VALUE rb_str_buf_cat(VALUE, const char *, long)
static VALUE pst_wifsignaled(VALUE st)
void rb_exc_raise(VALUE mesg)
unsigned unsetenv_others_do
static rb_pid_t rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
#define preserving_errno(stmts)
#define RB_TYPE_P(obj, type)
VALUE rb_last_status_get(void)
#define MEMZERO(p, type, n)
static void before_exec_non_async_signal_safe(void)
void rb_execarg_fixup(VALUE execarg_obj)
static VALUE proc_wait2(int argc, VALUE *argv)
static rb_gid_t rb_setegid_core(rb_gid_t egid)
void rb_thread_sleep(int)
static void mark_exec_arg(void *ptr)
VALUE rb_marshal_dump(VALUE, VALUE)
VALUE rb_class_new_instance(int, VALUE *, VALUE)
int execv(const char *path, char *const argv[])
static VALUE rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
int rb_block_given_p(void)
int getrlimit(int resource, struct rlimit *rlp)
RUBY_EXTERN VALUE rb_cObject
static VALUE rb_f_spawn(int argc, VALUE *argv)
static rb_uid_t SAVED_USER_ID
#define proc_getmaxgroups
static VALUE proc_detach(VALUE obj, VALUE pid)
const char * ruby_signal_name(int)
rb_pid_t rb_w32_spawn(int, const char *, const char *)
VALUE rb_io_check_io(VALUE io)
int rb_run_exec_options_err(const struct rb_exec_arg *e, struct rb_exec_arg *s, char *errmsg, size_t errmsg_buflen)
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_str_buf_cat2(VALUE, const char *)
static void after_exec_async_signal_safe(void)
static VALUE pst_wifexited(VALUE st)
VALUE rb_iv_get(VALUE, const char *)
static void after_exec_non_async_signal_safe(void)
void rb_thread_stop_timer_thread(int close_anyway)
int st_delete(st_table *, st_data_t *, st_data_t *)
static int proc_exec_v(char **argv, const char *prog)
rb_pid_t rb_fork_async_signal_safe(int *status, int(*chfunc)(void *, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen)
void rb_define_const(VALUE, const char *, VALUE)
void rb_ary_store(VALUE ary, long idx, VALUE val)
static VALUE pst_rshift(VALUE st1, VALUE st2)
void rb_sys_fail_str(VALUE mesg)
static VALUE rb_check_exec_env(VALUE hash)
mode_t umask(mode_t mask)
#define ALLOCA_N(type, n)
void ruby_stop(int ex)
Calls ruby_cleanup() and exits the process.
VALUE rb_obj_alloc(VALUE)
static size_t memsize_exec_arg(const void *ptr)
static int save_redirect_fd(int fd, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
static VALUE proc_geteuid(VALUE obj)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
int rb_exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
static void free_exec_arg(void *ptr)
static void before_exec(void)
VALUE rb_const_get(VALUE, ID)
VALUE rb_thread_local_aset(VALUE, ID, VALUE)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
static rb_pid_t rb_spawn_internal(int argc, VALUE *argv, char *errmsg, size_t errmsg_buflen)
VALUE rb_io_fdopen(int, int, const char *)
unsigned close_others_given
static int compare_posix_sh(const void *key, const void *el)
static VALUE p_uid_switch(VALUE obj)
static VALUE pst_wcoredump(VALUE st)
VALUE rb_sprintf(const char *format,...)
static int chfunc(void *data, char *errbuf, size_t errbuf_len)
static int under_uid_switch
static int proc_exec_cmd(const char *prog, VALUE argv_str, VALUE envp_str)
VALUE rb_iv_set(VALUE, const char *, VALUE)
static void save_env(struct rb_execarg *sargp)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
static VALUE pst_pid(VALUE st)
char * dln_find_exe_r(const char *, const char *, char *, size_t)
static void pst_message(VALUE str, rb_pid_t pid, int status)
VALUE rb_check_hash_type(VALUE hash)
unsigned char buf[MIME_BUF_SIZE]
VALUE rb_assoc_new(VALUE car, VALUE cdr)
VALUE tied_io_for_writing
static VALUE detach_process_watcher(void *arg)
unsigned new_pgroup_given
static VALUE p_gid_switch(VALUE obj)
#define CHILD_ERRMSG_BUFLEN
const char * rb_class2name(VALUE)
char * strchr(char *, char)
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
#define proc_setmaxgroups
VALUE rb_str_new_cstr(const char *)
static int check_exec_options_i_extract(st_data_t st_key, st_data_t st_val, st_data_t arg)
#define RARRAY_LENINT(ary)
st_table * st_init_numtable(void)
void rb_sys_fail(const char *mesg)
static int intcmp(const void *a, const void *b)
void rb_jump_tag(int tag)
void ruby_error_print(void)
static void security(const char *str)
union rb_execarg::@87 invoke
VALUE rb_define_module_under(VALUE outer, const char *name)
#define StringValueCStr(v)
static int check_exec_options_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
static rb_uid_t rb_seteuid_core(rb_uid_t euid)
static VALUE p_gid_grant_privilege(VALUE obj, VALUE id)
VALUE rb_f_abort(int argc, VALUE *argv)
void rb_thread_wait_for(struct timeval)
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
#define try_with_sh(prog, argv, envp)
static st_table * pid_tbl
VALUE rb_equal(VALUE, VALUE)
RUBY_EXTERN VALUE rb_stderr
#define rb_check_arity(argc, min, max)
#define UNLIMITED_ARGUMENTS
sighandler_t signal(int signum, sighandler_t handler)
void rb_last_status_set(int status, rb_pid_t pid)
int utime(const char *filename, const struct utimbuf *times)
static VALUE pst_wifstopped(VALUE st)
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
#define redirect_dup2(oldfd, newfd)
static VALUE p_gid_exchange(VALUE obj)
void rb_set_errinfo(VALUE err)
static VALUE p_uid_grant_privilege(VALUE obj, VALUE id)
VALUE rb_execarg_init(int argc, VALUE *argv, int accept_shell, VALUE execarg_obj)
static VALUE pst_to_i(VALUE st)
VALUE rb_check_array_type(VALUE ary)
static void check_uid_switch(void)
VALUE rb_exec_arg_init(int argc, VALUE *argv, int accept_shell, struct rb_exec_arg *e)
VALUE rb_str_catf(VALUE str, const char *format,...)
void rb_thread_reset_timer_thread(void)
VALUE rb_f_kill(int, VALUE *)
VALUE rb_check_string_type(VALUE)
static VALUE proc_getegid(VALUE obj)
static VALUE get_ppid(void)
#define ARGVSTR2ARGV(argv_str)
static int exit_status_code(VALUE status)
VALUE rb_execarg_new(int argc, VALUE *argv, int accept_shell)
static int waitall_each(rb_pid_t pid, int status, VALUE ary)
static int fill_envp_buf_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
static VALUE p_gid_sw_ensure(VALUE obj)
static VALUE pst_inspect(VALUE st)
VALUE rb_marshal_load(VALUE)
#define TypedData_Make_Struct(klass, type, data_type, sval)
VALUE rb_ary_dup(VALUE ary)
VALUE rb_io_puts(int, VALUE *, VALUE)
void rb_notimplement(void)
void rb_last_status_clear(void)
static unsigned int hash(const char *str, unsigned int len)
#define SafeStringValue(v)
VALUE rb_ary_join(VALUE ary, VALUE sep)
static VALUE rb_f_sleep(int argc, VALUE *argv)
static int proc_exec_sh(const char *str, VALUE envp_str)
static VALUE p_uid_change_privilege(VALUE obj, VALUE id)
static VALUE rb_exec_getargs(int *argc_p, VALUE **argv_p, int accept_shell, VALUE *env_ret, VALUE *opthash_ret)
const char * rb_id2name(ID id)
#define StringValuePtr(v)
#define redirect_dup(oldfd)
static char fbuf[MAXPATHLEN]
RUBY_EXTERN int dup2(int, int)
int rb_exec_arg_addopt(struct rb_exec_arg *e, VALUE key, VALUE val)
VALUE rb_str_new_frozen(VALUE)
#define STRCASECMP(s1, s2)
#define CONST_ID(var, str)
static VALUE proc_getuid(VALUE obj)
VALUE rb_struct_define(const char *,...)
int rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
VALUE rb_define_module(const char *name)
rb_pid_t rb_spawn(int argc, VALUE *argv)
static VALUE check_exec_redirect1(VALUE ary, VALUE key, VALUE param)
#define ARGVSTR2ARGC(argv_str)
VALUE rb_str_buf_new(long)
VALUE rb_detach_process(rb_pid_t pid)
void rb_exec_arg_fixup(struct rb_exec_arg *e)
static VALUE get_pid(void)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
struct rb_execarg::@87::@88 sh
VALUE rb_thread_create(VALUE(*)(ANYARGS), void *)
VALUE rb_thread_blocking_region(rb_blocking_function_t *func, void *data1, rb_unblock_function_t *ubf, void *data2)
static rb_thread_t * GET_THREAD(void)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
void ruby_setenv(const char *name, const char *value)
VALUE rb_str_new2(const char *)
void rb_warn(const char *fmt,...)
static VALUE pst_wexitstatus(VALUE st)
static int intrcmp(const void *a, const void *b)
rb_pid_t waitpid(rb_pid_t, int *, int)
VALUE rb_attr_get(VALUE, ID)
static int wait_each(rb_pid_t pid, int status, struct wait_data *data)
char * strrchr(const char *, const char)
void rb_thread_sleep_forever(void)
VALUE rb_str_new(const char *, long)
VALUE rb_f_exec(int argc, VALUE *argv)