40 #define EXIT_SUCCESS 0 43 #define EXIT_FAILURE 1 46 #ifdef HAVE_SYS_WAIT_H 47 # include <sys/wait.h> 49 #ifdef HAVE_SYS_RESOURCE_H 50 # include <sys/resource.h> 55 #ifdef HAVE_SYS_PARAM_H 56 # include <sys/param.h> 59 # define MAXPATHLEN 1024 64 #if defined(__native_client__) && defined(NACL_NEWLIB) 65 # include <sys/unistd.h> 69 # undef HAVE_ISSETUGID 72 #ifdef HAVE_SYS_TIME_H 75 #ifdef HAVE_SYS_TIMES_H 76 #include <sys/times.h> 85 int initgroups(
const char *, rb_gid_t);
93 # include <mach/mach_time.h> 99 #define open rb_w32_uopen 102 #if defined(HAVE_TIMES) || defined(_WIN32) 103 static VALUE rb_cProcessTms;
107 #define WIFEXITED(w) (((w) & 0xff) == 0) 110 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f)) 113 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f) 116 #define WEXITSTATUS(w) (((w) >> 8) & 0xff) 119 #define WTERMSIG(w) ((w) & 0x7f) 122 #define WSTOPSIG WEXITSTATUS 125 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) 126 #define HAVE_44BSD_SETUID 1 127 #define HAVE_44BSD_SETGID 1 135 #ifdef BROKEN_SETREUID 136 #define setreuid ruby_setreuid 137 int setreuid(rb_uid_t ruid, rb_uid_t euid);
139 #ifdef BROKEN_SETREGID 140 #define setregid ruby_setregid 141 int setregid(rb_gid_t rgid, rb_gid_t egid);
144 #if defined(HAVE_44BSD_SETUID) || defined(__APPLE__) 145 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID) 146 #define OBSOLETE_SETREUID 1 148 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID) 149 #define OBSOLETE_SETREGID 1 153 #define preserving_errno(stmts) \ 154 do {int saved_errno = errno; stmts; errno = saved_errno;} while (0) 156 static void check_uid_switch(
void);
157 static void check_gid_switch(
void);
160 #define p_uid_from_name p_uid_from_name 161 #define p_gid_from_name p_gid_from_name 164 #if defined(HAVE_PWD_H) 165 # if defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX) 166 # define USE_GETPWNAM_R 1 167 # define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX) 168 # define GETPW_R_SIZE_DEFAULT 0x1000 169 # define GETPW_R_SIZE_LIMIT 0x10000 171 # ifdef USE_GETPWNAM_R 172 # define PREPARE_GETPWNAM \ 174 # define FINISH_GETPWNAM \ 175 (getpw_buf ? (void)rb_str_resize(getpw_buf, 0) : (void)0) 176 # define OBJ2UID1(id) obj2uid((id), &getpw_buf) 177 # define OBJ2UID(id) obj2uid0(id) 178 static rb_uid_t obj2uid(
VALUE id,
VALUE *getpw_buf);
179 static inline rb_uid_t
189 # define PREPARE_GETPWNAM 190 # define FINISH_GETPWNAM 191 # define OBJ2UID1(id) obj2uid((id)) 192 # define OBJ2UID(id) obj2uid((id)) 193 static rb_uid_t obj2uid(
VALUE id);
196 # define PREPARE_GETPWNAM 197 # define FINISH_GETPWNAM 198 # define OBJ2UID1(id) NUM2UIDT(id) 199 # define OBJ2UID(id) NUM2UIDT(id) 200 # ifdef p_uid_from_name 201 # undef p_uid_from_name 202 # define p_uid_from_name rb_f_notimplement 206 #if defined(HAVE_GRP_H) 207 # if defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX) 208 # define USE_GETGRNAM_R 209 # define GETGR_R_SIZE_INIT sysconf(_SC_GETGR_R_SIZE_MAX) 210 # define GETGR_R_SIZE_DEFAULT 0x1000 211 # define GETGR_R_SIZE_LIMIT 0x10000 213 # ifdef USE_GETGRNAM_R 214 # define PREPARE_GETGRNAM \ 216 # define FINISH_GETGRNAM \ 217 (getgr_buf ? (void)rb_str_resize(getgr_buf, 0) : (void)0) 218 # define OBJ2GID1(id) obj2gid((id), &getgr_buf) 219 # define OBJ2GID(id) obj2gid0(id) 220 static rb_gid_t obj2gid(
VALUE id,
VALUE *getgr_buf);
221 static inline rb_gid_t
230 static rb_gid_t obj2gid(
VALUE id,
VALUE *getgr_buf);
232 # define PREPARE_GETGRNAM 233 # define FINISH_GETGRNAM 234 # define OBJ2GID1(id) obj2gid((id)) 235 # define OBJ2GID(id) obj2gid((id)) 236 static rb_gid_t obj2gid(
VALUE id);
239 # define PREPARE_GETGRNAM 240 # define FINISH_GETGRNAM 241 # define OBJ2GID1(id) NUM2GIDT(id) 242 # define OBJ2GID(id) NUM2GIDT(id) 243 # ifdef p_gid_from_name 244 # undef p_gid_from_name 245 # define p_gid_from_name rb_f_notimplement 249 #if SIZEOF_CLOCK_T == SIZEOF_INT 251 #elif SIZEOF_CLOCK_T == SIZEOF_LONG 253 #elif defined(HAVE_LONG_LONG) && SIZEOF_CLOCK_T == SIZEOF_LONG_LONG 260 static ID id_in, id_out, id_err, id_pid, id_uid, id_gid;
261 static ID id_close, id_child;
266 static ID id_new_pgroup;
268 static ID id_unsetenv_others, id_chdir, id_umask, id_close_others, id_ENV;
269 static ID id_nanosecond, id_microsecond, id_millisecond, id_second;
270 static ID id_float_microsecond, id_float_millisecond, id_float_second;
271 static ID id_GETTIMEOFDAY_BASED_CLOCK_REALTIME, id_TIME_BASED_CLOCK_REALTIME;
273 static ID id_TIMES_BASED_CLOCK_MONOTONIC;
274 static ID id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID;
277 static ID id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID;
279 static ID id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID;
281 static ID id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC;
285 #define id_status ruby_static_id_status 288 #if defined(__sun) && !defined(_XPG7) 289 #define execv(path, argv) (rb_async_bug_errno("unreachable: async-signal-unsafe execv() is called", 0)) 290 #define execl(path, arg0, arg1, arg2, term) do { extern char **environ; execle((path), (arg0), (arg1), (arg2), (term), (environ)); } while (0) 291 #define ALWAYS_NEED_ENVP 1 293 #define ALWAYS_NEED_ENVP 0 297 close_unless_reserved(
int fd)
308 #if defined(DEBUG_REDIRECT) 313 ttyprintf(
const char *fmt, ...)
319 tty = fopen(
"con",
"w");
321 tty = fopen(
"/dev/tty",
"w");
327 vfprintf(tty, fmt, ap);
338 ttyprintf(
"dup(%d) => %d\n", oldfd, ret);
346 ret =
dup2(oldfd, newfd);
347 ttyprintf(
"dup2(%d, %d) => %d\n", oldfd, newfd, ret);
356 ttyprintf(
"cloexec_dup(%d) => %d\n", oldfd, ret);
365 ttyprintf(
"cloexec_dup2(%d, %d) => %d\n", oldfd, newfd, ret);
373 ret = close_unless_reserved(fd);
374 ttyprintf(
"close(%d) => %d\n", fd, ret);
383 ttyprintf(
"parent_open(\"%s\", 0x%x, 0%o) => %d\n", pathname,
flags, perm, ret);
391 ret = close_unless_reserved(fd);
392 ttyprintf(
"parent_close(%d) => %d\n", fd, ret);
397 #define redirect_dup(oldfd) dup(oldfd) 398 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd)) 399 #define redirect_cloexec_dup(oldfd) rb_cloexec_dup(oldfd) 400 #define redirect_cloexec_dup2(oldfd, newfd) rb_cloexec_dup2((oldfd), (newfd)) 401 #define redirect_close(fd) close_unless_reserved(fd) 402 #define parent_redirect_open(pathname, flags, perm) rb_cloexec_open((pathname), (flags), (perm)) 403 #define parent_redirect_close(fd) close_unless_reserved(fd) 476 static VALUE rb_cProcessStatus;
518 #define PST2INT(st) NUM2INT(pst_to_i(st)) 538 pst_message(
VALUE str, rb_pid_t pid,
int status)
545 rb_str_catf(str,
" stopped SIG%s (signal %d)", signame, stopsig);
555 rb_str_catf(str,
" SIG%s (signal %d)", signame, termsig);
565 if (WCOREDUMP(status)) {
594 pst_message(str, pid, status);
611 pst_inspect(
VALUE st)
625 pst_message(str, pid, status);
642 if (st1 == st2)
return Qtrue;
643 return rb_equal(pst_to_i(st1), st2);
699 pst_wifstopped(
VALUE st)
719 pst_wstopsig(
VALUE st)
738 pst_wifsignaled(
VALUE st)
759 pst_wtermsig(
VALUE st)
779 pst_wifexited(
VALUE st)
810 pst_wexitstatus(
VALUE st)
829 pst_success_p(
VALUE st)
848 pst_wcoredump(
VALUE st)
853 if (WCOREDUMP(status))
871 #if defined HAVE_WAITPID 872 return waitpid(pid, st, flags);
873 #elif defined HAVE_WAIT4 874 return wait4(pid, st, flags,
NULL);
876 # error waitpid or wait4 is required. 881 rb_waitpid_blocking(
void *data)
884 rb_pid_t result = do_waitpid(arg->
pid, arg->
st, arg->
flags);
885 return (
void *)(
VALUE)result;
889 do_waitpid_nonblocking(rb_pid_t
pid,
int *
st,
int flags)
898 return (rb_pid_t)(
VALUE)result;
907 result = do_waitpid(pid, st, flags);
910 while ((result = do_waitpid_nonblocking(pid, st, flags)) < 0 &&
994 if (
argc == 2 && !
NIL_P(vflags = argv[1])) {
998 if ((pid =
rb_waitpid(pid, &status, flags)) < 0)
1076 static VALUE rb_cWaiter;
1079 detach_process_pid(
VALUE thread)
1085 detach_process_watcher(
void *arg)
1087 rb_pid_t cpid,
pid = (rb_pid_t)(
VALUE)arg;
1090 while ((cpid =
rb_waitpid(pid, &status, 0)) == 0) {
1161 before_exec_async_signal_safe(
void)
1166 before_exec_non_async_signal_safe(
void)
1183 before_exec_non_async_signal_safe();
1184 before_exec_async_signal_safe();
1189 after_exec_async_signal_safe(
void)
1194 after_exec_non_async_signal_safe(
void)
1203 after_exec_async_signal_safe();
1204 after_exec_non_async_signal_safe();
1207 #define before_fork_ruby() before_exec() 1208 #define after_fork_ruby() (rb_threadptr_pending_interrupt_clear(GET_THREAD()), after_exec()) 1213 security(
const char *str)
1222 #if defined(HAVE_WORKING_FORK) && !defined(__native_client__) 1225 #define try_with_sh(prog, argv, envp) ((saved_errno == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0) 1227 exec_with_sh(
const char *prog,
char **
argv,
char **envp)
1229 *
argv = (
char *)prog;
1230 *--
argv = (
char *)
"sh";
1232 execve(
"/bin/sh",
argv, envp);
1234 execv(
"/bin/sh",
argv);
1238 #define try_with_sh(prog, argv, envp) (void)0 1243 proc_exec_cmd(
const char *prog,
VALUE argv_str,
VALUE envp_str)
1245 #ifdef __native_client__ 1266 execve(prog, argv, envp);
1277 proc_exec_sh(
const char *str,
VALUE envp_str)
1279 #ifdef __native_client__ 1286 while (*s ==
' ' || *s ==
'\t' || *s ==
'\n')
1298 #if defined(__CYGWIN32__) 1304 execl(shell,
"sh",
"-c", str, (
char *)
NULL);
1306 status = system(str);
1312 execle(
"/bin/sh",
"sh",
"-c", str, (
char *)
NULL, (
char **)
RSTRING_PTR(envp_str));
1314 execl(
"/bin/sh",
"sh",
"-c", str, (
char *)NULL);
1326 ret = proc_exec_sh(str,
Qfalse);
1332 mark_exec_arg(
void *ptr)
1358 memsize_exec_arg(
const void *ptr)
1370 # define DEFAULT_PROCESS_ENCODING rb_utf8_encoding() 1372 #ifdef DEFAULT_PROCESS_ENCODING 1373 # define EXPORT_STR(str) rb_str_export_to_enc((str), DEFAULT_PROCESS_ENCODING) 1374 # define EXPORT_DUP(str) export_dup(str) 1376 export_dup(
VALUE str)
1383 # define EXPORT_STR(str) (str) 1384 # define EXPORT_DUP(str) rb_str_dup(str) 1387 #if !defined(HAVE_WORKING_FORK) && defined(HAVE_SPAWNV) 1388 # define USE_SPAWNV 1 1390 # define USE_SPAWNV 0 1393 # define P_NOWAIT _P_NOWAIT 1398 #define proc_spawn_cmd_internal(argv, prog) rb_w32_uaspawn(P_NOWAIT, (prog), (argv)) 1401 proc_spawn_cmd_internal(
char **
argv,
char *prog)
1414 status = spawnv(
P_NOWAIT, prog, (
const char **)argv);
1415 if (status == -1 &&
errno == ENOEXEC) {
1416 *argv = (
char *)prog;
1417 *--argv = (
char *)
"sh";
1418 status = spawnv(
P_NOWAIT,
"/bin/sh", (
const char **)argv);
1420 if (status == -1)
errno = ENOEXEC;
1435 flags = CREATE_NEW_PROCESS_GROUP;
1446 #define proc_spawn_sh(str) rb_w32_uspawn(P_NOWAIT, (str), 0) 1449 proc_spawn_sh(
char *str)
1456 status = spawnl(
P_NOWAIT, (shell ? shell :
"/bin/sh"),
"sh",
"-c", str, (
char*)
NULL);
1471 check_exec_redirect_fd(
VALUE v,
int iskey)
1482 else if (
id == id_out)
1484 else if (
id == id_err)
1504 else if (fd >= 3 && iskey) {
1525 VALUE fd = check_exec_redirect_fd(v, !
NIL_P(param));
1544 if (
id == id_close) {
1548 else if (
id == id_in) {
1552 else if (
id == id_out) {
1556 else if (
id == id_err) {
1569 val = check_exec_redirect_fd(
val, 0);
1579 path ==
ID2SYM(id_child)) {
1595 flags, perm,
Qnil));
1604 key = check_exec_redirect_fd(
key, 1);
1606 flags =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
1611 VALUE fd = check_exec_redirect_fd(v, 1);
1615 flags =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
1623 flags, perm,
Qnil));
1636 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 1637 static int rlimit_type_by_sym(
VALUE key);
1643 VALUE tmp, softlim, hardlim;
1675 switch (
TYPE(key)) {
1677 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 1679 int rtype = rlimit_type_by_sym(key);
1681 rb_execarg_addopt_rlimit(eargp, rtype, val);
1689 if (
id == id_pgroup) {
1696 else if (val ==
Qtrue)
1710 if (
id == id_new_pgroup) {
1719 if (
id == id_unsetenv_others) {
1726 else if (
id == id_chdir) {
1735 else if (
id == id_umask) {
1743 else if (
id == id_close_others) {
1750 else if (
id == id_in) {
1754 else if (
id == id_out) {
1758 else if (
id == id_err) {
1762 else if (
id == id_uid) {
1774 "uid option is unimplemented on this machine");
1777 else if (
id == id_gid) {
1789 "gid option is unimplemented on this machine");
1801 check_exec_redirect(key, val, eargp);
1833 VALUE execarg_obj = args[0];
1835 VALUE nonopts = args[1];
1880 maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->
fd_dup2);
1881 maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->
fd_close);
1882 maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->
fd_dup2_child);
1902 if (oldfd != lastfd) {
1920 rb_check_exec_options(
VALUE opthash,
VALUE execarg_obj)
1933 args[0] = execarg_obj;
1939 #ifdef ENV_IGNORECASE 1940 #define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0) 1942 #define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0) 1990 const char *
name = 0;
2007 for (i = 0; i <
argc; i++) {
2017 check_hash(
VALUE obj)
2029 rb_exec_getargs(
int *argc_p,
VALUE **argv_p,
int accept_shell,
VALUE *env_ret,
VALUE *opthash_ret)
2034 hash = check_hash((*argv_p)[*argc_p-1]);
2036 *opthash_ret = hash;
2042 hash = check_hash((*argv_p)[0]);
2049 prog = rb_check_argv(*argc_p, *argv_p);
2051 prog = (*argv_p)[0];
2052 if (accept_shell && *argc_p == 1) {
2067 compare_posix_sh(
const void *
key,
const void *el)
2070 int ret = strncmp(word->
ptr, el, word->
len);
2071 if (!ret && ((
const char *)el)[word->
len]) ret = -1;
2084 if (!
NIL_P(opthash)) {
2085 rb_check_exec_options(opthash, execarg_obj);
2095 eargp->
invoke.
sh.shell_script = prog;
2101 static const char posix_sh_cmds[][9] = {
2160 if (*p ==
' ' || *p ==
'\t') {
2161 if (first.
ptr && !first.
len) first.
len = p - first.
ptr;
2164 if (!first.
ptr) first.
ptr = p;
2166 if (!has_meta &&
strchr(
"*?{}[]<>()~&|\\$;'`\"\n#", *p))
2172 else if (*p ==
'/') {
2179 if (!has_meta && first.
ptr) {
2180 if (!first.
len) first.
len = p - first.
ptr;
2181 if (first.
len > 0 && first.
len <=
sizeof(posix_sh_cmds[0]) &&
2182 bsearch(&first, posix_sh_cmds,
numberof(posix_sh_cmds),
sizeof(posix_sh_cmds[0]), compare_posix_sh))
2194 while (*p ==
' ' || *p ==
'\t')
2198 while (*p && *p !=
' ' && *p !=
'\t')
2211 const char *abspath;
2212 const char *path_env = 0;
2215 path_env, fbuf,
sizeof(fbuf));
2227 for (i = 0; i <
argc; i++) {
2230 #ifdef DEFAULT_PROCESS_ENCODING 2240 const char *p, *ep, *null=
NULL;
2262 hide_obj(execarg_obj);
2284 prog = rb_exec_getargs(&argc, &argv, accept_shell, &env, &opthash);
2285 rb_exec_fillarg(prog, argc, argv, env, opthash, execarg_obj);
2316 static long run_exec_dup2_tmpbuf_size(
long n);
2327 open_func(
void *ptr)
2337 rb_execarg_parent_start1(
VALUE execarg_obj)
2340 int unsetenv_others;
2361 open_data.
fname = vpath;
2365 open_data.
err = EINTR;
2367 if (open_data.ret == -1) {
2368 if (open_data.err == EINTR) {
2374 fd2 = open_data.ret;
2399 VALUE envtbl, envp_str, envp_buf;
2401 if (unsetenv_others) {
2460 rb_protect(rb_execarg_parent_start1, execarg_obj, &state);
2468 execarg_parent_end(
VALUE execarg_obj)
2498 execarg_parent_end(execarg_obj);
2503 rb_exec_fail(
struct rb_execarg *eargp,
int err,
const char *errmsg)
2505 if (!errmsg || !*errmsg)
return;
2506 if (strcmp(errmsg,
"chdir") == 0) {
2514 rb_execarg_fail(
VALUE execarg_obj,
int err,
const char *errmsg)
2516 if (!errmsg || !*errmsg)
return;
2598 VALUE execarg_obj, fail_str;
2600 #define CHILD_ERRMSG_BUFLEN 80 2615 rb_exec_fail(eargp, err, errmsg);
2621 #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0) 2622 #define ERRMSG1(str, a) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a)); } while (0) 2623 #define ERRMSG2(str, a, b) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a), (b)); } while (0) 2625 static int fd_get_cloexec(
int fd,
char *errmsg,
size_t errmsg_buflen);
2626 static int fd_set_cloexec(
int fd,
char *errmsg,
size_t errmsg_buflen);
2627 static int fd_clear_cloexec(
int fd,
char *errmsg,
size_t errmsg_buflen);
2630 save_redirect_fd(
int fd,
struct rb_execarg *sargp,
char *errmsg,
size_t errmsg_buflen)
2633 VALUE newary, redirection;
2635 if (save_fd == -1) {
2647 cloexec = fd_get_cloexec(fd, errmsg, errmsg_buflen);
2664 intcmp(
const void *a,
const void *b)
2666 return *(
int*)a - *(
int*)b;
2670 intrcmp(
const void *a,
const void *b)
2672 return *(
int*)b - *(
int*)a;
2684 run_exec_dup2_tmpbuf_size(
long n)
2691 fd_get_cloexec(
int fd,
char *errmsg,
size_t errmsg_buflen)
2697 ERRMSG(
"fcntl(F_GETFD)");
2707 fd_set_cloexec(
int fd,
char *errmsg,
size_t errmsg_buflen)
2713 ERRMSG(
"fcntl(F_GETFD)");
2720 ERRMSG(
"fcntl(F_SETFD)");
2730 fd_clear_cloexec(
int fd,
char *errmsg,
size_t errmsg_buflen)
2736 ERRMSG(
"fcntl(F_GETFD)");
2743 ERRMSG(
"fcntl(F_SETFD)");
2764 for (i = 0; i < n; i++) {
2779 for (i = 0; i < n; i++) {
2786 while (pairs < found && (found-1)->
oldfd == newfd)
2788 while (found < pairs+n && found->
oldfd == newfd) {
2797 for (i = 0; i < n; i++) {
2799 while (j != -1 && pairs[j].
oldfd != -1 && pairs[j].
num_newer == 0) {
2800 if (save_redirect_fd(pairs[j].
newfd, sargp, errmsg, errmsg_buflen) < 0)
2808 fd_set_cloexec(pairs[j].newfd, errmsg, errmsg_buflen)) {
2812 pairs[j].
oldfd = -1;
2820 for (i = 0; i < n; i++) {
2822 if (pairs[i].
oldfd == -1)
2825 if (fd_clear_cloexec(pairs[i].
oldfd, errmsg, errmsg_buflen) == -1)
2827 pairs[i].
oldfd = -1;
2830 if (extra_fd == -1) {
2832 if (extra_fd == -1) {
2846 pairs[i].
oldfd = extra_fd;
2856 pairs[j].
oldfd = -1;
2860 if (extra_fd != -1) {
2876 run_exec_close(
VALUE ary,
char *errmsg,
size_t errmsg_buflen)
2895 run_exec_dup2_child(
VALUE ary,
struct rb_execarg *sargp,
char *errmsg,
size_t errmsg_buflen)
2905 if (save_redirect_fd(newfd, sargp, errmsg, errmsg_buflen) < 0)
2920 run_exec_pgroup(
const struct rb_execarg *eargp,
struct rb_execarg *sargp,
char *errmsg,
size_t errmsg_buflen)
2945 ret = setpgid(getpid(), pgroup);
2946 if (ret == -1)
ERRMSG(
"setpgid");
2951 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM) 2954 run_exec_rlimit(
VALUE ary,
struct rb_execarg *sargp,
char *errmsg,
size_t errmsg_buflen)
2963 if (getrlimit(rtype, &rlim) == -1) {
2968 RLIM2NUM(rlim.rlim_cur),
2969 RLIM2NUM(rlim.rlim_max)));
2978 if (setrlimit(rtype, &rlim) == -1) {
2987 #if !defined(HAVE_WORKING_FORK) 3016 #define chdir(p) rb_w32_uchdir(p) 3033 if (run_exec_pgroup(eargp, sargp, errmsg, errmsg_buflen) == -1)
3038 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM) 3041 if (run_exec_rlimit(obj, sargp, errmsg, errmsg_buflen) == -1)
3046 #if !defined(HAVE_WORKING_FORK) 3079 if (run_exec_dup2(obj, eargp->
dup2_tmpbuf, sargp, errmsg, errmsg_buflen) == -1)
3086 rb_warn(
"cannot close fd before spawn");
3088 if (run_exec_close(obj, errmsg, errmsg_buflen) == -1)
3093 #ifdef HAVE_WORKING_FORK 3101 if (run_exec_dup2_child(obj, sargp, errmsg, errmsg_buflen) == -1)
3152 #if !defined(HAVE_WORKING_FORK) 3153 struct rb_execarg sarg, *
const sargp = &sarg;
3166 char *abspath =
NULL;
3171 #if !defined(HAVE_WORKING_FORK) 3179 #ifdef HAVE_WORKING_FORK 3182 rb_exec_atfork(
void* arg,
char *errmsg,
size_t errmsg_buflen)
3188 #ifdef HAVE_WORKING_FORK 3189 #if SIZEOF_INT == SIZEOF_LONG 3190 #define proc_syswait (VALUE (*)(VALUE))rb_syswait 3201 move_fds_to_avoid_crash(
int *fdp,
int n,
VALUE fds)
3205 for (i = 0; i < n; i++) {
3224 pipe_nocrash(
int filedes[2],
VALUE fds)
3232 if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
3247 handle_fork_error(
int *status,
int *ep,
volatile int *try_gc_p)
3259 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 3262 if (!status && !ep) {
3268 if (status) *status = state;
3269 if (!state)
return 0;
3280 #define prefork() ( \ 3281 rb_io_flush(rb_stdout), \ 3282 rb_io_flush(rb_stderr) \ 3312 write_retry(
int fd,
const void *
buf,
size_t len)
3317 w = write(fd, buf, len);
3318 }
while (w < 0 &&
errno == EINTR);
3324 read_retry(
int fd,
void *buf,
size_t len)
3329 r = read(fd, buf, len);
3330 }
while (r < 0 &&
errno == EINTR);
3336 send_child_error(
int fd,
char *errmsg,
size_t errmsg_buflen)
3341 if (write_retry(fd, &err,
sizeof(err)) < 0) err =
errno;
3342 if (errmsg && 0 < errmsg_buflen) {
3343 errmsg[errmsg_buflen-1] =
'\0';
3344 errmsg_buflen =
strlen(errmsg);
3345 if (errmsg_buflen > 0 && write_retry(fd, errmsg, errmsg_buflen) < 0)
3351 recv_child_error(
int fd,
int *errp,
char *errmsg,
size_t errmsg_buflen)
3355 if ((size = read_retry(fd, &err,
sizeof(err))) < 0) {
3359 if (size ==
sizeof(err) &&
3360 errmsg && 0 < errmsg_buflen) {
3361 ssize_t ret = read_retry(fd, errmsg, errmsg_buflen-1);
3370 #ifdef HAVE_WORKING_VFORK 3371 #if !defined(HAVE_GETRESUID) && defined(HAVE_GETUIDX) 3374 getresuid(rb_uid_t *ruid, rb_uid_t *euid, rb_uid_t *suid)
3380 ret = getuidx(ID_SAVED);
3381 if (ret == (rb_uid_t)-1)
3386 #define HAVE_GETRESUID 3389 #if !defined(HAVE_GETRESGID) && defined(HAVE_GETGIDX) 3392 getresgid(rb_gid_t *rgid, rb_gid_t *egid, rb_gid_t *sgid)
3398 ret = getgidx(ID_SAVED);
3399 if (ret == (rb_gid_t)-1)
3404 #define HAVE_GETRESGID 3422 rb_uid_t ruid, euid;
3423 rb_gid_t rgid, egid;
3425 #if defined HAVE_ISSETUGID 3430 #ifdef HAVE_GETRESUID 3434 ret = getresuid(&ruid, &euid, &suid);
3445 if (euid == 0 || euid != ruid)
3448 #ifdef HAVE_GETRESGID 3452 ret = getresgid(&rgid, &egid, &sgid);
3470 struct child_handler_disabler_state
3477 disable_child_handler_before_fork(
struct child_handler_disabler_state *old)
3482 #ifdef HAVE_PTHREAD_SIGMASK 3483 ret = sigfillset(&all);
3487 ret = pthread_sigmask(SIG_SETMASK, &all, &old->sigmask);
3492 # pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous" 3495 #ifdef PTHREAD_CANCEL_DISABLE 3496 ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old->cancelstate);
3504 disable_child_handler_fork_parent(
struct child_handler_disabler_state *old)
3508 #ifdef PTHREAD_CANCEL_DISABLE 3509 ret = pthread_setcancelstate(old->cancelstate,
NULL);
3515 #ifdef HAVE_PTHREAD_SIGMASK 3516 ret = pthread_sigmask(SIG_SETMASK, &old->sigmask,
NULL);
3521 # pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous" 3527 disable_child_handler_fork_child(
struct child_handler_disabler_state *old,
char *errmsg,
size_t errmsg_buflen)
3532 for (sig = 1; sig <
NSIG; sig++) {
3533 sig_t handler = signal(sig, SIG_DFL);
3535 if (handler == SIG_ERR &&
errno == EINVAL) {
3538 if (handler == SIG_ERR) {
3539 ERRMSG(
"signal to obtain old action");
3543 if (sig == SIGPIPE) {
3548 if (handler == SIG_IGN) {
3549 signal(sig, SIG_IGN);
3553 ret = sigprocmask(SIG_SETMASK, &old->sigmask,
NULL);
3562 retry_fork_async_signal_safe(
int *status,
int *ep,
3563 int (*chfunc)(
void*,
char *,
size_t),
void *charg,
3564 char *errmsg,
size_t errmsg_buflen)
3567 volatile int try_gc = 1;
3568 struct child_handler_disabler_state old;
3572 disable_child_handler_before_fork(&old);
3573 #ifdef HAVE_WORKING_VFORK 3574 if (!has_privilege())
3584 ret = disable_child_handler_fork_child(&old, errmsg, errmsg_buflen);
3586 ret = chfunc(charg, errmsg, errmsg_buflen);
3589 send_child_error(ep[1], errmsg, errmsg_buflen);
3590 #if EXIT_SUCCESS == 127 3600 if (handle_fork_error(status, ep, &try_gc))
3607 char *errmsg,
size_t errmsg_buflen)
3614 if (status) *status = 0;
3616 if (pipe_nocrash(ep, fds))
return -1;
3617 pid = retry_fork_async_signal_safe(status, ep, chfunc, charg, errmsg, errmsg_buflen);
3621 error_occurred = recv_child_error(ep[0], &err, errmsg, errmsg_buflen);
3622 if (error_occurred) {
3636 retry_fork_ruby(
int *status,
struct child_handler_disabler_state *old)
3644 disable_child_handler_before_fork(old);
3653 if (handle_fork_error(status,
NULL, &try_gc))
3662 struct child_handler_disabler_state old;
3664 if (status) *status = 0;
3666 pid = retry_fork_ruby(status, &old);
3671 disable_child_handler_fork_parent(&old);
3678 #if defined(HAVE_WORKING_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD) 3729 #define rb_f_fork rb_f_notimplement 3733 exit_status_code(
VALUE status)
3746 #if EXIT_SUCCESS != 0 3772 istatus = exit_status_code(argv[0]);
3843 istatus = exit_status_code(argv[0]);
3872 if (!
NIL_P(errinfo)) {
3880 args[1] = args[0] = argv[0];
3898 #if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV 3911 for (i = 1; i <
argc; ++i) {
3912 p[argv[i] - start - 1] =
' ';
3922 rb_spawn_process(
struct rb_execarg *eargp,
char *errmsg,
size_t errmsg_buflen)
3925 #if !defined HAVE_WORKING_FORK || USE_SPAWNV 3928 # if !defined HAVE_SPAWNV 3933 #if defined HAVE_WORKING_FORK && !USE_SPAWNV 3946 # if defined HAVE_SPAWNV 3952 pid = proc_spawn_cmd(argv, prog, eargp);
3976 do_spawn_process(
VALUE arg)
3979 rb_execarg_parent_start1(argp->
execarg);
3985 rb_execarg_spawn(
VALUE execarg_obj,
char *errmsg,
size_t errmsg_buflen)
3993 execarg_parent_end, execarg_obj);
3997 rb_spawn_internal(
int argc,
const VALUE *argv,
char *errmsg,
size_t errmsg_buflen)
4002 return rb_execarg_spawn(execarg_obj, errmsg, errmsg_buflen);
4008 return rb_spawn_internal(argc, argv, errmsg, errmsg_buflen);
4014 return rb_spawn_internal(argc, argv,
NULL, 0);
4051 rb_f_system(
int argc,
VALUE *argv)
4056 #if defined(SIGCLD) && !defined(SIGCHLD) 4057 # define SIGCHLD SIGCLD 4061 RETSIGTYPE (*chfunc)(int);
4064 chfunc = signal(SIGCHLD, SIG_DFL);
4066 pid = rb_spawn_internal(argc, argv,
NULL, 0);
4067 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV) 4071 if (ret == (rb_pid_t)-1)
4072 rb_sys_fail(
"Another thread waited the process started by system().");
4076 signal(SIGCHLD, chfunc);
4355 rb_f_spawn(
int argc,
VALUE *argv)
4359 VALUE execarg_obj, fail_str;
4366 pid = rb_execarg_spawn(execarg_obj, errmsg,
sizeof(errmsg));
4370 rb_exec_fail(eargp, err, errmsg);
4374 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV) 4399 rb_f_sleep(
int argc,
VALUE *argv)
4412 end = time(0) - beg;
4418 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID) 4435 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID) 4446 #define proc_getpgrp rb_f_notimplement 4450 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)) 4468 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID) 4474 #define proc_setpgrp rb_f_notimplement 4478 #if defined(HAVE_GETPGID) 4499 #define proc_getpgid rb_f_notimplement 4515 rb_pid_t ipid, ipgrp;
4524 #define proc_setpgid rb_f_notimplement 4555 #define proc_getsid rb_f_notimplement 4559 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY)) 4560 #if !defined(HAVE_SETSID) 4561 static rb_pid_t ruby_setsid(
void);
4562 #define setsid() ruby_setsid() 4585 #if !defined(HAVE_SETSID) 4586 #define HAVE_SETSID 1 4594 #if defined(SETPGRP_VOID) 4600 ret = setpgrp(0, pid);
4602 if (ret == -1)
return -1;
4613 #define proc_setsid rb_f_notimplement 4617 #ifdef HAVE_GETPRIORITY 4638 int prio, iwhich, iwho;
4644 prio = getpriority(iwhich, iwho);
4649 #define proc_getpriority rb_f_notimplement 4653 #ifdef HAVE_GETPRIORITY 4669 int iwhich, iwho, iprio;
4675 if (setpriority(iwhich, iwho, iprio) < 0)
4680 #define proc_setpriority rb_f_notimplement 4683 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 4685 rlimit_resource_name2int(
const char *
name,
long len,
int casetype)
4689 #define RESCHECK(r) \ 4691 if (len == rb_strlen_lit(#r) && STRCASECMP(name, #r) == 0) { \ 4692 resource = RLIMIT_##r; \ 4726 #ifdef RLIMIT_MEMLOCK 4729 #ifdef RLIMIT_MSGQUEUE 4735 #ifdef RLIMIT_NOFILE 4750 #ifdef RLIMIT_RTPRIO 4753 #ifdef RLIMIT_RTTIME 4762 #ifdef RLIMIT_SBSIZE 4765 #ifdef RLIMIT_SIGPENDING 4766 RESCHECK(SIGPENDING);
4775 for (p = name; *p; p++)
4781 for (p = name; *p; p++)
4787 rb_bug(
"unexpected casetype");
4794 rlimit_type_by_hname(
const char *
name,
long len)
4796 return rlimit_resource_name2int(name, len, 0);
4800 rlimit_type_by_lname(
const char *name,
long len)
4802 return rlimit_resource_name2int(name, len, 1);
4812 static const char prefix[] =
"rlimit_";
4813 enum {prefix_len =
sizeof(prefix)-1};
4815 if (len > prefix_len && strncmp(prefix, rname, prefix_len) == 0) {
4816 rtype = rlimit_type_by_lname(rname + prefix_len, len - prefix_len);
4824 rlimit_resource_type(
VALUE rtype)
4831 switch (
TYPE(rtype)) {
4854 r = rlimit_type_by_hname(name, len);
4864 rlimit_resource_value(
VALUE rval)
4869 switch (
TYPE(rval)) {
4887 return NUM2RLIM(rval);
4890 #ifdef RLIM_INFINITY 4891 if (strcmp(name,
"INFINITY") == 0)
return RLIM_INFINITY;
4893 #ifdef RLIM_SAVED_MAX 4894 if (strcmp(name,
"SAVED_MAX") == 0)
return RLIM_SAVED_MAX;
4896 #ifdef RLIM_SAVED_CUR 4897 if (strcmp(name,
"SAVED_CUR") == 0)
return RLIM_SAVED_CUR;
4905 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM) 4931 if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
4934 return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
4937 #define proc_getrlimit rb_f_notimplement 4940 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) 4995 VALUE resource, rlim_cur, rlim_max;
5001 if (argc < 3 ||
NIL_P(rlim_max = argv[2]))
5002 rlim_max = rlim_cur;
5004 rlim.rlim_cur = rlimit_resource_value(rlim_cur);
5005 rlim.rlim_max = rlimit_resource_value(rlim_max);
5007 if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
5013 #define proc_setrlimit rb_f_notimplement 5016 static int under_uid_switch = 0;
5018 check_uid_switch(
void)
5020 if (under_uid_switch) {
5025 static int under_gid_switch = 0;
5027 check_gid_switch(
void)
5029 if (under_gid_switch) {
5045 #if defined(HAVE_PWD_H) 5048 # ifdef USE_GETPWNAM_R
5061 struct passwd *pwptr;
5062 #ifdef USE_GETPWNAM_R 5063 struct passwd pwbuf;
5068 getpw_buf_len = GETPW_R_SIZE_INIT;
5069 if (getpw_buf_len < 0) getpw_buf_len = GETPW_R_SIZE_DEFAULT;
5076 while ((e = getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) != 0) {
5077 if (e != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) {
5086 pwptr = getpwnam(usrname);
5089 #ifndef USE_GETPWNAM_R 5094 uid = pwptr->pw_uid;
5095 #ifndef USE_GETPWNAM_R 5102 # ifdef p_uid_from_name 5122 #if defined(HAVE_GRP_H) 5125 # ifdef USE_GETGRNAM_R
5138 struct group *grptr;
5139 #ifdef USE_GETGRNAM_R 5145 getgr_buf_len = GETGR_R_SIZE_INIT;
5146 if (getgr_buf_len < 0) getgr_buf_len = GETGR_R_SIZE_DEFAULT;
5153 while ((e = getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) != 0) {
5154 if (e != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) {
5162 #elif defined(HAVE_GETGRNAM) 5163 grptr = getgrnam(grpname);
5168 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT) 5173 gid = grptr->gr_gid;
5174 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT) 5181 # ifdef p_gid_from_name 5201 #if defined HAVE_SETUID 5219 #define p_sys_setuid rb_f_notimplement 5223 #if defined HAVE_SETRUID 5241 #define p_sys_setruid rb_f_notimplement 5245 #if defined HAVE_SETEUID 5263 #define p_sys_seteuid rb_f_notimplement 5267 #if defined HAVE_SETREUID 5282 rb_uid_t ruid, euid;
5292 #define p_sys_setreuid rb_f_notimplement 5296 #if defined HAVE_SETRESUID 5311 rb_uid_t ruid, euid, suid;
5318 if (setresuid(ruid, euid, suid) != 0)
rb_sys_fail(0);
5322 #define p_sys_setresuid rb_f_notimplement 5338 proc_getuid(
VALUE obj)
5345 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID) 5362 #if defined(HAVE_SETRESUID) 5364 #elif defined HAVE_SETREUID 5366 #elif defined HAVE_SETRUID 5368 #elif defined HAVE_SETUID 5381 #define proc_setuid rb_f_notimplement 5395 static rb_uid_t SAVED_USER_ID = -1;
5397 #ifdef BROKEN_SETREUID 5399 setreuid(rb_uid_t ruid, rb_uid_t euid)
5401 if (ruid != (rb_uid_t)-1 && ruid !=
getuid()) {
5402 if (euid == (rb_uid_t)-1) euid =
geteuid();
5403 if (
setuid(ruid) < 0)
return -1;
5405 if (euid != (rb_uid_t)-1 && euid !=
geteuid()) {
5406 if (
seteuid(euid) < 0)
return -1;
5435 #if defined(HAVE_SETRESUID) 5437 SAVED_USER_ID = uid;
5438 #elif defined(HAVE_SETUID) 5440 SAVED_USER_ID = uid;
5441 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 5443 if (SAVED_USER_ID == uid) {
5448 if (setreuid(-1, SAVED_USER_ID) < 0)
rb_sys_fail(0);
5449 if (setreuid(SAVED_USER_ID, 0) < 0)
rb_sys_fail(0);
5452 SAVED_USER_ID = uid;
5458 SAVED_USER_ID = uid;
5464 SAVED_USER_ID = uid;
5466 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID) 5468 if (SAVED_USER_ID == uid) {
5482 SAVED_USER_ID = uid;
5489 SAVED_USER_ID = uid;
5497 #if defined(HAVE_SETRESUID) 5498 if (setresuid((
getuid() == uid)? (rb_uid_t)-1: uid,
5499 (
geteuid() == uid)? (rb_uid_t)-1: uid,
5500 (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0)
rb_sys_fail(0);
5501 SAVED_USER_ID = uid;
5502 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 5503 if (SAVED_USER_ID == uid) {
5504 if (setreuid((
getuid() == uid)? (rb_uid_t)-1: uid,
5505 (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5508 else if (
getuid() != uid) {
5509 if (setreuid(uid, (
geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
5511 SAVED_USER_ID = uid;
5515 SAVED_USER_ID = uid;
5519 if (setreuid(-1, SAVED_USER_ID) < 0)
rb_sys_fail(0);
5520 if (setreuid(SAVED_USER_ID, uid) < 0)
rb_sys_fail(0);
5521 SAVED_USER_ID = uid;
5524 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID) 5525 if (SAVED_USER_ID == uid) {
5532 SAVED_USER_ID = uid;
5536 SAVED_USER_ID = uid;
5540 else if (
getuid() == uid) {
5543 SAVED_USER_ID = uid;
5549 #elif defined HAVE_44BSD_SETUID 5553 SAVED_USER_ID = uid;
5558 #elif defined HAVE_SETEUID 5559 if (
getuid() == uid && SAVED_USER_ID == uid) {
5565 #elif defined HAVE_SETUID 5566 if (
getuid() == uid && SAVED_USER_ID == uid) {
5581 #if defined HAVE_SETGID 5599 #define p_sys_setgid rb_f_notimplement 5603 #if defined HAVE_SETRGID 5621 #define p_sys_setrgid rb_f_notimplement 5625 #if defined HAVE_SETEGID 5643 #define p_sys_setegid rb_f_notimplement 5647 #if defined HAVE_SETREGID 5662 rb_gid_t rgid, egid;
5672 #define p_sys_setregid rb_f_notimplement 5675 #if defined HAVE_SETRESGID 5690 rb_gid_t rgid, egid, sgid;
5697 if (setresgid(rgid, egid, sgid) != 0)
rb_sys_fail(0);
5701 #define p_sys_setresgid rb_f_notimplement 5705 #if defined HAVE_ISSETUGID 5729 #define p_sys_issetugid rb_f_notimplement 5745 proc_getgid(
VALUE obj)
5752 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID) 5768 #if defined(HAVE_SETRESGID) 5770 #elif defined HAVE_SETREGID 5772 #elif defined HAVE_SETRGID 5774 #elif defined HAVE_SETGID 5787 #define proc_setgid rb_f_notimplement 5791 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX) 5812 static int _maxgroups = -1;
5814 get_sc_ngroups_max(
void)
5816 #ifdef _SC_NGROUPS_MAX 5817 return (
int)sysconf(_SC_NGROUPS_MAX);
5818 #elif defined(NGROUPS_MAX) 5819 return (
int)NGROUPS_MAX;
5827 if (_maxgroups < 0) {
5828 _maxgroups = get_sc_ngroups_max();
5839 #ifdef HAVE_GETGROUPS 5858 ngroups = getgroups(0,
NULL);
5862 groups =
ALLOCV_N(rb_gid_t, tmp, ngroups);
5864 ngroups = getgroups(ngroups, groups);
5869 for (i = 0; i < ngroups; i++)
5877 #define proc_getgroups rb_f_notimplement 5881 #ifdef HAVE_SETGROUPS 5906 if (ngroups > maxgroups())
5909 groups =
ALLOCV_N(rb_gid_t, tmp, ngroups);
5911 for (i = 0; i < ngroups; i++) {
5918 if (setgroups(ngroups, groups) == -1)
5926 #define proc_setgroups rb_f_notimplement 5930 #ifdef HAVE_INITGROUPS 5957 #define proc_initgroups rb_f_notimplement 5960 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX) 5977 #define proc_getmaxgroups rb_f_notimplement 5980 #ifdef HAVE_SETGROUPS 5993 int ngroups_max = get_sc_ngroups_max();
6001 if (ngroups_max > 0 && ngroups > ngroups_max)
6002 ngroups = ngroups_max;
6004 _maxgroups = ngroups;
6009 #define proc_setmaxgroups rb_f_notimplement 6012 #if defined(HAVE_DAEMON) || (defined(HAVE_WORKING_FORK) && defined(HAVE_SETSID)) 6013 static int rb_daemon(
int nochdir,
int noclose);
6035 case 2: noclose =
RTEST(argv[1]);
6036 case 1: nochdir =
RTEST(argv[0]);
6040 n = rb_daemon(nochdir, noclose);
6046 rb_daemon(
int nochdir,
int noclose)
6051 err = daemon(nochdir, noclose);
6057 #define fork_daemon() \ 6058 switch (rb_fork_ruby(NULL)) { \ 6059 case -1: return -1; \ 6060 case 0: rb_thread_atfork(); break; \ 6061 default: _exit(EXIT_SUCCESS); \ 6066 if (setsid() < 0)
return -1;
6074 if (!noclose && (n =
rb_cloexec_open(
"/dev/null", O_RDWR, 0)) != -1) {
6086 #define proc_daemon rb_f_notimplement 6099 static rb_gid_t SAVED_GROUP_ID = -1;
6101 #ifdef BROKEN_SETREGID 6103 setregid(rb_gid_t rgid, rb_gid_t egid)
6105 if (rgid != (rb_gid_t)-1 && rgid !=
getgid()) {
6106 if (egid == (rb_gid_t)-1) egid =
getegid();
6107 if (
setgid(rgid) < 0)
return -1;
6109 if (egid != (rb_gid_t)-1 && egid !=
getegid()) {
6110 if (
setegid(egid) < 0)
return -1;
6139 #if defined(HAVE_SETRESGID) 6141 SAVED_GROUP_ID = gid;
6142 #elif defined HAVE_SETGID 6144 SAVED_GROUP_ID = gid;
6145 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6147 if (SAVED_GROUP_ID == gid) {
6152 if (setregid(-1, SAVED_GROUP_ID) < 0)
rb_sys_fail(0);
6153 if (setregid(SAVED_GROUP_ID, 0) < 0)
rb_sys_fail(0);
6156 SAVED_GROUP_ID = gid;
6162 SAVED_GROUP_ID = gid;
6168 SAVED_GROUP_ID = gid;
6170 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID) 6172 if (SAVED_GROUP_ID == gid) {
6187 SAVED_GROUP_ID = gid;
6194 SAVED_GROUP_ID = gid;
6201 #if defined(HAVE_SETRESGID) 6202 if (setresgid((
getgid() == gid)? (rb_gid_t)-1: gid,
6203 (
getegid() == gid)? (rb_gid_t)-1: gid,
6204 (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0)
rb_sys_fail(0);
6205 SAVED_GROUP_ID = gid;
6206 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6207 if (SAVED_GROUP_ID == gid) {
6208 if (setregid((
getgid() == gid)? (rb_uid_t)-1: gid,
6209 (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
6212 else if (
getgid() != gid) {
6213 if (setregid(gid, (
getegid() == gid)? (rb_uid_t)-1: gid) < 0)
6215 SAVED_GROUP_ID = gid;
6219 SAVED_GROUP_ID = gid;
6223 if (setregid(-1, SAVED_GROUP_ID) < 0)
rb_sys_fail(0);
6224 if (setregid(SAVED_GROUP_ID, gid) < 0)
rb_sys_fail(0);
6225 SAVED_GROUP_ID = gid;
6228 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID) 6229 if (SAVED_GROUP_ID == gid) {
6236 SAVED_GROUP_ID = gid;
6240 SAVED_GROUP_ID = gid;
6244 else if (
getgid() == gid) {
6247 SAVED_GROUP_ID = gid;
6253 #elif defined HAVE_44BSD_SETGID 6257 SAVED_GROUP_ID = gid;
6262 #elif defined HAVE_SETEGID 6263 if (
getgid() == gid && SAVED_GROUP_ID == gid) {
6269 #elif defined HAVE_SETGID 6270 if (
getgid() == gid && SAVED_GROUP_ID == gid) {
6297 proc_geteuid(
VALUE obj)
6303 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS) 6305 proc_seteuid(rb_uid_t uid)
6307 #if defined(HAVE_SETRESUID) 6309 #elif defined HAVE_SETREUID 6311 #elif defined HAVE_SETEUID 6313 #elif defined HAVE_SETUID 6326 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) 6343 #define proc_seteuid_m rb_f_notimplement 6347 rb_seteuid_core(rb_uid_t euid)
6349 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)) 6355 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)) 6359 #if defined(HAVE_SETRESUID) 6362 SAVED_USER_ID = euid;
6367 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 6372 SAVED_USER_ID = euid;
6374 #elif defined HAVE_SETEUID 6376 #elif defined HAVE_SETUID 6421 proc_getegid(
VALUE obj)
6428 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS) 6440 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) 6446 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) 6450 #if defined(HAVE_SETRESGID) 6452 #elif defined HAVE_SETREGID 6454 #elif defined HAVE_SETEGID 6456 #elif defined HAVE_SETGID 6470 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) 6471 #define proc_setegid_m proc_setegid 6473 #define proc_setegid_m rb_f_notimplement 6477 rb_setegid_core(rb_gid_t egid)
6479 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)) 6485 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)) 6489 #if defined(HAVE_SETRESGID) 6492 SAVED_GROUP_ID = egid;
6497 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6502 SAVED_GROUP_ID = egid;
6504 #elif defined HAVE_SETEGID 6506 #elif defined HAVE_SETGID 6548 p_uid_exchangeable(
void)
6550 #if defined(HAVE_SETRESUID) 6552 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 6573 p_uid_exchange(
VALUE obj)
6576 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)) 6583 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)) 6587 #if defined(HAVE_SETRESUID) 6588 if (setresuid(euid, uid, uid) < 0)
rb_sys_fail(0);
6589 SAVED_USER_ID = uid;
6590 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID) 6592 SAVED_USER_ID = uid;
6610 p_gid_exchangeable(
void)
6612 #if defined(HAVE_SETRESGID) 6614 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6635 p_gid_exchange(
VALUE obj)
6638 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)) 6645 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)) 6649 #if defined(HAVE_SETRESGID) 6650 if (setresgid(egid, gid, gid) < 0)
rb_sys_fail(0);
6651 SAVED_GROUP_ID = gid;
6652 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID) 6654 SAVED_GROUP_ID = gid;
6673 p_uid_have_saved_id(
void)
6675 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS) 6683 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS) 6685 p_uid_sw_ensure(rb_uid_t
id)
6687 under_uid_switch = 0;
6688 id = rb_seteuid_core(
id);
6707 p_uid_switch(
VALUE obj)
6719 under_uid_switch = 1;
6726 else if (euid != SAVED_USER_ID) {
6727 proc_seteuid(SAVED_USER_ID);
6729 under_uid_switch = 1;
6744 p_uid_sw_ensure(
VALUE obj)
6746 under_uid_switch = 0;
6747 return p_uid_exchange(obj);
6751 p_uid_switch(
VALUE obj)
6763 p_uid_exchange(obj);
6765 under_uid_switch = 1;
6787 p_gid_have_saved_id(
void)
6789 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS) 6796 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS) 6798 p_gid_sw_ensure(rb_gid_t
id)
6800 under_gid_switch = 0;
6801 id = rb_setegid_core(
id);
6820 p_gid_switch(
VALUE obj)
6832 under_gid_switch = 1;
6839 else if (egid != SAVED_GROUP_ID) {
6840 proc_setegid(obj,
GIDT2NUM(SAVED_GROUP_ID));
6842 under_gid_switch = 1;
6857 p_gid_sw_ensure(
VALUE obj)
6859 under_gid_switch = 0;
6860 return p_gid_exchange(obj);
6864 p_gid_switch(
VALUE obj)
6876 p_gid_exchange(obj);
6878 under_gid_switch = 1;
6888 #if defined(HAVE_TIMES) 6893 #ifdef HAVE__SC_CLK_TCK 6894 (double)sysconf(_SC_CLK_TCK);
6924 #if defined(RUSAGE_SELF) && defined(RUSAGE_CHILDREN) 6925 struct rusage usage_s, usage_c;
6927 if (
getrusage(RUSAGE_SELF, &usage_s) != 0 ||
getrusage(RUSAGE_CHILDREN, &usage_c) != 0)
6929 utime =
DBL2NUM((
double)usage_s.ru_utime.tv_sec + (
double)usage_s.ru_utime.tv_usec/1e6);
6930 stime =
DBL2NUM((
double)usage_s.ru_stime.tv_sec + (
double)usage_s.ru_stime.tv_usec/1e6);
6931 cutime =
DBL2NUM((
double)usage_c.ru_utime.tv_sec + (
double)usage_c.ru_utime.tv_usec/1e6);
6932 cstime =
DBL2NUM((
double)usage_c.ru_stime.tv_sec + (
double)usage_c.ru_stime.tv_usec/1e6);
6934 const double hertz = get_clk_tck();
6943 ret =
rb_struct_new(rb_cProcessTms, utime, stime, cutime, cstime);
6951 #define rb_proc_times rb_f_notimplement 6954 #ifdef HAVE_LONG_LONG 6956 #define TIMETICK_INT_MIN LLONG_MIN 6957 #define TIMETICK_INT_MAX LLONG_MAX 6958 #define TIMETICK_INT2NUM(v) LL2NUM(v) 6959 #define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_LONG_P(a, b) 6962 #define TIMETICK_INT_MIN LONG_MIN 6963 #define TIMETICK_INT_MAX LONG_MAX 6964 #define TIMETICK_INT2NUM(v) LONG2NUM(v) 6965 #define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_P(a, b) 6968 CONSTFUNC(
static timetick_int_t gcd_timetick_int(timetick_int_t, timetick_int_t));
6969 static timetick_int_t
6970 gcd_timetick_int(timetick_int_t a, timetick_int_t b)
6990 reduce_fraction(timetick_int_t *np, timetick_int_t *
dp)
6992 timetick_int_t gcd = gcd_timetick_int(*np, *dp);
7000 reduce_factors(timetick_int_t *numerators,
int num_numerators,
7001 timetick_int_t *denominators,
int num_denominators)
7004 for (i = 0; i < num_numerators; i++) {
7005 if (numerators[i] == 1)
7007 for (j = 0; j < num_denominators; j++) {
7008 if (denominators[j] == 1)
7010 reduce_fraction(&numerators[i], &denominators[j]);
7021 timetick2dblnum(
struct timetick *ttp,
7022 timetick_int_t *numerators,
int num_numerators,
7023 timetick_int_t *denominators,
int num_denominators)
7028 reduce_factors(numerators, num_numerators,
7029 denominators, num_denominators);
7033 for (i = 0; i < num_numerators; i++)
7035 for (i = 0; i < num_denominators; i++)
7036 d /= denominators[i];
7042 timetick2dblnum_reciprocal(
struct timetick *ttp,
7043 timetick_int_t *numerators,
int num_numerators,
7044 timetick_int_t *denominators,
int num_denominators)
7049 reduce_factors(numerators, num_numerators,
7050 denominators, num_denominators);
7053 for (i = 0; i < num_denominators; i++)
7054 d *= denominators[i];
7055 for (i = 0; i < num_numerators; i++)
7062 #define NDIV(x,y) (-(-((x)+1)/(y))-1) 7063 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d)) 7066 timetick2integer(
struct timetick *ttp,
7067 timetick_int_t *numerators,
int num_numerators,
7068 timetick_int_t *denominators,
int num_denominators)
7073 reduce_factors(numerators, num_numerators,
7074 denominators, num_denominators);
7079 for (i = 0; i < num_numerators; i++) {
7080 timetick_int_t factor = numerators[i];
7085 for (i = 0; i < num_denominators; i++) {
7086 t =
DIV(t, denominators[i]);
7095 for (i = 0; i < num_numerators; i++) {
7096 timetick_int_t factor = numerators[i];
7101 for (i = 0; i < num_denominators; i++) {
7108 make_clock_result(
struct timetick *ttp,
7109 timetick_int_t *numerators,
int num_numerators,
7110 timetick_int_t *denominators,
int num_denominators,
7113 if (unit ==
ID2SYM(id_nanosecond)) {
7114 numerators[num_numerators++] = 1000000000;
7115 return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7117 else if (unit ==
ID2SYM(id_microsecond)) {
7118 numerators[num_numerators++] = 1000000;
7119 return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7121 else if (unit ==
ID2SYM(id_millisecond)) {
7122 numerators[num_numerators++] = 1000;
7123 return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7125 else if (unit ==
ID2SYM(id_second)) {
7126 return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
7128 else if (unit ==
ID2SYM(id_float_microsecond)) {
7129 numerators[num_numerators++] = 1000000;
7130 return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7132 else if (unit ==
ID2SYM(id_float_millisecond)) {
7133 numerators[num_numerators++] = 1000;
7134 return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7136 else if (
NIL_P(unit) || unit ==
ID2SYM(id_float_second)) {
7137 return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
7144 static mach_timebase_info_data_t *
7145 get_mach_timebase_info(
void)
7147 static mach_timebase_info_data_t sTimebaseInfo;
7149 if ( sTimebaseInfo.denom == 0 ) {
7150 (void) mach_timebase_info(&sTimebaseInfo);
7153 return &sTimebaseInfo;
7289 timetick_int_t numerators[2];
7290 timetick_int_t denominators[2];
7291 int num_numerators = 0;
7292 int num_denominators = 0;
7295 VALUE clk_id = argv[0];
7305 #define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ID2SYM(id_GETTIMEOFDAY_BASED_CLOCK_REALTIME) 7313 denominators[num_denominators++] = 1000000000;
7317 #define RUBY_TIME_BASED_CLOCK_REALTIME ID2SYM(id_TIME_BASED_CLOCK_REALTIME) 7321 if (t == (time_t)-1)
7325 denominators[num_denominators++] = 1000000000;
7330 #define RUBY_TIMES_BASED_CLOCK_MONOTONIC \ 7331 ID2SYM(id_TIMES_BASED_CLOCK_MONOTONIC) 7332 if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
7337 if (c == (clock_t)-1)
7340 tt.
count = (int32_t)(uc % 1000000000);
7342 denominators[num_denominators++] = get_clk_tck();
7348 #define RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID \ 7349 ID2SYM(id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) 7350 if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7351 struct rusage usage;
7356 tt.
giga_count = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
7357 usec = (int32_t)(usage.ru_utime.tv_usec + usage.ru_stime.tv_usec);
7358 if (1000000 <= usec) {
7362 tt.
count = usec * 1000;
7363 denominators[num_denominators++] = 1000000000;
7369 #define RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID \ 7370 ID2SYM(id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) 7371 if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7374 if (times(&buf) == (clock_t)-1)
7378 tt.
count = (int32_t)((utime % 1000000000) + (stime % 1000000000));
7379 tt.
giga_count = (utime / 1000000000) + (stime / 1000000000);
7380 if (1000000000 <= tt.
count) {
7381 tt.
count -= 1000000000;
7384 denominators[num_denominators++] = get_clk_tck();
7389 #define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID \ 7390 ID2SYM(id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID) 7396 if (c == (clock_t)-1)
7399 tt.
count = (int32_t)(uc % 1000000000);
7401 denominators[num_denominators++] = CLOCKS_PER_SEC;
7406 #define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) 7407 if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
7408 mach_timebase_info_data_t *info = get_mach_timebase_info();
7410 tt.
count = (int32_t)(t % 1000000000);
7412 numerators[num_numerators++] = info->numer;
7413 denominators[num_denominators++] = info->denom;
7414 denominators[num_denominators++] = 1000000000;
7420 #if defined(HAVE_CLOCK_GETTIME) 7423 c = NUM2CLOCKID(clk_id);
7429 denominators[num_denominators++] = 1000000000;
7437 return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
7482 timetick_int_t numerators[2];
7483 timetick_int_t denominators[2];
7484 int num_numerators = 0;
7485 int num_denominators = 0;
7488 VALUE clk_id = argv[0];
7491 #ifdef RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME 7495 denominators[num_denominators++] = 1000000000;
7500 #ifdef RUBY_TIME_BASED_CLOCK_REALTIME 7504 denominators[num_denominators++] = 1000000000;
7509 #ifdef RUBY_TIMES_BASED_CLOCK_MONOTONIC 7510 if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
7513 denominators[num_denominators++] = get_clk_tck();
7518 #ifdef RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID 7519 if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7522 denominators[num_denominators++] = 1000000000;
7527 #ifdef RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID 7528 if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
7531 denominators[num_denominators++] = get_clk_tck();
7536 #ifdef RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID 7540 denominators[num_denominators++] = CLOCKS_PER_SEC;
7545 #ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC 7546 if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
7547 mach_timebase_info_data_t *info = get_mach_timebase_info();
7550 numerators[num_numerators++] = info->numer;
7551 denominators[num_denominators++] = info->denom;
7552 denominators[num_denominators++] = 1000000000;
7558 #if defined(HAVE_CLOCK_GETRES) 7566 denominators[num_denominators++] = 1000000000;
7574 if (unit ==
ID2SYM(id_hertz)) {
7575 return timetick2dblnum_reciprocal(&tt, numerators, num_numerators, denominators, num_denominators);
7578 return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
7597 #define rb_intern(str) rb_intern_const(str) 7681 #ifdef HAVE_GETPRIORITY 7692 #if defined(RLIM2NUM) && defined(RLIM_INFINITY) 7694 VALUE inf = RLIM2NUM(RLIM_INFINITY);
7695 #ifdef RLIM_SAVED_MAX 7697 VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
7704 #ifdef RLIM_SAVED_CUR 7706 VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
7747 #ifdef RLIMIT_MEMLOCK 7754 #ifdef RLIMIT_MSGQUEUE 7769 #ifdef RLIMIT_NOFILE 7792 #ifdef RLIMIT_RTPRIO 7799 #ifdef RLIMIT_RTTIME 7807 #ifdef RLIMIT_SBSIZE 7812 #ifdef RLIMIT_SIGPENDING 7847 #ifdef CLOCK_REALTIME 7850 #elif defined(RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME) 7854 #ifdef CLOCK_MONOTONIC 7857 #elif defined(RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) 7859 rb_define_const(rb_mProcess,
"CLOCK_MONOTONIC", RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC);
7861 #ifdef CLOCK_PROCESS_CPUTIME_ID 7863 rb_define_const(rb_mProcess,
"CLOCK_PROCESS_CPUTIME_ID", CLOCKID2NUM(CLOCK_PROCESS_CPUTIME_ID));
7864 #elif defined(RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) 7866 rb_define_const(rb_mProcess,
"CLOCK_PROCESS_CPUTIME_ID", RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID);
7868 #ifdef CLOCK_THREAD_CPUTIME_ID 7870 rb_define_const(rb_mProcess,
"CLOCK_THREAD_CPUTIME_ID", CLOCKID2NUM(CLOCK_THREAD_CPUTIME_ID));
7872 #ifdef CLOCK_VIRTUAL 7874 rb_define_const(rb_mProcess,
"CLOCK_VIRTUAL", CLOCKID2NUM(CLOCK_VIRTUAL));
7880 #ifdef CLOCK_REALTIME_FAST 7882 rb_define_const(rb_mProcess,
"CLOCK_REALTIME_FAST", CLOCKID2NUM(CLOCK_REALTIME_FAST));
7884 #ifdef CLOCK_REALTIME_PRECISE 7886 rb_define_const(rb_mProcess,
"CLOCK_REALTIME_PRECISE", CLOCKID2NUM(CLOCK_REALTIME_PRECISE));
7888 #ifdef CLOCK_REALTIME_COARSE 7890 rb_define_const(rb_mProcess,
"CLOCK_REALTIME_COARSE", CLOCKID2NUM(CLOCK_REALTIME_COARSE));
7892 #ifdef CLOCK_REALTIME_ALARM 7894 rb_define_const(rb_mProcess,
"CLOCK_REALTIME_ALARM", CLOCKID2NUM(CLOCK_REALTIME_ALARM));
7896 #ifdef CLOCK_MONOTONIC_FAST 7898 rb_define_const(rb_mProcess,
"CLOCK_MONOTONIC_FAST", CLOCKID2NUM(CLOCK_MONOTONIC_FAST));
7900 #ifdef CLOCK_MONOTONIC_PRECISE 7902 rb_define_const(rb_mProcess,
"CLOCK_MONOTONIC_PRECISE", CLOCKID2NUM(CLOCK_MONOTONIC_PRECISE));
7904 #ifdef CLOCK_MONOTONIC_RAW 7906 rb_define_const(rb_mProcess,
"CLOCK_MONOTONIC_RAW", CLOCKID2NUM(CLOCK_MONOTONIC_RAW));
7908 #ifdef CLOCK_MONOTONIC_RAW_APPROX 7910 rb_define_const(rb_mProcess,
"CLOCK_MONOTONIC_RAW_APPROX", CLOCKID2NUM(CLOCK_MONOTONIC_RAW_APPROX));
7912 #ifdef CLOCK_MONOTONIC_COARSE 7914 rb_define_const(rb_mProcess,
"CLOCK_MONOTONIC_COARSE", CLOCKID2NUM(CLOCK_MONOTONIC_COARSE));
7916 #ifdef CLOCK_BOOTTIME 7918 rb_define_const(rb_mProcess,
"CLOCK_BOOTTIME", CLOCKID2NUM(CLOCK_BOOTTIME));
7920 #ifdef CLOCK_BOOTTIME_ALARM 7922 rb_define_const(rb_mProcess,
"CLOCK_BOOTTIME_ALARM", CLOCKID2NUM(CLOCK_BOOTTIME_ALARM));
7926 rb_define_const(rb_mProcess,
"CLOCK_UPTIME", CLOCKID2NUM(CLOCK_UPTIME));
7928 #ifdef CLOCK_UPTIME_FAST 7930 rb_define_const(rb_mProcess,
"CLOCK_UPTIME_FAST", CLOCKID2NUM(CLOCK_UPTIME_FAST));
7932 #ifdef CLOCK_UPTIME_PRECISE 7934 rb_define_const(rb_mProcess,
"CLOCK_UPTIME_PRECISE", CLOCKID2NUM(CLOCK_UPTIME_PRECISE));
7936 #ifdef CLOCK_UPTIME_RAW 7938 rb_define_const(rb_mProcess,
"CLOCK_UPTIME_RAW", CLOCKID2NUM(CLOCK_UPTIME_RAW));
7940 #ifdef CLOCK_UPTIME_RAW_APPROX 7942 rb_define_const(rb_mProcess,
"CLOCK_UPTIME_RAW_APPROX", CLOCKID2NUM(CLOCK_UPTIME_RAW_APPROX));
7946 rb_define_const(rb_mProcess,
"CLOCK_SECOND", CLOCKID2NUM(CLOCK_SECOND));
7951 #if defined(HAVE_TIMES) || defined(_WIN32) 7980 #ifdef p_uid_from_name 7983 #ifdef p_gid_from_name 8026 id_new_pgroup =
rb_intern(
"new_pgroup");
8028 id_unsetenv_others =
rb_intern(
"unsetenv_others");
8031 id_close_others =
rb_intern(
"close_others");
8033 id_nanosecond =
rb_intern(
"nanosecond");
8034 id_microsecond =
rb_intern(
"microsecond");
8035 id_millisecond =
rb_intern(
"millisecond");
8037 id_float_microsecond =
rb_intern(
"float_microsecond");
8038 id_float_millisecond =
rb_intern(
"float_millisecond");
8039 id_float_second =
rb_intern(
"float_second");
8040 id_GETTIMEOFDAY_BASED_CLOCK_REALTIME =
rb_intern(
"GETTIMEOFDAY_BASED_CLOCK_REALTIME");
8041 id_TIME_BASED_CLOCK_REALTIME =
rb_intern(
"TIME_BASED_CLOCK_REALTIME");
8043 id_TIMES_BASED_CLOCK_MONOTONIC =
rb_intern(
"TIMES_BASED_CLOCK_MONOTONIC");
8044 id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID =
rb_intern(
"TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID");
8047 id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID =
rb_intern(
"GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID");
8049 id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID =
rb_intern(
"CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID");
8051 id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC =
rb_intern(
"MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC");
#define RBASIC_CLEAR_CLASS(obj)
struct timeval rb_time_interval(VALUE num)
void rb_syswait(rb_pid_t pid)
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
#define RUBY_VM_CHECK_INTS(th)
#define redirect_close(fd)
RUBY_EXTERN VALUE rb_cData
void rb_thread_atfork(void)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
void rb_warn(const char *fmt,...)
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
void rb_bug(const char *fmt,...)
VALUE rb_ary_entry(VALUE ary, long offset)
int gettimeofday(struct timeval *, struct timezone *)
void rb_syserr_fail(int e, const char *mesg)
#define RUBY_TYPED_FREE_IMMEDIATELY
size_t strlen(const char *)
unsigned int unsigned_clock_t
struct spawn_args::@92 errmsg
void rb_update_max_fd(int fd)
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
#define RB_OBJ_WRITTEN(a, oldv, b)
CONSTFUNC(static timetick_int_t gcd_timetick_int(timetick_int_t, timetick_int_t))
void rb_undef_alloc_func(VALUE)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
void rb_syserr_fail_str(int e, VALUE mesg)
int rb_block_given_p(void)
Determines if the current method is given a block.
#define RUBY_TIME_BASED_CLOCK_REALTIME
int rb_io_modestr_oflags(const char *modestr)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_f_exit(int argc, const VALUE *argv)
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
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)
int rb_env_path_tainted(void)
#define TypedData_Get_Struct(obj, type, data_type, sval)
#define before_fork_ruby()
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
unsigned unsetenv_others_given
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
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)
#define RB_SPECIAL_CONST_P(x)
#define redirect_cloexec_dup2(oldfd, newfd)
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)
void rb_str_set_len(VALUE, long)
#define RBASIC_SET_CLASS(obj, cls)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_ivar_get(VALUE, ID)
rb_pid_t rb_waitpid(rb_pid_t pid, int *st, int flags)
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
#define after_fork_ruby()
#define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
#define MUL_OVERFLOW_TIMETICK_P(a, b)
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
void rb_gc_mark(VALUE ptr)
VALUE rb_hash_lookup(VALUE hash, VALUE key)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
An equivalent to ensure clause.
#define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell)
VALUE rb_str_tmp_new(long)
void rb_undef_method(VALUE klass, const char *name)
#define GetOpenFile(obj, fp)
VALUE rb_struct_define_under(VALUE, const char *,...)
void rb_thread_start_timer_thread(void)
VALUE rb_thread_local_aref(VALUE, ID)
VALUE rb_f_kill(int, const VALUE *)
VALUE rb_str_buf_cat(VALUE, const char *, long)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
unsigned unsetenv_others_do
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)
unsigned long long uint64_t
void rb_thread_sleep(int)
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false
void rb_execarg_parent_start(VALUE execarg_obj)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_str_encode_ospath(VALUE path)
VALUE rb_f_exec(int argc, const VALUE *argv)
RUBY_EXTERN VALUE rb_cObject
void rb_async_bug_errno(const char *mesg, int errno_arg)
#define proc_getmaxgroups
const char * ruby_signal_name(int)
VALUE rb_io_check_io(VALUE io)
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_str_buf_cat2(VALUE, const char *)
struct rb_execarg::@81::@83 cmd
#define TIMETICK_INT2NUM(v)
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)
void rb_notimplement(void)
struct rb_execarg::@81::@82 sh
void rb_thread_stop_timer_thread(void)
#define ALLOCV_N(type, v, n)
mode_t umask(mode_t mask)
int rb_cloexec_dup2(int oldfd, int newfd)
#define MEMCPY(p1, p2, type, n)
union rb_execarg::@81 invoke
void ruby_stop(int ex)
Calls ruby_cleanup() and exits the process.
void InitVM_process(void)
void rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
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)
rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
VALUE rb_str_resize(VALUE, long)
void rb_sys_fail(const char *mesg)
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.
timetick_int_t giga_count
unsigned close_others_given
VALUE rb_sprintf(const char *format,...)
#define parent_redirect_close(fd)
void rb_str_modify_expand(VALUE, long)
VALUE rb_ivar_set(VALUE, ID, VALUE)
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
unsigned new_pgroup_given
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
RUBY_EXTERN VALUE rb_cThread
void rb_execarg_parent_end(VALUE execarg_obj)
rb_pid_t rb_w32_uaspawn(int, const char *, char *const *)
#define CHILD_ERRMSG_BUFLEN
const char * rb_class2name(VALUE)
char * strchr(char *, char)
VALUE rb_io_puts(int, const VALUE *, VALUE)
int clock_gettime(clockid_t, struct timespec *)
#define proc_setmaxgroups
VALUE rb_str_new_cstr(const char *)
#define RARRAY_LENINT(ary)
int rb_reserved_fd_p(int fd)
register unsigned int len
VALUE rb_define_module_under(VALUE outer, const char *name)
#define StringValueCStr(v)
void rb_thread_wait_for(struct timeval)
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
#define RARRAY_ASET(a, i, v)
#define try_with_sh(prog, argv, envp)
RUBY_EXTERN VALUE rb_stderr
#define UNLIMITED_ARGUMENTS
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)
#define redirect_dup2(oldfd, newfd)
int getrusage(int who, struct rusage *usage)
VALUE rb_check_array_type(VALUE ary)
rb_pid_t rb_spawn(int argc, const VALUE *argv)
VALUE rb_str_catf(VALUE str, const char *format,...)
void rb_thread_reset_timer_thread(void)
VALUE rb_check_string_type(VALUE)
int clock_getres(clockid_t, struct timespec *)
#define ARGVSTR2ARGV(argv_str)
void rb_thread_check_ints(void)
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
size_t rb_str_capacity(VALUE str)
#define RB_BUILTIN_TYPE(x)
#define parent_redirect_open(pathname, flags, perm)
#define TypedData_Make_Struct(klass, type, data_type, sval)
VALUE rb_ary_dup(VALUE ary)
void rb_last_status_clear(void)
#define SafeStringValue(v)
rb_execution_context_t ec
#define redirect_dup(oldfd)
RUBY_EXTERN int dup2(int, int)
VALUE rb_str_new_frozen(VALUE)
int rb_cloexec_dup(int oldfd)
#define RUBY_TYPED_DEFAULT_FREE
VALUE rb_define_module(const char *name)
#define ARGVSTR2ARGC(argv_str)
VALUE rb_str_buf_new(long)
VALUE rb_detach_process(rb_pid_t pid)
rb_pid_t rb_w32_uspawn(int, const char *, const char *)
#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max)
void rb_sys_fail_str(VALUE mesg)
VALUE rb_execarg_init(int argc, const VALUE *orig_argv, int accept_shell, VALUE execarg_obj)
VALUE rb_thread_create(VALUE(*)(ANYARGS), void *)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
void ruby_setenv(const char *name, const char *value)
VALUE rb_clock_getres(int argc, VALUE *argv)
rb_pid_t waitpid(rb_pid_t, int *, int)
VALUE rb_to_int(VALUE)
Converts val into Integer.
VALUE rb_attr_get(VALUE, ID)
#define redirect_cloexec_dup(oldfd)
VALUE rb_f_abort(int argc, const VALUE *argv)
void rb_thread_sleep_forever(void)
VALUE rb_str_new(const char *, long)