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) 71 #ifdef HAVE_SYS_TIME_H 74 #ifdef HAVE_SYS_TIMES_H 75 #include <sys/times.h> 86 # include <mach/mach_time.h> 92 #define open rb_w32_uopen 95 #if defined(HAVE_TIMES) || defined(_WIN32) 96 static VALUE rb_cProcessTms;
100 #define WIFEXITED(w) (((w) & 0xff) == 0) 103 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f)) 106 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f) 109 #define WEXITSTATUS(w) (((w) >> 8) & 0xff) 112 #define WTERMSIG(w) ((w) & 0x7f) 115 #define WSTOPSIG WEXITSTATUS 118 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) 119 #define HAVE_44BSD_SETUID 1 120 #define HAVE_44BSD_SETGID 1 128 #ifdef BROKEN_SETREUID 129 #define setreuid ruby_setreuid 130 int setreuid(rb_uid_t ruid, rb_uid_t euid);
132 #ifdef BROKEN_SETREGID 133 #define setregid ruby_setregid 134 int setregid(rb_gid_t rgid, rb_gid_t egid);
137 #if defined(HAVE_44BSD_SETUID) || defined(__APPLE__) 138 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID) 139 #define OBSOLETE_SETREUID 1 141 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID) 142 #define OBSOLETE_SETREGID 1 146 #define preserving_errno(stmts) \ 147 do {int saved_errno = errno; stmts; errno = saved_errno;} while (0) 153 #define p_uid_from_name p_uid_from_name 154 #define p_gid_from_name p_gid_from_name 157 #if defined(HAVE_PWD_H) 158 # if defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX) 159 # define USE_GETPWNAM_R 1 160 # define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX) 161 # define GETPW_R_SIZE_DEFAULT 0x1000 162 # define GETPW_R_SIZE_LIMIT 0x10000 164 # ifdef USE_GETPWNAM_R 165 # define PREPARE_GETPWNAM \ 167 # define FINISH_GETPWNAM \ 168 ALLOCV_END(getpw_buf) 169 # define OBJ2UID1(id) obj2uid((id), &getpw_buf) 170 # define OBJ2UID(id) obj2uid0(id) 171 static rb_uid_t obj2uid(
VALUE id,
VALUE *getpw_buf);
172 static inline rb_uid_t
182 # define PREPARE_GETPWNAM 183 # define FINISH_GETPWNAM 184 # define OBJ2UID(id) obj2uid((id)) 185 static rb_uid_t obj2uid(
VALUE id);
188 # define PREPARE_GETPWNAM 189 # define FINISH_GETPWNAM 190 # define OBJ2UID(id) NUM2UIDT(id) 191 # ifdef p_uid_from_name 192 # undef p_uid_from_name 193 # define p_uid_from_name rb_f_notimplement 197 #if defined(HAVE_GRP_H) 198 # if defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX) 199 # define USE_GETGRNAM_R 200 # define GETGR_R_SIZE_INIT sysconf(_SC_GETGR_R_SIZE_MAX) 201 # define GETGR_R_SIZE_DEFAULT 0x1000 202 # define GETGR_R_SIZE_LIMIT 0x10000 204 # ifdef USE_GETGRNAM_R 205 # define PREPARE_GETGRNAM \ 207 # define FINISH_GETGRNAM \ 208 ALLOCV_END(getgr_buf) 209 # define OBJ2GID1(id) obj2gid((id), &getgr_buf) 210 # define OBJ2GID(id) obj2gid0(id) 211 static rb_gid_t obj2gid(
VALUE id,
VALUE *getgr_buf);
212 static inline rb_gid_t
221 static rb_gid_t obj2gid(
VALUE id,
VALUE *getgr_buf);
223 # define PREPARE_GETGRNAM 224 # define FINISH_GETGRNAM 225 # define OBJ2GID(id) obj2gid((id)) 226 static rb_gid_t obj2gid(
VALUE id);
229 # define PREPARE_GETGRNAM 230 # define FINISH_GETGRNAM 231 # define OBJ2GID(id) NUM2GIDT(id) 232 # ifdef p_gid_from_name 233 # undef p_gid_from_name 234 # define p_gid_from_name rb_f_notimplement 238 #if SIZEOF_CLOCK_T == SIZEOF_INT 240 #elif SIZEOF_CLOCK_T == SIZEOF_LONG 242 #elif defined(HAVE_LONG_LONG) && SIZEOF_CLOCK_T == SIZEOF_LONG_LONG 360 #define PST2INT(st) NUM2INT(pst_to_i(st)) 387 rb_str_catf(str,
" stopped SIG%s (signal %d)", signame, stopsig);
397 rb_str_catf(str,
" SIG%s (signal %d)", signame, termsig);
407 if (WCOREDUMP(status)) {
484 if (st1 == st2)
return Qtrue;
695 if (WCOREDUMP(status))
704 #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4) 743 struct waitpid_arg *arg = data;
746 #if defined NO_WAITPID 748 #elif defined HAVE_WAITPID 751 result = wait4(arg->pid, arg->st, arg->flags,
NULL);
762 struct waitpid_arg arg;
771 if (
errno == EINTR) {
780 if (pid == (rb_pid_t)-1) {
782 data.
pid = (rb_pid_t)-1;
785 if (data.status != -1) {
804 if (
errno == EINTR) {
985 if (
errno == EINTR) {
1017 rb_pid_t cpid,
pid = (rb_pid_t)(
VALUE)arg;
1093 static RETSIGTYPE (*saved_sigpipe_handler)(int) = 0;
1098 sig_do_nothing(
int sig)
1114 saved_sigpipe_handler =
signal(SIGPIPE, sig_do_nothing);
1145 signal(SIGPIPE, saved_sigpipe_handler);
1165 #define before_fork() before_exec() 1166 #define after_fork() (rb_threadptr_pending_interrupt_clear(GET_THREAD()), after_exec()) 1180 #if defined(HAVE_FORK) && !defined(__native_client__) 1183 #define try_with_sh(prog, argv, envp) ((saved_errno == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0) 1185 exec_with_sh(
const char *prog,
char **
argv,
char **envp)
1187 *
argv = (
char *)prog;
1188 *--
argv = (
char *)
"sh";
1190 execve(
"/bin/sh",
argv, envp);
1196 #define try_with_sh(prog, argv, envp) (void)0 1203 #ifdef __native_client__ 1209 # if defined(__EMX__) || defined(OS2) 1210 char **new_argv =
NULL;
1220 # if defined(__EMX__) || defined(OS2) 1222 # define COMMAND "cmd.exe" 1229 for (n = 0;
argv[n]; n++)
1231 new_argv =
ALLOC_N(
char*, n + 2);
1233 new_argv[n + 1] =
argv[n];
1235 for (p = new_argv[1]; *p !=
'\0'; p++)
1238 new_argv[0] = COMMAND;
1250 execve(prog,
argv, envp);
1254 # if defined(__EMX__) || defined(OS2) 1287 #define ARGV_COUNT(n) ((n)+1) 1288 #define ARGV_SIZE(n) (sizeof(char*) * ARGV_COUNT(n)) 1289 #define ALLOC_ARGV(n, v) ALLOCV_N(char*, (v), ARGV_COUNT(n)) 1297 for (i=0; i<
argc; i++) {
1316 #ifdef __native_client__ 1323 while (*s ==
' ' || *s ==
'\t' || *s ==
'\n')
1335 #if defined(__CYGWIN32__) || defined(__EMX__) 1341 execl(shell,
"sh",
"-c", str, (
char *)
NULL);
1349 execle(
"/bin/sh",
"sh",
"-c", str, (
char *)
NULL, (
char **)
RSTRING_PTR(envp_str));
1351 execl(
"/bin/sh",
"sh",
"-c", str, (
char *)
NULL);
1412 # define DEFAULT_PROCESS_ENCODING rb_utf8_encoding() 1414 #ifdef DEFAULT_PROCESS_ENCODING 1415 # define EXPORT_STR(str) rb_str_export_to_enc((str), DEFAULT_PROCESS_ENCODING) 1416 # define EXPORT_DUP(str) export_dup(str) 1418 export_dup(
VALUE str)
1425 # define EXPORT_STR(str) (str) 1426 # define EXPORT_DUP(str) rb_str_dup(str) 1429 #if !defined(HAVE_FORK) && defined(HAVE_SPAWNV) 1430 # define USE_SPAWNV 1 1432 # define USE_SPAWNV 0 1435 # define P_NOWAIT _P_NOWAIT 1440 #define proc_spawn_cmd_internal(argv, prog) rb_w32_uaspawn(P_NOWAIT, (prog), (argv)) 1443 proc_spawn_cmd_internal(
char **
argv,
char *prog)
1457 if (status == -1 &&
errno == ENOEXEC) {
1458 *
argv = (
char *)prog;
1459 *--
argv = (
char *)
"sh";
1460 status = spawnv(
P_NOWAIT,
"/bin/sh", (
const char **)
argv);
1462 if (status == -1)
errno = ENOEXEC;
1477 flags = CREATE_NEW_PROCESS_GROUP;
1488 #define proc_spawn_sh(str) rb_w32_uspawn(P_NOWAIT, (str), 0) 1491 proc_spawn_sh(
char *str)
1498 status = spawnl(
P_NOWAIT, (shell ? shell :
"/bin/sh"),
"sh",
"-c", str, (
char*)
NULL);
1546 else if (fd >= 3 && iskey) {
1579 VALUE path, flags, perm;
1647 flags =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
1665 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 1666 static int rlimit_type_by_lname(
const char *
name);
1675 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 1715 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 1716 if (strncmp(
"rlimit_",
rb_id2name(
id), 7) == 0 &&
1717 (rtype = rlimit_type_by_lname(
rb_id2name(
id)+7)) != -1) {
1719 VALUE tmp, softlim, hardlim;
1744 if (
id ==
rb_intern(
"unsetenv_others")) {
1768 else if (
id ==
rb_intern(
"close_others")) {
1799 "uid option is unimplemented on this machine");
1814 "gid option is unimplemented on this machine");
1864 VALUE execarg_obj = args[0];
1866 VALUE nonopts = args[1];
1934 if (oldfd != lastfd) {
1965 args[0] = execarg_obj;
2010 const char *
name = 0;
2027 for (i = 0; i <
argc; i++) {
2044 *opthash_ret =
hash;
2059 prog = (*argv_p)[0];
2060 if (accept_shell && *argc_p == 1) {
2078 int ret = strncmp(word->
ptr, el, word->
len);
2079 if (!ret && ((
const char *)el)[word->
len]) ret = -1;
2092 if (!
NIL_P(opthash)) {
2103 eargp->
invoke.
sh.shell_script = prog;
2109 static const char posix_sh_cmds[][9] = {
2168 if (*p ==
' ' || *p ==
'\t') {
2169 if (first.
ptr && !first.
len) first.
len = p - first.
ptr;
2172 if (!first.
ptr) first.
ptr = p;
2174 if (!has_meta &&
strchr(
"*?{}[]<>()~&|\\$;'`\"\n#", *p))
2180 else if (*p ==
'/') {
2187 if (!has_meta && first.
ptr) {
2188 if (!first.
len) first.
len = p - first.
ptr;
2189 if (first.
len > 0 && first.
len <=
sizeof(posix_sh_cmds[0]) &&
2202 while (*p ==
' ' || *p ==
'\t')
2206 while (*p && *p !=
' ' && *p !=
'\t')
2219 const char *abspath;
2232 for (i = 0; i <
argc; i++) {
2235 #ifdef DEFAULT_PROCESS_ENCODING 2245 const char *p, *ep, *null=
NULL;
2329 int unsetenv_others;
2345 if (unsetenv_others || envopts !=
Qfalse) {
2348 if (unsetenv_others) {
2485 VALUE execarg_obj, fail_str;
2487 #define CHILD_ERRMSG_BUFLEN 80 2495 #if defined(__APPLE__) || defined(__HAIKU__) 2507 #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0) 2510 #if defined(DEBUG_REDIRECT) 2515 ttyprintf(
const char *fmt, ...)
2521 tty = fopen(
"con",
"w");
2523 tty = fopen(
"/dev/tty",
"w");
2529 vfprintf(tty, fmt, ap);
2540 ttyprintf(
"dup(%d) => %d\n", oldfd, ret);
2548 ret =
dup2(oldfd, newfd);
2549 ttyprintf(
"dup2(%d, %d)\n", oldfd, newfd);
2558 ttyprintf(
"close(%d)\n", fd);
2566 ret = open(pathname, flags, perm);
2567 ttyprintf(
"open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
2572 #define redirect_dup(oldfd) dup(oldfd) 2573 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd)) 2574 #define redirect_close(fd) close(fd) 2575 #define redirect_open(pathname, flags, perm) open((pathname), (flags), (perm)) 2584 if (save_fd == -1) {
2613 return *(
int*)a - *(
int*)b;
2619 return *(
int*)b - *(
int*)a;
2648 for (i = 0; i < n; i++) {
2662 for (i = 0; i < n; i++) {
2669 while (pairs < found && (found-1)->
oldfd ==
newfd)
2671 while (found < pairs+n && found->
oldfd ==
newfd) {
2680 for (i = 0; i < n; i++) {
2682 while (j != -1 && pairs[j].
oldfd != -1 && pairs[j].
num_newer == 0) {
2691 pairs[j].
oldfd = -1;
2699 for (i = 0; i < n; i++) {
2701 if (pairs[i].
oldfd == -1)
2705 int fd = pairs[i].
oldfd;
2706 ret =
fcntl(fd, F_GETFD);
2708 ERRMSG(
"fcntl(F_GETFD)");
2711 if (ret & FD_CLOEXEC) {
2713 ret =
fcntl(fd, F_SETFD, ret);
2715 ERRMSG(
"fcntl(F_SETFD)");
2720 pairs[i].
oldfd = -1;
2723 if (extra_fd == -1) {
2725 if (extra_fd == -1) {
2739 pairs[i].
oldfd = extra_fd;
2749 pairs[j].
oldfd = -1;
2753 if (extra_fd != -1) {
2866 run_exec_pgroup(
const struct rb_execarg *eargp,
struct rb_execarg *sargp,
char *errmsg,
size_t errmsg_buflen)
2890 ret = setpgid(getpid(), pgroup);
2891 if (ret == -1)
ERRMSG(
"setpgid");
2896 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM) 2899 run_exec_rlimit(
VALUE ary,
struct rb_execarg *sargp,
char *errmsg,
size_t errmsg_buflen)
2913 RLIM2NUM(rlim.rlim_cur),
2914 RLIM2NUM(rlim.rlim_max)));
2932 #if !defined(HAVE_FORK) 2961 #define chdir(p) rb_w32_uchdir(p) 2978 if (run_exec_pgroup(eargp, sargp, errmsg, errmsg_buflen) == -1)
2983 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM) 2986 if (run_exec_rlimit(obj, sargp, errmsg, errmsg_buflen) == -1)
2991 #if !defined(HAVE_FORK) 3031 rb_warn(
"cannot close fd before spawn");
3115 #if !defined(HAVE_FORK) 3116 struct rb_execarg sarg, *
const sargp = &sarg;
3131 char *abspath =
NULL;
3136 #if !defined(HAVE_FORK) 3164 #if !defined FD_CLOEXEC && !defined HAVE_SPAWNV 3165 char errmsg[80] = {
'\0' };
3169 fprintf(stderr,
"%s\n", errmsg);
3172 fprintf(stderr,
"%s:%d: command not found: %s\n",
3174 RSTRING_PTR(e->use_shell ? e->invoke.sh.shell_script : e->invoke.cmd.command_name));
3186 rb_exec_atfork(
void* arg,
char *errmsg,
size_t errmsg_buflen)
3193 #if SIZEOF_INT == SIZEOF_LONG 3194 #define proc_syswait (VALUE (*)(VALUE))rb_syswait 3197 proc_syswait(
VALUE pid)
3205 move_fds_to_avoid_crash(
int *fdp,
int n,
VALUE fds)
3209 for (i = 0; i < n; i++) {
3228 pipe_nocrash(
int filedes[2],
VALUE fds)
3236 if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
3246 struct chfunc_protect_t {
3247 int (*
chfunc)(
void*,
char *, size_t);
3254 chfunc_protect(
VALUE arg)
3256 struct chfunc_protect_t *p = (
struct chfunc_protect_t *)arg;
3258 return (
VALUE)(*p->chfunc)(p->arg, p->errmsg, p->buflen);
3292 retry_fork(
int *status,
int *ep,
int chfunc_is_async_signal_safe)
3298 #define prefork() ( \ 3299 rb_io_flush(rb_stdout), \ 3300 rb_io_flush(rb_stderr) \ 3305 if (!chfunc_is_async_signal_safe)
3310 if (!chfunc_is_async_signal_safe)
3323 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 3326 if (!status && !ep) {
3332 if (status) *status = state;
3333 if (!state)
continue;
3346 write_retry(
int fd,
const void *
buf,
size_t len)
3351 w = write(fd,
buf, len);
3352 }
while (w < 0 &&
errno == EINTR);
3358 read_retry(
int fd,
void *
buf,
size_t len)
3363 r = read(fd,
buf, len);
3364 }
while (r < 0 &&
errno == EINTR);
3370 send_child_error(
int fd,
int state,
char *errmsg,
size_t errmsg_buflen,
int chfunc_is_async_signal_safe)
3375 if (!chfunc_is_async_signal_safe) {
3376 if (write_retry(fd, &state,
sizeof(state)) ==
sizeof(state) && state) {
3385 if (errmsg && 0 < errmsg_buflen) {
3386 errmsg[errmsg_buflen-1] =
'\0';
3387 errmsg_buflen =
strlen(errmsg);
3388 if (errmsg_buflen > 0 && write_retry(fd, errmsg, errmsg_buflen) < 0)
3395 recv_child_error(
int fd,
int *statep,
VALUE *excp,
int *errp,
char *errmsg,
size_t errmsg_buflen,
int chfunc_is_async_signal_safe)
3401 if (!chfunc_is_async_signal_safe) {
3402 if ((read_retry(fd, &state,
sizeof(state))) ==
sizeof(state) && state) {
3407 if (!*statep && state) *statep = state;
3410 #define READ_FROM_CHILD(ptr, len) \ 3411 (NIL_P(io) ? read_retry(fd, (ptr), (len)) : rb_io_bufread(io, (ptr), (len))) 3412 if ((
size = READ_FROM_CHILD(&
err,
sizeof(
err))) < 0) {
3417 errmsg && 0 < errmsg_buflen) {
3418 ssize_t ret = READ_FROM_CHILD(errmsg, errmsg_buflen-1);
3431 rb_fork_internal(
int *status,
int (*
chfunc)(
void*,
char *,
size_t),
void *charg,
3432 int chfunc_is_async_signal_safe,
VALUE fds,
3433 char *errmsg,
size_t errmsg_buflen)
3441 if (status) *status = 0;
3454 if (pipe_nocrash(ep, fds))
return -1;
3455 pid = retry_fork(status, ep, chfunc_is_async_signal_safe);
3462 if (chfunc_is_async_signal_safe)
3463 ret =
chfunc(charg, errmsg, errmsg_buflen);
3465 struct chfunc_protect_t arg;
3468 arg.errmsg = errmsg;
3469 arg.buflen = errmsg_buflen;
3473 send_child_error(ep[1], state, errmsg, errmsg_buflen, chfunc_is_async_signal_safe);
3474 #if EXIT_SUCCESS == 127 3481 error_occurred = recv_child_error(ep[0], &state, &exc, &
err, errmsg, errmsg_buflen, chfunc_is_async_signal_safe);
3482 if (state || error_occurred) {
3485 if (state) *status = state;
3499 rb_fork_err(
int *status,
int (*
chfunc)(
void*,
char *,
size_t),
void *charg,
VALUE fds,
3500 char *errmsg,
size_t errmsg_buflen)
3502 return rb_fork_internal(status,
chfunc, charg,
FALSE, fds, errmsg, errmsg_buflen);
3507 char *errmsg,
size_t errmsg_buflen)
3509 return rb_fork_internal(status,
chfunc, charg,
TRUE, fds, errmsg, errmsg_buflen);
3512 struct chfunc_wrapper_t {
3518 chfunc_wrapper(
void *arg_,
char *errmsg,
size_t errmsg_buflen)
3520 struct chfunc_wrapper_t *arg = arg_;
3521 return arg->chfunc(arg->arg);
3525 rb_fork(
int *status,
int (*
chfunc)(
void*),
void *charg,
VALUE fds)
3528 struct chfunc_wrapper_t warg;
3531 return rb_fork_internal(status, chfunc_wrapper, &warg,
FALSE, fds,
NULL, 0);
3547 #if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD) 3601 #define rb_f_fork rb_f_notimplement 3618 #if EXIT_SUCCESS != 0 3777 #if !defined HAVE_FORK || USE_SPAWNV 3782 #if defined HAVE_FORK && !USE_SPAWNV 3795 # if defined HAVE_SPAWNV 3801 pid = proc_spawn_cmd(
argv, prog, eargp);
3886 #if defined(SIGCLD) && !defined(SIGCHLD) 3887 # define SIGCHLD SIGCLD 3891 RETSIGTYPE (*
chfunc)(int);
3897 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV) 3901 if (ret == (rb_pid_t)-1)
3902 rb_sys_fail(
"Another thread waited the process started by system().");
4186 VALUE execarg_obj, fail_str;
4198 const char *prog = errmsg;
4204 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV) 4242 end = time(0) - beg;
4248 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID) 4266 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID) 4277 #define proc_getpgrp rb_f_notimplement 4281 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)) 4300 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID) 4306 #define proc_setpgrp rb_f_notimplement 4310 #if defined(HAVE_GETPGID) 4332 #define proc_getpgid rb_f_notimplement 4348 rb_pid_t ipid, ipgrp;
4358 #define proc_setpgid rb_f_notimplement 4392 #define proc_getsid rb_f_notimplement 4396 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY)) 4397 #if !defined(HAVE_SETSID) 4398 static rb_pid_t ruby_setsid(
void);
4399 #define setsid() ruby_setsid() 4423 #if !defined(HAVE_SETSID) 4424 #define HAVE_SETSID 1 4432 #if defined(SETPGRP_VOID) 4438 ret = setpgrp(0, pid);
4440 if (ret == -1)
return -1;
4451 #define proc_setsid rb_f_notimplement 4455 #ifdef HAVE_GETPRIORITY 4476 int prio, iwhich, iwho;
4483 prio = getpriority(iwhich, iwho);
4488 #define proc_getpriority rb_f_notimplement 4492 #ifdef HAVE_GETPRIORITY 4508 int iwhich, iwho, iprio;
4515 if (setpriority(iwhich, iwho, iprio) < 0)
4520 #define proc_setpriority rb_f_notimplement 4523 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 4525 rlimit_resource_name2int(
const char *
name,
int casetype)
4529 #define RESCHECK(r) \ 4531 if (STRCASECMP(name, #r) == 0) { \ 4532 resource = RLIMIT_##r; \ 4566 #ifdef RLIMIT_MEMLOCK 4569 #ifdef RLIMIT_MSGQUEUE 4575 #ifdef RLIMIT_NOFILE 4590 #ifdef RLIMIT_RTPRIO 4593 #ifdef RLIMIT_RTTIME 4602 #ifdef RLIMIT_SBSIZE 4605 #ifdef RLIMIT_SIGPENDING 4606 RESCHECK(SIGPENDING);
4615 for (p =
name; *p; p++)
4621 for (p =
name; *p; p++)
4627 rb_bug(
"unexpected casetype");
4634 rlimit_type_by_hname(
const char *
name)
4636 return rlimit_resource_name2int(
name, 0);
4640 rlimit_type_by_lname(
const char *
name)
4642 return rlimit_resource_name2int(
name, 1);
4646 rlimit_resource_type(
VALUE rtype)
4652 switch (
TYPE(rtype)) {
4672 r = rlimit_type_by_hname(
name);
4682 rlimit_resource_value(
VALUE rval)
4687 switch (
TYPE(rval)) {
4704 return NUM2RLIM(rval);
4707 #ifdef RLIM_INFINITY 4708 if (strcmp(
name,
"INFINITY") == 0)
return RLIM_INFINITY;
4710 #ifdef RLIM_SAVED_MAX 4711 if (strcmp(
name,
"SAVED_MAX") == 0)
return RLIM_SAVED_MAX;
4713 #ifdef RLIM_SAVED_CUR 4714 if (strcmp(
name,
"SAVED_CUR") == 0)
return RLIM_SAVED_CUR;
4722 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM) 4750 if (
getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4753 return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
4756 #define proc_getrlimit rb_f_notimplement 4759 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 4814 VALUE resource, rlim_cur, rlim_max;
4820 if (rlim_max ==
Qnil)
4821 rlim_max = rlim_cur;
4823 rlim.rlim_cur = rlimit_resource_value(rlim_cur);
4824 rlim.rlim_max = rlimit_resource_value(rlim_max);
4826 if (
setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4832 #define proc_setrlimit rb_f_notimplement 4866 #if defined(HAVE_PWD_H) 4869 # ifdef USE_GETPWNAM_R
4882 struct passwd *pwptr;
4883 #ifdef USE_GETPWNAM_R 4884 struct passwd pwbuf;
4888 getpw_buf_len = GETPW_R_SIZE_INIT;
4889 if (getpw_buf_len < 0) getpw_buf_len = GETPW_R_SIZE_DEFAULT;
4898 while (getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) {
4899 if (
errno != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) {
4908 pwptr = getpwnam(usrname);
4911 #ifndef USE_GETPWNAM_R 4916 uid = pwptr->pw_uid;
4917 #ifndef USE_GETPWNAM_R 4924 # ifdef p_uid_from_name 4944 #if defined(HAVE_GRP_H) 4947 # ifdef USE_GETGRNAM_R
4960 struct group *grptr;
4961 #ifdef USE_GETGRNAM_R 4966 getgr_buf_len = GETGR_R_SIZE_INIT;
4967 if (getgr_buf_len < 0) getgr_buf_len = GETGR_R_SIZE_DEFAULT;
4976 while (getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) {
4977 if (
errno != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) {
4986 grptr = getgrnam(grpname);
4989 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT) 4994 gid = grptr->gr_gid;
4995 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT) 5002 # ifdef p_gid_from_name 5022 #if defined HAVE_SETUID 5040 #define p_sys_setuid rb_f_notimplement 5044 #if defined HAVE_SETRUID 5062 #define p_sys_setruid rb_f_notimplement 5066 #if defined HAVE_SETEUID 5084 #define p_sys_seteuid rb_f_notimplement 5088 #if defined HAVE_SETREUID 5103 rb_uid_t ruid, euid;
5106 ruid = OBJ2UID1(rid);
5107 euid = OBJ2UID1(eid);
5113 #define p_sys_setreuid rb_f_notimplement 5117 #if defined HAVE_SETRESUID 5132 rb_uid_t ruid, euid, suid;
5135 ruid = OBJ2UID1(rid);
5136 euid = OBJ2UID1(eid);
5137 suid = OBJ2UID1(sid);
5139 if (setresuid(ruid, euid, suid) != 0)
rb_sys_fail(0);
5143 #define p_sys_setresuid rb_f_notimplement 5166 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID) 5183 #if defined(HAVE_SETRESUID) 5185 #elif defined HAVE_SETREUID 5187 #elif defined HAVE_SETRUID 5189 #elif defined HAVE_SETUID 5202 #define proc_setuid rb_f_notimplement 5218 #ifdef BROKEN_SETREUID 5220 setreuid(rb_uid_t ruid, rb_uid_t euid)
5222 if (ruid != (rb_uid_t)-1 && ruid !=
getuid()) {
5223 if (euid == (rb_uid_t)-1) euid =
geteuid();
5224 if (
setuid(ruid) < 0)
return -1;
5226 if (euid != (rb_uid_t)-1 && euid !=
geteuid()) {
5227 if (
seteuid(euid) < 0)
return -1;
5256 #if defined(HAVE_SETRESUID) 5259 #elif defined(HAVE_SETUID) 5262 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 5287 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID) 5318 #if defined(HAVE_SETRESUID) 5319 if (setresuid((
getuid() == uid)? (rb_uid_t)-1: uid,
5320 (
geteuid() == uid)? (rb_uid_t)-1: uid,
5323 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 5325 if (setreuid((
getuid() == uid)? (rb_uid_t)-1: uid,
5326 (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5329 else if (
getuid() != uid) {
5330 if (setreuid(uid, (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5345 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID) 5361 else if (
getuid() == uid) {
5371 #elif defined HAVE_44BSD_SETUID 5381 #elif defined HAVE_SETEUID 5389 #elif defined HAVE_SETUID 5406 #if defined HAVE_SETGID 5424 #define p_sys_setgid rb_f_notimplement 5428 #if defined HAVE_SETRGID 5446 #define p_sys_setrgid rb_f_notimplement 5450 #if defined HAVE_SETEGID 5468 #define p_sys_setegid rb_f_notimplement 5472 #if defined HAVE_SETREGID 5487 rb_gid_t rgid, egid;
5497 #define p_sys_setregid rb_f_notimplement 5500 #if defined HAVE_SETRESGID 5515 rb_gid_t rgid, egid, sgid;
5522 if (setresgid(rgid, egid, sgid) != 0)
rb_sys_fail(0);
5526 #define p_sys_setresgid rb_f_notimplement 5530 #if defined HAVE_ISSETUGID 5555 #define p_sys_issetugid rb_f_notimplement 5578 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID) 5594 #if defined(HAVE_SETRESGID) 5596 #elif defined HAVE_SETREGID 5598 #elif defined HAVE_SETRGID 5600 #elif defined HAVE_SETGID 5613 #define proc_setgid rb_f_notimplement 5617 #if defined(HAVE_SETGROUPS) || defined(HAVE_GETGROUPS) 5638 static int _maxgroups = -1;
5640 get_sc_ngroups_max(
void)
5642 #ifdef _SC_NGROUPS_MAX 5643 return (
int)sysconf(_SC_NGROUPS_MAX);
5644 #elif defined(NGROUPS_MAX) 5645 return (
int)NGROUPS_MAX;
5653 if (_maxgroups < 0) {
5654 _maxgroups = get_sc_ngroups_max();
5665 #ifdef HAVE_GETGROUPS 5684 ngroups = getgroups(0,
NULL);
5688 groups =
ALLOCV_N(rb_gid_t, tmp, ngroups);
5690 ngroups = getgroups(ngroups, groups);
5695 for (i = 0; i < ngroups; i++)
5703 #define proc_getgroups rb_f_notimplement 5707 #ifdef HAVE_SETGROUPS 5732 if (ngroups > maxgroups())
5735 groups =
ALLOCV_N(rb_gid_t, tmp, ngroups);
5737 for (i = 0; i < ngroups; i++) {
5740 groups[i] = OBJ2GID1(g);
5744 if (setgroups(ngroups, groups) == -1)
5752 #define proc_setgroups rb_f_notimplement 5756 #ifdef HAVE_INITGROUPS 5783 #define proc_initgroups rb_f_notimplement 5786 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX) 5803 #define proc_getmaxgroups rb_f_notimplement 5806 #ifdef HAVE_SETGROUPS 5819 int ngroups_max = get_sc_ngroups_max();
5827 if (ngroups_max > 0 && ngroups > ngroups_max)
5828 ngroups = ngroups_max;
5830 _maxgroups = ngroups;
5835 #define proc_setmaxgroups rb_f_notimplement 5838 #if defined(HAVE_DAEMON) || (defined(HAVE_FORK) && defined(HAVE_SETSID)) 5839 static int rb_daemon(
int nochdir,
int noclose);
5858 VALUE nochdir, noclose;
5865 n = rb_daemon(
RTEST(nochdir),
RTEST(noclose));
5871 rb_daemon(
int nochdir,
int noclose)
5876 err = daemon(nochdir, noclose);
5882 #define fork_daemon() \ 5883 switch (rb_fork_ruby(NULL)) { \ 5884 case -1: return -1; \ 5885 case 0: rb_thread_atfork(); break; \ 5886 default: _exit(EXIT_SUCCESS); \ 5891 if (setsid() < 0)
return -1;
5899 if (!noclose && (n =
rb_cloexec_open(
"/dev/null", O_RDWR, 0)) != -1) {
5911 #define proc_daemon rb_f_notimplement 5926 #ifdef BROKEN_SETREGID 5928 setregid(rb_gid_t rgid, rb_gid_t egid)
5930 if (rgid != (rb_gid_t)-1 && rgid !=
getgid()) {
5931 if (egid == (rb_gid_t)-1) egid =
getegid();
5932 if (
setgid(rgid) < 0)
return -1;
5934 if (egid != (rb_gid_t)-1 && egid !=
getegid()) {
5935 if (
setegid(egid) < 0)
return -1;
5964 #if defined(HAVE_SETRESGID) 5967 #elif defined HAVE_SETGID 5970 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 5995 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID) 6026 #if defined(HAVE_SETRESGID) 6027 if (setresgid((
getgid() == gid)? (rb_gid_t)-1: gid,
6028 (
getegid() == gid)? (rb_gid_t)-1: gid,
6031 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6033 if (setregid((
getgid() == gid)? (rb_uid_t)-1: gid,
6034 (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
6037 else if (
getgid() != gid) {
6038 if (setregid(gid, (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
6053 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID) 6069 else if (
getgid() == gid) {
6079 #elif defined HAVE_44BSD_SETGID 6089 #elif defined HAVE_SETEGID 6097 #elif defined HAVE_SETGID 6132 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS) 6134 proc_seteuid(rb_uid_t uid)
6136 #if defined(HAVE_SETRESUID) 6138 #elif defined HAVE_SETREUID 6140 #elif defined HAVE_SETEUID 6142 #elif defined HAVE_SETUID 6155 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) 6172 #define proc_seteuid_m rb_f_notimplement 6178 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)) 6184 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)) 6188 #if defined(HAVE_SETRESUID) 6196 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 6203 #elif defined HAVE_SETEUID 6205 #elif defined HAVE_SETUID 6257 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS) 6269 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) 6275 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) 6279 #if defined(HAVE_SETRESGID) 6281 #elif defined HAVE_SETREGID 6283 #elif defined HAVE_SETEGID 6285 #elif defined HAVE_SETGID 6299 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) 6300 #define proc_setegid_m proc_setegid 6302 #define proc_setegid_m rb_f_notimplement 6308 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)) 6314 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)) 6318 #if defined(HAVE_SETRESGID) 6326 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6333 #elif defined HAVE_SETEGID 6335 #elif defined HAVE_SETGID 6379 #if defined(HAVE_SETRESUID) 6381 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 6405 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)) 6412 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)) 6416 #if defined(HAVE_SETRESUID) 6417 if (setresuid(euid, uid, uid) < 0)
rb_sys_fail(0);
6419 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 6441 #if defined(HAVE_SETRESGID) 6443 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6467 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)) 6474 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)) 6478 #if defined(HAVE_SETRESGID) 6479 if (setresgid(egid, gid, gid) < 0)
rb_sys_fail(0);
6481 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6504 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS) 6512 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS) 6620 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS) 6627 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS) 6721 #if defined(HAVE_TIMES) 6726 #ifdef HAVE__SC_CLK_TCK 6727 (double)sysconf(_SC_CLK_TCK);
6756 const double hertz = get_clk_tck();
6773 #define rb_proc_times rb_f_notimplement 6776 #ifdef HAVE_LONG_LONG 6778 #define TIMETICK_INT_MIN LLONG_MIN 6779 #define TIMETICK_INT_MAX LLONG_MAX 6780 #define TIMETICK_INT2NUM(v) LL2NUM(v) 6783 #define TIMETICK_INT_MIN LONG_MIN 6784 #define TIMETICK_INT_MAX LONG_MAX 6785 #define TIMETICK_INT2NUM(v) LONG2NUM(v) 6823 for (i = 0; i < num_numerators; i++) {
6824 if (numerators[i] == 1)
6826 for (j = 0; j < num_denominators; j++) {
6827 if (denominators[j] == 1)
6848 denominators, num_denominators);
6852 for (i = 0; i < num_numerators; i++)
6854 for (i = 0; i < num_denominators; i++)
6855 d /= denominators[i];
6869 denominators, num_denominators);
6872 for (i = 0; i < num_denominators; i++)
6873 d *= denominators[i];
6874 for (i = 0; i < num_numerators; i++)
6881 #define NDIV(x,y) (-(-((x)+1)/(y))-1) 6882 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d)) 6893 denominators, num_denominators);
6898 for (i = 0; i < num_numerators; i++) {
6905 for (i = 0; i < num_denominators; i++) {
6906 t =
DIV(
t, denominators[i]);
6915 for (i = 0; i < num_numerators; i++) {
6921 for (i = 0; i < num_denominators; i++) {
6934 numerators[num_numerators++] = 1000000000;
6935 return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
6938 numerators[num_numerators++] = 1000000;
6939 return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
6942 numerators[num_numerators++] = 1000;
6943 return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
6946 return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
6949 numerators[num_numerators++] = 1000000;
6950 return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
6953 numerators[num_numerators++] = 1000;
6954 return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
6957 return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
6964 static mach_timebase_info_data_t *
6965 get_mach_timebase_info(
void)
6967 static mach_timebase_info_data_t sTimebaseInfo;
6969 if ( sTimebaseInfo.denom == 0 ) {
6970 (void) mach_timebase_info(&sTimebaseInfo);
6973 return &sTimebaseInfo;
7109 int num_numerators = 0;
7110 int num_denominators = 0;
7122 #define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ID2SYM(rb_intern("GETTIMEOFDAY_BASED_CLOCK_REALTIME")) 7130 denominators[num_denominators++] = 1000000000;
7134 #define RUBY_TIME_BASED_CLOCK_REALTIME ID2SYM(rb_intern("TIME_BASED_CLOCK_REALTIME")) 7138 if (
t == (time_t)-1)
7142 denominators[num_denominators++] = 1000000000;
7147 #define RUBY_TIMES_BASED_CLOCK_MONOTONIC \ 7148 ID2SYM(rb_intern("TIMES_BASED_CLOCK_MONOTONIC")) 7149 if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
7154 if (c == (clock_t)-1)
7157 tt.
count = (int32_t)(uc % 1000000000);
7159 denominators[num_denominators++] = get_clk_tck();
7165 #define RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID \ 7166 ID2SYM(rb_intern("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID")) 7167 if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7168 struct rusage
usage;
7174 usec = (int32_t)(
usage.ru_utime.tv_usec +
usage.ru_stime.tv_usec);
7175 if (1000000 <= usec) {
7179 tt.
count = usec * 1000;
7180 denominators[num_denominators++] = 1000000000;
7186 #define RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID \ 7187 ID2SYM(rb_intern("TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID")) 7188 if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7191 if (times(&
buf) == (clock_t)-1)
7195 tt.
count = (int32_t)((
utime % 1000000000) + (stime % 1000000000));
7197 if (1000000000 <= tt.
count) {
7198 tt.
count -= 1000000000;
7201 denominators[num_denominators++] = get_clk_tck();
7206 #define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID \ 7207 ID2SYM(rb_intern("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID")) 7213 if (c == (clock_t)-1)
7216 tt.
count = (int32_t)(uc % 1000000000);
7218 denominators[num_denominators++] = CLOCKS_PER_SEC;
7223 #define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(rb_intern("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC")) 7224 if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
7225 mach_timebase_info_data_t *info = get_mach_timebase_info();
7227 tt.
count = (int32_t)(
t % 1000000000);
7229 numerators[num_numerators++] = info->numer;
7230 denominators[num_denominators++] = info->denom;
7231 denominators[num_denominators++] = 1000000000;
7237 #if defined(HAVE_CLOCK_GETTIME) 7240 c = NUM2CLOCKID(clk_id);
7246 denominators[num_denominators++] = 1000000000;
7255 return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
7304 int num_numerators = 0;
7305 int num_denominators = 0;
7310 #ifdef RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME 7314 denominators[num_denominators++] = 1000000000;
7319 #ifdef RUBY_TIME_BASED_CLOCK_REALTIME 7323 denominators[num_denominators++] = 1000000000;
7328 #ifdef RUBY_TIMES_BASED_CLOCK_MONOTONIC 7329 if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
7332 denominators[num_denominators++] = get_clk_tck();
7337 #ifdef RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID 7338 if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7341 denominators[num_denominators++] = 1000000000;
7346 #ifdef RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID 7347 if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7350 denominators[num_denominators++] = get_clk_tck();
7355 #ifdef RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID 7359 denominators[num_denominators++] = CLOCKS_PER_SEC;
7364 #ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC 7365 if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
7366 mach_timebase_info_data_t *info = get_mach_timebase_info();
7369 numerators[num_numerators++] = info->numer;
7370 denominators[num_denominators++] = info->denom;
7371 denominators[num_denominators++] = 1000000000;
7377 #if defined(HAVE_CLOCK_GETRES) 7385 denominators[num_denominators++] = 1000000000;
7398 return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
7417 #define rb_intern(str) rb_intern_const(str) 7496 #ifdef HAVE_GETPRIORITY 7507 #if defined(RLIM2NUM) && defined(RLIM_INFINITY) 7509 VALUE inf = RLIM2NUM(RLIM_INFINITY);
7510 #ifdef RLIM_SAVED_MAX 7512 VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ?
inf : RLIM2NUM(RLIM_SAVED_MAX);
7519 #ifdef RLIM_SAVED_CUR 7521 VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ?
inf : RLIM2NUM(RLIM_SAVED_CUR);
7562 #ifdef RLIMIT_MEMLOCK 7569 #ifdef RLIMIT_MSGQUEUE 7584 #ifdef RLIMIT_NOFILE 7607 #ifdef RLIMIT_RTPRIO 7614 #ifdef RLIMIT_RTTIME 7622 #ifdef RLIMIT_SBSIZE 7627 #ifdef RLIMIT_SIGPENDING 7662 #ifdef CLOCK_REALTIME 7664 #elif defined(RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME) 7667 #ifdef CLOCK_MONOTONIC 7669 #elif defined(RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) 7672 #ifdef CLOCK_PROCESS_CPUTIME_ID 7674 #elif defined(RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) 7677 #ifdef CLOCK_THREAD_CPUTIME_ID 7680 #ifdef CLOCK_VIRTUAL 7686 #ifdef CLOCK_REALTIME_FAST 7689 #ifdef CLOCK_REALTIME_PRECISE 7692 #ifdef CLOCK_REALTIME_COARSE 7695 #ifdef CLOCK_REALTIME_ALARM 7698 #ifdef CLOCK_MONOTONIC_FAST 7701 #ifdef CLOCK_MONOTONIC_PRECISE 7704 #ifdef CLOCK_MONOTONIC_RAW 7707 #ifdef CLOCK_MONOTONIC_COARSE 7710 #ifdef CLOCK_BOOTTIME 7713 #ifdef CLOCK_BOOTTIME_ALARM 7719 #ifdef CLOCK_UPTIME_FAST 7722 #ifdef CLOCK_UPTIME_PRECISE 7731 #if defined(HAVE_TIMES) || defined(_WIN32) 7760 #ifdef p_uid_from_name 7763 #ifdef p_gid_from_name
static VALUE timetick2dblnum(struct timetick *ttp, timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators)
static VALUE p_uid_have_saved_id(void)
static int run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
#define RBASIC_CLEAR_CLASS(obj)
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)
static VALUE rb_check_argv(int argc, VALUE *argv)
VALUE rb_ary_entry(VALUE ary, long offset)
void rb_bug(const char *fmt,...)
int gettimeofday(struct timeval *, struct timezone *)
#define RUBY_TYPED_FREE_IMMEDIATELY
static VALUE check_exec_fds(struct rb_execarg *eargp)
static void rb_check_exec_options(VALUE opthash, VALUE execarg_obj)
union rb_execarg::@123 invoke
static timetick_int_t gcd_timetick_int(timetick_int_t a, timetick_int_t b)
size_t strlen(const char *)
unsigned int unsigned_clock_t
void rb_update_max_fd(int fd)
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
#define redirect_open(pathname, flags, perm)
void rb_free_tmp_buffer(volatile VALUE *store)
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)
#define RB_OBJ_WRITTEN(a, oldv, b)
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)
#define RUBY_TIME_BASED_CLOCK_REALTIME
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)
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
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)
static VALUE p_gid_have_saved_id(void)
static VALUE p_gid_exchangeable(void)
struct st_table * rb_hash_tbl_raw(VALUE hash)
rb_pid_t rb_fork_ruby(int *status)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
rb_pid_t rb_w32_uaspawn_flags(int, const char *, char *const *, DWORD)
VALUE rb_iv_set(VALUE, const char *, VALUE)
void rb_str_set_len(VALUE, long)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
VALUE rb_iv_get(VALUE, const char *)
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)
static VALUE check_exec_redirect_fd(VALUE v, int iskey)
VALUE rb_f_exit(int argc, VALUE *argv)
#define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
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)
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)
#define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
static VALUE pst_wtermsig(VALUE st)
void rb_undef_method(VALUE klass, const char *name)
#define GetOpenFile(obj, fp)
static void reduce_fraction(timetick_int_t *np, timetick_int_t *dp)
VALUE rb_struct_define_under(VALUE, const char *,...)
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)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
static void reduce_factors(timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators)
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
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)
unsigned long long uint64_t
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)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
int getrlimit(int resource, struct rlimit *rlp)
VALUE rb_str_encode_ospath(VALUE path)
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)
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)
static void after_exec_non_async_signal_safe(void)
void rb_thread_stop_timer_thread(int close_anyway)
#define TIMETICK_INT2NUM(v)
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)
#define ALLOCV_N(type, v, n)
mode_t umask(mode_t mask)
void ruby_stop(int ex)
Calls ruby_cleanup() and exits the process.
VALUE rb_obj_alloc(VALUE)
static VALUE timetick2dblnum_reciprocal(struct timetick *ttp, timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators)
static size_t memsize_exec_arg(const void *ptr)
static VALUE make_clock_result(struct timetick *ttp, timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators, VALUE unit)
static int save_redirect_fd(int fd, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
static VALUE save_env_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
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)
size_t rb_str_capacity(VALUE)
VALUE rb_const_get(VALUE, ID)
VALUE rb_thread_local_aset(VALUE, ID, VALUE)
VALUE rb_clock_gettime(int argc, VALUE *argv)
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)
timetick_int_t giga_count
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)
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)
void rb_str_modify_expand(VALUE, long)
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)
int clock_gettime(clockid_t, struct timespec *)
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)
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)
static VALUE timetick2integer(struct timetick *ttp, timetick_int_t *numerators, int num_numerators, timetick_int_t *denominators, int num_denominators)
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)
struct rb_execarg::@123::@125 cmd
RUBY_EXTERN VALUE rb_stderr
#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)
RUBY_EXTERN VALUE rb_cStruct
#define RARRAY_AREF(a, i)
static VALUE pst_wifstopped(VALUE st)
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
#define redirect_dup2(oldfd, newfd)
struct rb_execarg::@123::@124 sh
static VALUE p_gid_exchange(VALUE obj)
void rb_set_errinfo(VALUE err)
static VALUE p_uid_grant_privilege(VALUE obj, VALUE id)
int getrusage(int who, struct rusage *usage)
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)
int clock_getres(clockid_t, struct timespec *)
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)
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)
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)
rb_pid_t rb_w32_uspawn(int, const char *, const char *)
#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max)
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)
void rb_warn(const char *fmt,...)
static VALUE pst_wexitstatus(VALUE st)
void * rb_alloc_tmp_buffer(volatile VALUE *store, long len) RUBY_ATTR_ALLOC_SIZE((2))
VALUE rb_clock_getres(int argc, VALUE *argv)
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)