Ruby  3.1.4p223 (2023-03-30 revision HEAD)
process.c
1 /**********************************************************************
2 
3  process.c -
4 
5  $Author$
6  created at: Tue Aug 10 14:30:50 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9  Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10  Copyright (C) 2000 Information-technology Promotion Agency, Japan
11 
12 **********************************************************************/
13 
14 #include "ruby/internal/config.h"
15 
16 #include "ruby/fiber/scheduler.h"
17 
18 #include <ctype.h>
19 #include <errno.h>
20 #include <signal.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <time.h>
24 
25 #ifdef HAVE_STDLIB_H
26 # include <stdlib.h>
27 #endif
28 
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32 
33 #ifdef HAVE_FCNTL_H
34 # include <fcntl.h>
35 #endif
36 
37 #ifdef HAVE_PROCESS_H
38 # include <process.h>
39 #endif
40 
41 #ifndef EXIT_SUCCESS
42 # define EXIT_SUCCESS 0
43 #endif
44 
45 #ifndef EXIT_FAILURE
46 # define EXIT_FAILURE 1
47 #endif
48 
49 #ifdef HAVE_SYS_WAIT_H
50 # include <sys/wait.h>
51 #endif
52 
53 #ifdef HAVE_SYS_RESOURCE_H
54 # include <sys/resource.h>
55 #endif
56 
57 #ifdef HAVE_VFORK_H
58 # include <vfork.h>
59 #endif
60 
61 #ifdef HAVE_SYS_PARAM_H
62 # include <sys/param.h>
63 #endif
64 
65 #ifndef MAXPATHLEN
66 # define MAXPATHLEN 1024
67 #endif
68 
69 #include <sys/stat.h>
70 
71 #ifdef HAVE_SYS_TIME_H
72 # include <sys/time.h>
73 #endif
74 
75 #ifdef HAVE_SYS_TIMES_H
76 # include <sys/times.h>
77 #endif
78 
79 #ifdef HAVE_PWD_H
80 # include <pwd.h>
81 #endif
82 
83 #ifdef HAVE_GRP_H
84 # include <grp.h>
85 # ifdef __CYGWIN__
86 int initgroups(const char *, rb_gid_t);
87 # endif
88 #endif
89 
90 #ifdef HAVE_SYS_ID_H
91 # include <sys/id.h>
92 #endif
93 
94 #ifdef __APPLE__
95 # include <mach/mach_time.h>
96 #endif
97 
98 #include "dln.h"
99 #include "hrtime.h"
100 #include "internal.h"
101 #include "internal/bits.h"
102 #include "internal/dir.h"
103 #include "internal/error.h"
104 #include "internal/eval.h"
105 #include "internal/hash.h"
106 #include "internal/numeric.h"
107 #include "internal/object.h"
108 #include "internal/process.h"
109 #include "internal/thread.h"
110 #include "internal/variable.h"
111 #include "internal/warnings.h"
112 #include "mjit.h"
113 #include "ruby/io.h"
114 #include "ruby/st.h"
115 #include "ruby/thread.h"
116 #include "ruby/util.h"
117 #include "vm_core.h"
118 #include "ruby/ractor.h"
119 
120 /* define system APIs */
121 #ifdef _WIN32
122 #undef open
123 #define open rb_w32_uopen
124 #endif
125 
126 #if defined(HAVE_TIMES) || defined(_WIN32)
127 static VALUE rb_cProcessTms;
128 #endif
129 
130 #ifndef WIFEXITED
131 #define WIFEXITED(w) (((w) & 0xff) == 0)
132 #endif
133 #ifndef WIFSIGNALED
134 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
135 #endif
136 #ifndef WIFSTOPPED
137 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
138 #endif
139 #ifndef WEXITSTATUS
140 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
141 #endif
142 #ifndef WTERMSIG
143 #define WTERMSIG(w) ((w) & 0x7f)
144 #endif
145 #ifndef WSTOPSIG
146 #define WSTOPSIG WEXITSTATUS
147 #endif
148 
149 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
150 #define HAVE_44BSD_SETUID 1
151 #define HAVE_44BSD_SETGID 1
152 #endif
153 
154 #ifdef __NetBSD__
155 #undef HAVE_SETRUID
156 #undef HAVE_SETRGID
157 #endif
158 
159 #ifdef BROKEN_SETREUID
160 #define setreuid ruby_setreuid
161 int setreuid(rb_uid_t ruid, rb_uid_t euid);
162 #endif
163 #ifdef BROKEN_SETREGID
164 #define setregid ruby_setregid
165 int setregid(rb_gid_t rgid, rb_gid_t egid);
166 #endif
167 
168 #if defined(HAVE_44BSD_SETUID) || defined(__APPLE__)
169 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
170 #define OBSOLETE_SETREUID 1
171 #endif
172 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
173 #define OBSOLETE_SETREGID 1
174 #endif
175 #endif
176 
177 static void check_uid_switch(void);
178 static void check_gid_switch(void);
179 static int exec_async_signal_safe(const struct rb_execarg *, char *, size_t);
180 
181 VALUE rb_envtbl(void);
182 VALUE rb_env_to_hash(void);
183 
184 #if 1
185 #define p_uid_from_name p_uid_from_name
186 #define p_gid_from_name p_gid_from_name
187 #endif
188 
189 #if defined(HAVE_UNISTD_H)
190 # if defined(HAVE_GETLOGIN_R)
191 # define USE_GETLOGIN_R 1
192 # define GETLOGIN_R_SIZE_DEFAULT 0x100
193 # define GETLOGIN_R_SIZE_LIMIT 0x1000
194 # if defined(_SC_LOGIN_NAME_MAX)
195 # define GETLOGIN_R_SIZE_INIT sysconf(_SC_LOGIN_NAME_MAX)
196 # else
197 # define GETLOGIN_R_SIZE_INIT GETLOGIN_R_SIZE_DEFAULT
198 # endif
199 # elif defined(HAVE_GETLOGIN)
200 # define USE_GETLOGIN 1
201 # endif
202 #endif
203 
204 #if defined(HAVE_PWD_H)
205 # if defined(HAVE_GETPWUID_R)
206 # define USE_GETPWUID_R 1
207 # elif defined(HAVE_GETPWUID)
208 # define USE_GETPWUID 1
209 # endif
210 # if defined(HAVE_GETPWNAM_R)
211 # define USE_GETPWNAM_R 1
212 # elif defined(HAVE_GETPWNAM)
213 # define USE_GETPWNAM 1
214 # endif
215 # if defined(HAVE_GETPWNAM_R) || defined(HAVE_GETPWUID_R)
216 # define GETPW_R_SIZE_DEFAULT 0x1000
217 # define GETPW_R_SIZE_LIMIT 0x10000
218 # if defined(_SC_GETPW_R_SIZE_MAX)
219 # define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX)
220 # else
221 # define GETPW_R_SIZE_INIT GETPW_R_SIZE_DEFAULT
222 # endif
223 # endif
224 # ifdef USE_GETPWNAM_R
225 # define PREPARE_GETPWNAM \
226  VALUE getpw_buf = 0
227 # define FINISH_GETPWNAM \
228  (getpw_buf ? (void)rb_str_resize(getpw_buf, 0) : (void)0)
229 # define OBJ2UID1(id) obj2uid((id), &getpw_buf)
230 # define OBJ2UID(id) obj2uid0(id)
231 static rb_uid_t obj2uid(VALUE id, VALUE *getpw_buf);
232 static inline rb_uid_t
233 obj2uid0(VALUE id)
234 {
235  rb_uid_t uid;
236  PREPARE_GETPWNAM;
237  uid = OBJ2UID1(id);
238  FINISH_GETPWNAM;
239  return uid;
240 }
241 # else
242 # define PREPARE_GETPWNAM /* do nothing */
243 # define FINISH_GETPWNAM /* do nothing */
244 # define OBJ2UID1(id) obj2uid((id))
245 # define OBJ2UID(id) obj2uid((id))
246 static rb_uid_t obj2uid(VALUE id);
247 # endif
248 #else
249 # define PREPARE_GETPWNAM /* do nothing */
250 # define FINISH_GETPWNAM /* do nothing */
251 # define OBJ2UID1(id) NUM2UIDT(id)
252 # define OBJ2UID(id) NUM2UIDT(id)
253 # ifdef p_uid_from_name
254 # undef p_uid_from_name
255 # define p_uid_from_name rb_f_notimplement
256 # endif
257 #endif
258 
259 #if defined(HAVE_GRP_H)
260 # if defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
261 # define USE_GETGRNAM_R
262 # define GETGR_R_SIZE_INIT sysconf(_SC_GETGR_R_SIZE_MAX)
263 # define GETGR_R_SIZE_DEFAULT 0x1000
264 # define GETGR_R_SIZE_LIMIT 0x10000
265 # endif
266 # ifdef USE_GETGRNAM_R
267 # define PREPARE_GETGRNAM \
268  VALUE getgr_buf = 0
269 # define FINISH_GETGRNAM \
270  (getgr_buf ? (void)rb_str_resize(getgr_buf, 0) : (void)0)
271 # define OBJ2GID1(id) obj2gid((id), &getgr_buf)
272 # define OBJ2GID(id) obj2gid0(id)
273 static rb_gid_t obj2gid(VALUE id, VALUE *getgr_buf);
274 static inline rb_gid_t
275 obj2gid0(VALUE id)
276 {
277  rb_gid_t gid;
278  PREPARE_GETGRNAM;
279  gid = OBJ2GID1(id);
280  FINISH_GETGRNAM;
281  return gid;
282 }
283 static rb_gid_t obj2gid(VALUE id, VALUE *getgr_buf);
284 # else
285 # define PREPARE_GETGRNAM /* do nothing */
286 # define FINISH_GETGRNAM /* do nothing */
287 # define OBJ2GID1(id) obj2gid((id))
288 # define OBJ2GID(id) obj2gid((id))
289 static rb_gid_t obj2gid(VALUE id);
290 # endif
291 #else
292 # define PREPARE_GETGRNAM /* do nothing */
293 # define FINISH_GETGRNAM /* do nothing */
294 # define OBJ2GID1(id) NUM2GIDT(id)
295 # define OBJ2GID(id) NUM2GIDT(id)
296 # ifdef p_gid_from_name
297 # undef p_gid_from_name
298 # define p_gid_from_name rb_f_notimplement
299 # endif
300 #endif
301 
302 #if SIZEOF_CLOCK_T == SIZEOF_INT
303 typedef unsigned int unsigned_clock_t;
304 #elif SIZEOF_CLOCK_T == SIZEOF_LONG
305 typedef unsigned long unsigned_clock_t;
306 #elif defined(HAVE_LONG_LONG) && SIZEOF_CLOCK_T == SIZEOF_LONG_LONG
307 typedef unsigned LONG_LONG unsigned_clock_t;
308 #endif
309 #ifndef HAVE_SIG_T
310 typedef void (*sig_t) (int);
311 #endif
312 
313 #define id_exception idException
314 static ID id_in, id_out, id_err, id_pid, id_uid, id_gid;
315 static ID id_close, id_child;
316 #ifdef HAVE_SETPGID
317 static ID id_pgroup;
318 #endif
319 #ifdef _WIN32
320 static ID id_new_pgroup;
321 #endif
322 static ID id_unsetenv_others, id_chdir, id_umask, id_close_others;
323 static ID id_nanosecond, id_microsecond, id_millisecond, id_second;
324 static ID id_float_microsecond, id_float_millisecond, id_float_second;
325 static ID id_GETTIMEOFDAY_BASED_CLOCK_REALTIME, id_TIME_BASED_CLOCK_REALTIME;
326 #ifdef HAVE_TIMES
327 static ID id_TIMES_BASED_CLOCK_MONOTONIC;
328 static ID id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID;
329 #endif
330 #ifdef RUSAGE_SELF
331 static ID id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID;
332 #endif
333 static ID id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID;
334 #ifdef __APPLE__
335 static ID id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC;
336 #endif
337 static ID id_hertz;
338 
339 /* execv and execl are async-signal-safe since SUSv4 (POSIX.1-2008, XPG7) */
340 #if defined(__sun) && !defined(_XPG7) /* Solaris 10, 9, ... */
341 #define execv(path, argv) (rb_async_bug_errno("unreachable: async-signal-unsafe execv() is called", 0))
342 #define execl(path, arg0, arg1, arg2, term) do { extern char **environ; execle((path), (arg0), (arg1), (arg2), (term), (environ)); } while (0)
343 #define ALWAYS_NEED_ENVP 1
344 #else
345 #define ALWAYS_NEED_ENVP 0
346 #endif
347 
348 static void
349 assert_close_on_exec(int fd)
350 {
351 #if VM_CHECK_MODE > 0
352 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(FD_CLOEXEC)
353  int flags = fcntl(fd, F_GETFD);
354  if (flags == -1) {
355  static const char m[] = "reserved FD closed unexpectedly?\n";
356  (void)!write(2, m, sizeof(m) - 1);
357  return;
358  }
359  if (flags & FD_CLOEXEC) return;
360  rb_bug("reserved FD did not have close-on-exec set");
361 #else
362  rb_bug("reserved FD without close-on-exec support");
363 #endif /* FD_CLOEXEC */
364 #endif /* VM_CHECK_MODE */
365 }
366 
367 static inline int
368 close_unless_reserved(int fd)
369 {
370  if (rb_reserved_fd_p(fd)) { /* async-signal-safe */
371  assert_close_on_exec(fd);
372  return 0;
373  }
374  return close(fd); /* async-signal-safe */
375 }
376 
377 /*#define DEBUG_REDIRECT*/
378 #if defined(DEBUG_REDIRECT)
379 
380 static void
381 ttyprintf(const char *fmt, ...)
382 {
383  va_list ap;
384  FILE *tty;
385  int save = errno;
386 #ifdef _WIN32
387  tty = fopen("con", "w");
388 #else
389  tty = fopen("/dev/tty", "w");
390 #endif
391  if (!tty)
392  return;
393 
394  va_start(ap, fmt);
395  vfprintf(tty, fmt, ap);
396  va_end(ap);
397  fclose(tty);
398  errno = save;
399 }
400 
401 static int
402 redirect_dup(int oldfd)
403 {
404  int ret;
405  ret = dup(oldfd);
406  ttyprintf("dup(%d) => %d\n", oldfd, ret);
407  return ret;
408 }
409 
410 static int
411 redirect_dup2(int oldfd, int newfd)
412 {
413  int ret;
414  ret = dup2(oldfd, newfd);
415  ttyprintf("dup2(%d, %d) => %d\n", oldfd, newfd, ret);
416  return ret;
417 }
418 
419 static int
420 redirect_cloexec_dup(int oldfd)
421 {
422  int ret;
423  ret = rb_cloexec_dup(oldfd);
424  ttyprintf("cloexec_dup(%d) => %d\n", oldfd, ret);
425  return ret;
426 }
427 
428 static int
429 redirect_cloexec_dup2(int oldfd, int newfd)
430 {
431  int ret;
432  ret = rb_cloexec_dup2(oldfd, newfd);
433  ttyprintf("cloexec_dup2(%d, %d) => %d\n", oldfd, newfd, ret);
434  return ret;
435 }
436 
437 static int
438 redirect_close(int fd)
439 {
440  int ret;
441  ret = close_unless_reserved(fd);
442  ttyprintf("close(%d) => %d\n", fd, ret);
443  return ret;
444 }
445 
446 static int
447 parent_redirect_open(const char *pathname, int flags, mode_t perm)
448 {
449  int ret;
450  ret = rb_cloexec_open(pathname, flags, perm);
451  ttyprintf("parent_open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
452  return ret;
453 }
454 
455 static int
456 parent_redirect_close(int fd)
457 {
458  int ret;
459  ret = close_unless_reserved(fd);
460  ttyprintf("parent_close(%d) => %d\n", fd, ret);
461  return ret;
462 }
463 
464 #else
465 #define redirect_dup(oldfd) dup(oldfd)
466 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
467 #define redirect_cloexec_dup(oldfd) rb_cloexec_dup(oldfd)
468 #define redirect_cloexec_dup2(oldfd, newfd) rb_cloexec_dup2((oldfd), (newfd))
469 #define redirect_close(fd) close_unless_reserved(fd)
470 #define parent_redirect_open(pathname, flags, perm) rb_cloexec_open((pathname), (flags), (perm))
471 #define parent_redirect_close(fd) close_unless_reserved(fd)
472 #endif
473 
474 /*
475  * Document-module: Process
476  *
477  * The module contains several groups of functionality for handling OS processes:
478  *
479  * * Low-level property introspection and management of the current process, like
480  * Process.argv0, Process.pid;
481  * * Low-level introspection of other processes, like Process.getpgid, Process.getpriority;
482  * * Management of the current process: Process.abort, Process.exit, Process.daemon, etc.
483  * (for convenience, most of those are also available as global functions
484  * and module functions of Kernel);
485  * * Creation and management of child processes: Process.fork, Process.spawn, and
486  * related methods;
487  * * Management of low-level system clock: Process.times and Process.clock_gettime,
488  * which could be important for proper benchmarking and other elapsed
489  * time measurement tasks.
490  */
491 
492 static VALUE
493 get_pid(void)
494 {
495  return PIDT2NUM(getpid());
496 }
497 
498 /*
499  * call-seq:
500  * Process.pid -> integer
501  *
502  * Returns the process id of this process. Not available on all
503  * platforms.
504  *
505  * Process.pid #=> 27415
506  */
507 
508 static VALUE
509 proc_get_pid(VALUE _)
510 {
511  return get_pid();
512 }
513 
514 static VALUE
515 get_ppid(void)
516 {
517  return PIDT2NUM(getppid());
518 }
519 
520 /*
521  * call-seq:
522  * Process.ppid -> integer
523  *
524  * Returns the process id of the parent of this process. Returns
525  * untrustworthy value on Win32/64. Not available on all platforms.
526  *
527  * puts "I am #{Process.pid}"
528  * Process.fork { puts "Dad is #{Process.ppid}" }
529  *
530  * <em>produces:</em>
531  *
532  * I am 27417
533  * Dad is 27417
534  */
535 
536 static VALUE
537 proc_get_ppid(VALUE _)
538 {
539  return get_ppid();
540 }
541 
542 
543 /*********************************************************************
544  *
545  * Document-class: Process::Status
546  *
547  * Process::Status encapsulates the information on the
548  * status of a running or terminated system process. The built-in
549  * variable <code>$?</code> is either +nil+ or a
550  * Process::Status object.
551  *
552  * fork { exit 99 } #=> 26557
553  * Process.wait #=> 26557
554  * $?.class #=> Process::Status
555  * $?.to_i #=> 25344
556  * $? >> 8 #=> 99
557  * $?.stopped? #=> false
558  * $?.exited? #=> true
559  * $?.exitstatus #=> 99
560  *
561  * Posix systems record information on processes using a 16-bit
562  * integer. The lower bits record the process status (stopped,
563  * exited, signaled) and the upper bits possibly contain additional
564  * information (for example the program's return code in the case of
565  * exited processes). Pre Ruby 1.8, these bits were exposed directly
566  * to the Ruby program. Ruby now encapsulates these in a
567  * Process::Status object. To maximize compatibility,
568  * however, these objects retain a bit-oriented interface. In the
569  * descriptions that follow, when we talk about the integer value of
570  * _stat_, we're referring to this 16 bit value.
571  */
572 
573 static VALUE rb_cProcessStatus;
574 
576  rb_pid_t pid;
577  int status;
578  int error;
579 };
580 
581 static const rb_data_type_t rb_process_status_type = {
582  .wrap_struct_name = "Process::Status",
583  .function = {
584  .dfree = RUBY_DEFAULT_FREE,
585  },
586  .data = NULL,
587  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
588 };
589 
590 static VALUE
591 rb_process_status_allocate(VALUE klass)
592 {
593  struct rb_process_status *data = NULL;
594 
595  return TypedData_Make_Struct(klass, struct rb_process_status, &rb_process_status_type, data);
596 }
597 
598 VALUE
600 {
601  return GET_THREAD()->last_status;
602 }
603 
604 /*
605  * call-seq:
606  * Process.last_status -> Process::Status or nil
607  *
608  * Returns the status of the last executed child process in the
609  * current thread.
610  *
611  * Process.wait Process.spawn("ruby", "-e", "exit 13")
612  * Process.last_status #=> #<Process::Status: pid 4825 exit 13>
613  *
614  * If no child process has ever been executed in the current
615  * thread, this returns +nil+.
616  *
617  * Process.last_status #=> nil
618  */
619 static VALUE
620 proc_s_last_status(VALUE mod)
621 {
622  return rb_last_status_get();
623 }
624 
625 VALUE
626 rb_process_status_new(rb_pid_t pid, int status, int error)
627 {
628  VALUE last_status = rb_process_status_allocate(rb_cProcessStatus);
629 
630  struct rb_process_status *data = RTYPEDDATA_DATA(last_status);
631  data->pid = pid;
632  data->status = status;
633  data->error = error;
634 
635  rb_obj_freeze(last_status);
636  return last_status;
637 }
638 
639 static VALUE
640 process_status_dump(VALUE status)
641 {
642  VALUE dump = rb_class_new_instance(0, 0, rb_cObject);
643  struct rb_process_status *data = RTYPEDDATA_DATA(status);
644  if (data->pid) {
645  rb_ivar_set(dump, id_status, INT2NUM(data->status));
646  rb_ivar_set(dump, id_pid, PIDT2NUM(data->pid));
647  }
648  return dump;
649 }
650 
651 static VALUE
652 process_status_load(VALUE real_obj, VALUE load_obj)
653 {
654  struct rb_process_status *data = rb_check_typeddata(real_obj, &rb_process_status_type);
655  VALUE status = rb_attr_get(load_obj, id_status);
656  VALUE pid = rb_attr_get(load_obj, id_pid);
657  data->pid = NIL_P(pid) ? 0 : NUM2PIDT(pid);
658  data->status = NIL_P(status) ? 0 : NUM2INT(status);
659  return real_obj;
660 }
661 
662 void
663 rb_last_status_set(int status, rb_pid_t pid)
664 {
665  GET_THREAD()->last_status = rb_process_status_new(pid, status, 0);
666 }
667 
668 void
669 rb_last_status_clear(void)
670 {
671  GET_THREAD()->last_status = Qnil;
672 }
673 
674 static rb_pid_t
675 pst_pid(VALUE pst)
676 {
677  struct rb_process_status *data = RTYPEDDATA_DATA(pst);
678  return data->pid;
679 }
680 
681 static int
682 pst_status(VALUE pst)
683 {
684  struct rb_process_status *data = RTYPEDDATA_DATA(pst);
685  return data->status;
686 }
687 
688 /*
689  * call-seq:
690  * stat.to_i -> integer
691  *
692  * Returns the bits in _stat_ as an Integer. Poking
693  * around in these bits is platform dependent.
694  *
695  * fork { exit 0xab } #=> 26566
696  * Process.wait #=> 26566
697  * sprintf('%04x', $?.to_i) #=> "ab00"
698  */
699 
700 static VALUE
701 pst_to_i(VALUE self)
702 {
703  int status = pst_status(self);
704  return RB_INT2NUM(status);
705 }
706 
707 #define PST2INT(st) pst_status(st)
708 
709 /*
710  * call-seq:
711  * stat.pid -> integer
712  *
713  * Returns the process ID that this status object represents.
714  *
715  * fork { exit } #=> 26569
716  * Process.wait #=> 26569
717  * $?.pid #=> 26569
718  */
719 
720 static VALUE
721 pst_pid_m(VALUE self)
722 {
723  rb_pid_t pid = pst_pid(self);
724  return PIDT2NUM(pid);
725 }
726 
727 static VALUE pst_message_status(VALUE str, int status);
728 
729 static void
730 pst_message(VALUE str, rb_pid_t pid, int status)
731 {
732  rb_str_catf(str, "pid %ld", (long)pid);
733  pst_message_status(str, status);
734 }
735 
736 static VALUE
737 pst_message_status(VALUE str, int status)
738 {
739  if (WIFSTOPPED(status)) {
740  int stopsig = WSTOPSIG(status);
741  const char *signame = ruby_signal_name(stopsig);
742  if (signame) {
743  rb_str_catf(str, " stopped SIG%s (signal %d)", signame, stopsig);
744  }
745  else {
746  rb_str_catf(str, " stopped signal %d", stopsig);
747  }
748  }
749  if (WIFSIGNALED(status)) {
750  int termsig = WTERMSIG(status);
751  const char *signame = ruby_signal_name(termsig);
752  if (signame) {
753  rb_str_catf(str, " SIG%s (signal %d)", signame, termsig);
754  }
755  else {
756  rb_str_catf(str, " signal %d", termsig);
757  }
758  }
759  if (WIFEXITED(status)) {
760  rb_str_catf(str, " exit %d", WEXITSTATUS(status));
761  }
762 #ifdef WCOREDUMP
763  if (WCOREDUMP(status)) {
764  rb_str_cat2(str, " (core dumped)");
765  }
766 #endif
767  return str;
768 }
769 
770 
771 /*
772  * call-seq:
773  * stat.to_s -> string
774  *
775  * Show pid and exit status as a string.
776  *
777  * system("false")
778  * p $?.to_s #=> "pid 12766 exit 1"
779  *
780  */
781 
782 static VALUE
783 pst_to_s(VALUE st)
784 {
785  rb_pid_t pid;
786  int status;
787  VALUE str;
788 
789  pid = pst_pid(st);
790  status = PST2INT(st);
791 
792  str = rb_str_buf_new(0);
793  pst_message(str, pid, status);
794  return str;
795 }
796 
797 
798 /*
799  * call-seq:
800  * stat.inspect -> string
801  *
802  * Override the inspection method.
803  *
804  * system("false")
805  * p $?.inspect #=> "#<Process::Status: pid 12861 exit 1>"
806  *
807  */
808 
809 static VALUE
810 pst_inspect(VALUE st)
811 {
812  rb_pid_t pid;
813  int status;
814  VALUE str;
815 
816  pid = pst_pid(st);
817  if (!pid) {
818  return rb_sprintf("#<%s: uninitialized>", rb_class2name(CLASS_OF(st)));
819  }
820  status = PST2INT(st);
821 
822  str = rb_sprintf("#<%s: ", rb_class2name(CLASS_OF(st)));
823  pst_message(str, pid, status);
824  rb_str_cat2(str, ">");
825  return str;
826 }
827 
828 
829 /*
830  * call-seq:
831  * stat == other -> true or false
832  *
833  * Returns +true+ if the integer value of _stat_
834  * equals <em>other</em>.
835  */
836 
837 static VALUE
838 pst_equal(VALUE st1, VALUE st2)
839 {
840  if (st1 == st2) return Qtrue;
841  return rb_equal(pst_to_i(st1), st2);
842 }
843 
844 
845 /*
846  * call-seq:
847  * stat & num -> integer
848  *
849  * Logical AND of the bits in _stat_ with <em>num</em>.
850  *
851  * fork { exit 0x37 }
852  * Process.wait
853  * sprintf('%04x', $?.to_i) #=> "3700"
854  * sprintf('%04x', $? & 0x1e00) #=> "1600"
855  */
856 
857 static VALUE
858 pst_bitand(VALUE st1, VALUE st2)
859 {
860  int status = PST2INT(st1) & NUM2INT(st2);
861 
862  return INT2NUM(status);
863 }
864 
865 
866 /*
867  * call-seq:
868  * stat >> num -> integer
869  *
870  * Shift the bits in _stat_ right <em>num</em> places.
871  *
872  * fork { exit 99 } #=> 26563
873  * Process.wait #=> 26563
874  * $?.to_i #=> 25344
875  * $? >> 8 #=> 99
876  */
877 
878 static VALUE
879 pst_rshift(VALUE st1, VALUE st2)
880 {
881  int status = PST2INT(st1) >> NUM2INT(st2);
882 
883  return INT2NUM(status);
884 }
885 
886 
887 /*
888  * call-seq:
889  * stat.stopped? -> true or false
890  *
891  * Returns +true+ if this process is stopped. This is only returned
892  * if the corresponding #wait call had the Process::WUNTRACED flag
893  * set.
894  */
895 
896 static VALUE
897 pst_wifstopped(VALUE st)
898 {
899  int status = PST2INT(st);
900 
901  return RBOOL(WIFSTOPPED(status));
902 }
903 
904 
905 /*
906  * call-seq:
907  * stat.stopsig -> integer or nil
908  *
909  * Returns the number of the signal that caused _stat_ to stop
910  * (or +nil+ if self is not stopped).
911  */
912 
913 static VALUE
914 pst_wstopsig(VALUE st)
915 {
916  int status = PST2INT(st);
917 
918  if (WIFSTOPPED(status))
919  return INT2NUM(WSTOPSIG(status));
920  return Qnil;
921 }
922 
923 
924 /*
925  * call-seq:
926  * stat.signaled? -> true or false
927  *
928  * Returns +true+ if _stat_ terminated because of
929  * an uncaught signal.
930  */
931 
932 static VALUE
933 pst_wifsignaled(VALUE st)
934 {
935  int status = PST2INT(st);
936 
937  return RBOOL(WIFSIGNALED(status));
938 }
939 
940 
941 /*
942  * call-seq:
943  * stat.termsig -> integer or nil
944  *
945  * Returns the number of the signal that caused _stat_ to
946  * terminate (or +nil+ if self was not terminated by an
947  * uncaught signal).
948  */
949 
950 static VALUE
951 pst_wtermsig(VALUE st)
952 {
953  int status = PST2INT(st);
954 
955  if (WIFSIGNALED(status))
956  return INT2NUM(WTERMSIG(status));
957  return Qnil;
958 }
959 
960 
961 /*
962  * call-seq:
963  * stat.exited? -> true or false
964  *
965  * Returns +true+ if _stat_ exited normally (for
966  * example using an <code>exit()</code> call or finishing the
967  * program).
968  */
969 
970 static VALUE
971 pst_wifexited(VALUE st)
972 {
973  int status = PST2INT(st);
974 
975  return RBOOL(WIFEXITED(status));
976 }
977 
978 
979 /*
980  * call-seq:
981  * stat.exitstatus -> integer or nil
982  *
983  * Returns the least significant eight bits of the return code of
984  * _stat_. Only available if #exited? is +true+.
985  *
986  * fork { } #=> 26572
987  * Process.wait #=> 26572
988  * $?.exited? #=> true
989  * $?.exitstatus #=> 0
990  *
991  * fork { exit 99 } #=> 26573
992  * Process.wait #=> 26573
993  * $?.exited? #=> true
994  * $?.exitstatus #=> 99
995  */
996 
997 static VALUE
998 pst_wexitstatus(VALUE st)
999 {
1000  int status = PST2INT(st);
1001 
1002  if (WIFEXITED(status))
1003  return INT2NUM(WEXITSTATUS(status));
1004  return Qnil;
1005 }
1006 
1007 
1008 /*
1009  * call-seq:
1010  * stat.success? -> true, false or nil
1011  *
1012  * Returns +true+ if _stat_ is successful, +false+ if not.
1013  * Returns +nil+ if #exited? is not +true+.
1014  */
1015 
1016 static VALUE
1017 pst_success_p(VALUE st)
1018 {
1019  int status = PST2INT(st);
1020 
1021  if (!WIFEXITED(status))
1022  return Qnil;
1023  return RBOOL(WEXITSTATUS(status) == EXIT_SUCCESS);
1024 }
1025 
1026 
1027 /*
1028  * call-seq:
1029  * stat.coredump? -> true or false
1030  *
1031  * Returns +true+ if _stat_ generated a coredump
1032  * when it terminated. Not available on all platforms.
1033  */
1034 
1035 static VALUE
1036 pst_wcoredump(VALUE st)
1037 {
1038 #ifdef WCOREDUMP
1039  int status = PST2INT(st);
1040 
1041  return RBOOL(WCOREDUMP(status));
1042 #else
1043  return Qfalse;
1044 #endif
1045 }
1046 
1047 static rb_pid_t
1048 do_waitpid(rb_pid_t pid, int *st, int flags)
1049 {
1050 #if defined HAVE_WAITPID
1051  return waitpid(pid, st, flags);
1052 #elif defined HAVE_WAIT4
1053  return wait4(pid, st, flags, NULL);
1054 #else
1055 # error waitpid or wait4 is required.
1056 #endif
1057 }
1058 
1059 #define WAITPID_LOCK_ONLY ((struct waitpid_state *)-1)
1060 
1062  struct list_node wnode;
1064  rb_nativethread_cond_t *cond;
1065  rb_pid_t ret;
1066  rb_pid_t pid;
1067  int status;
1068  int options;
1069  int errnum;
1070 };
1071 
1072 int rb_sigwait_fd_get(const rb_thread_t *);
1073 void rb_sigwait_sleep(const rb_thread_t *, int fd, const rb_hrtime_t *);
1074 void rb_sigwait_fd_put(const rb_thread_t *, int fd);
1075 void rb_thread_sleep_interruptible(void);
1076 
1077 static int
1078 waitpid_signal(struct waitpid_state *w)
1079 {
1080  if (w->ec) { /* rb_waitpid */
1081  rb_threadptr_interrupt(rb_ec_thread_ptr(w->ec));
1082  return TRUE;
1083  }
1084  else { /* ruby_waitpid_locked */
1085  if (w->cond) {
1086  rb_native_cond_signal(w->cond);
1087  return TRUE;
1088  }
1089  }
1090  return FALSE;
1091 }
1092 
1093 /*
1094  * When a thread is done using sigwait_fd and there are other threads
1095  * sleeping on waitpid, we must kick one of the threads out of
1096  * rb_native_cond_wait so it can switch to rb_sigwait_sleep
1097  */
1098 static void
1099 sigwait_fd_migrate_sleeper(rb_vm_t *vm)
1100 {
1101  struct waitpid_state *w = 0;
1102 
1103  list_for_each(&vm->waiting_pids, w, wnode) {
1104  if (waitpid_signal(w)) return;
1105  }
1106  list_for_each(&vm->waiting_grps, w, wnode) {
1107  if (waitpid_signal(w)) return;
1108  }
1109 }
1110 
1111 void
1112 rb_sigwait_fd_migrate(rb_vm_t *vm)
1113 {
1114  rb_native_mutex_lock(&vm->waitpid_lock);
1115  sigwait_fd_migrate_sleeper(vm);
1116  rb_native_mutex_unlock(&vm->waitpid_lock);
1117 }
1118 
1119 #if RUBY_SIGCHLD
1120 extern volatile unsigned int ruby_nocldwait; /* signal.c */
1121 /* called by timer thread or thread which acquired sigwait_fd */
1122 static void
1123 waitpid_each(struct list_head *head)
1124 {
1125  struct waitpid_state *w = 0, *next;
1126 
1127  list_for_each_safe(head, w, next, wnode) {
1128  rb_pid_t ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG);
1129 
1130  if (!ret) continue;
1131  if (ret == -1) w->errnum = errno;
1132 
1133  w->ret = ret;
1134  list_del_init(&w->wnode);
1135  waitpid_signal(w);
1136  }
1137 }
1138 #else
1139 # define ruby_nocldwait 0
1140 #endif
1141 
1142 void
1143 ruby_waitpid_all(rb_vm_t *vm)
1144 {
1145 #if RUBY_SIGCHLD
1146  rb_native_mutex_lock(&vm->waitpid_lock);
1147  waitpid_each(&vm->waiting_pids);
1148  if (list_empty(&vm->waiting_pids)) {
1149  waitpid_each(&vm->waiting_grps);
1150  }
1151  /* emulate SA_NOCLDWAIT */
1152  if (list_empty(&vm->waiting_pids) && list_empty(&vm->waiting_grps)) {
1153  while (ruby_nocldwait && do_waitpid(-1, 0, WNOHANG) > 0)
1154  ; /* keep looping */
1155  }
1156  rb_native_mutex_unlock(&vm->waitpid_lock);
1157 #endif
1158 }
1159 
1160 static void
1161 waitpid_state_init(struct waitpid_state *w, rb_pid_t pid, int options)
1162 {
1163  w->ret = 0;
1164  w->pid = pid;
1165  w->options = options;
1166  w->errnum = 0;
1167  w->status = 0;
1168 }
1169 
1170 static const rb_hrtime_t *
1171 sigwait_sleep_time(void)
1172 {
1173  if (SIGCHLD_LOSSY) {
1174  static const rb_hrtime_t busy_wait = 100 * RB_HRTIME_PER_MSEC;
1175 
1176  return &busy_wait;
1177  }
1178  return 0;
1179 }
1180 
1181 /*
1182  * must be called with vm->waitpid_lock held, this is not interruptible
1183  */
1184 rb_pid_t
1185 ruby_waitpid_locked(rb_vm_t *vm, rb_pid_t pid, int *status, int options,
1186  rb_nativethread_cond_t *cond)
1187 {
1188  struct waitpid_state w;
1189 
1190  assert(!ruby_thread_has_gvl_p() && "must not have GVL");
1191 
1192  waitpid_state_init(&w, pid, options);
1193  if (w.pid > 0 || list_empty(&vm->waiting_pids))
1194  w.ret = do_waitpid(w.pid, &w.status, w.options | WNOHANG);
1195  if (w.ret) {
1196  if (w.ret == -1) w.errnum = errno;
1197  }
1198  else {
1199  int sigwait_fd = -1;
1200 
1201  w.ec = 0;
1202  list_add(w.pid > 0 ? &vm->waiting_pids : &vm->waiting_grps, &w.wnode);
1203  do {
1204  if (sigwait_fd < 0)
1205  sigwait_fd = rb_sigwait_fd_get(0);
1206 
1207  if (sigwait_fd >= 0) {
1208  w.cond = 0;
1209  rb_native_mutex_unlock(&vm->waitpid_lock);
1210  rb_sigwait_sleep(0, sigwait_fd, sigwait_sleep_time());
1211  rb_native_mutex_lock(&vm->waitpid_lock);
1212  }
1213  else {
1214  w.cond = cond;
1215  rb_native_cond_wait(w.cond, &vm->waitpid_lock);
1216  }
1217  } while (!w.ret);
1218  list_del(&w.wnode);
1219 
1220  /* we're done, maybe other waitpid callers are not: */
1221  if (sigwait_fd >= 0) {
1222  rb_sigwait_fd_put(0, sigwait_fd);
1223  sigwait_fd_migrate_sleeper(vm);
1224  }
1225  }
1226  if (status) {
1227  *status = w.status;
1228  }
1229  if (w.ret == -1) errno = w.errnum;
1230  return w.ret;
1231 }
1232 
1233 static VALUE
1234 waitpid_sleep(VALUE x)
1235 {
1236  struct waitpid_state *w = (struct waitpid_state *)x;
1237 
1238  while (!w->ret) {
1239  rb_thread_sleep_interruptible();
1240  }
1241 
1242  return Qfalse;
1243 }
1244 
1245 static VALUE
1246 waitpid_cleanup(VALUE x)
1247 {
1248  struct waitpid_state *w = (struct waitpid_state *)x;
1249 
1250  /*
1251  * XXX w->ret is sometimes set but list_del is still needed, here,
1252  * Not sure why, so we unconditionally do list_del here:
1253  */
1254  if (TRUE || w->ret == 0) {
1255  rb_vm_t *vm = rb_ec_vm_ptr(w->ec);
1256 
1257  rb_native_mutex_lock(&vm->waitpid_lock);
1258  list_del(&w->wnode);
1259  rb_native_mutex_unlock(&vm->waitpid_lock);
1260  }
1261 
1262  return Qfalse;
1263 }
1264 
1265 static void
1266 waitpid_wait(struct waitpid_state *w)
1267 {
1268  rb_vm_t *vm = rb_ec_vm_ptr(w->ec);
1269  int need_sleep = FALSE;
1270 
1271  /*
1272  * Lock here to prevent do_waitpid from stealing work from the
1273  * ruby_waitpid_locked done by mjit workers since mjit works
1274  * outside of GVL
1275  */
1276  rb_native_mutex_lock(&vm->waitpid_lock);
1277 
1278  if (w->pid > 0 || list_empty(&vm->waiting_pids)) {
1279  w->ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG);
1280  }
1281 
1282  if (w->ret) {
1283  if (w->ret == -1) w->errnum = errno;
1284  }
1285  else if (w->options & WNOHANG) {
1286  }
1287  else {
1288  need_sleep = TRUE;
1289  }
1290 
1291  if (need_sleep) {
1292  w->cond = 0;
1293  /* order matters, favor specified PIDs rather than -1 or 0 */
1294  list_add(w->pid > 0 ? &vm->waiting_pids : &vm->waiting_grps, &w->wnode);
1295  }
1296 
1297  rb_native_mutex_unlock(&vm->waitpid_lock);
1298 
1299  if (need_sleep) {
1300  rb_ensure(waitpid_sleep, (VALUE)w, waitpid_cleanup, (VALUE)w);
1301  }
1302 }
1303 
1304 static void *
1305 waitpid_blocking_no_SIGCHLD(void *x)
1306 {
1307  struct waitpid_state *w = x;
1308 
1309  w->ret = do_waitpid(w->pid, &w->status, w->options);
1310 
1311  return 0;
1312 }
1313 
1314 static void
1315 waitpid_no_SIGCHLD(struct waitpid_state *w)
1316 {
1317  if (w->options & WNOHANG) {
1318  w->ret = do_waitpid(w->pid, &w->status, w->options);
1319  }
1320  else {
1321  do {
1322  rb_thread_call_without_gvl(waitpid_blocking_no_SIGCHLD, w,
1323  RUBY_UBF_PROCESS, 0);
1324  } while (w->ret < 0 && errno == EINTR && (RUBY_VM_CHECK_INTS(w->ec),1));
1325  }
1326  if (w->ret == -1)
1327  w->errnum = errno;
1328 }
1329 
1330 VALUE
1331 rb_process_status_wait(rb_pid_t pid, int flags)
1332 {
1333  // We only enter the scheduler if we are "blocking":
1334  if (!(flags & WNOHANG)) {
1335  VALUE scheduler = rb_fiber_scheduler_current();
1336  VALUE result = rb_fiber_scheduler_process_wait(scheduler, pid, flags);
1337  if (result != Qundef) return result;
1338  }
1339 
1341 
1342  waitpid_state_init(&waitpid_state, pid, flags);
1343  waitpid_state.ec = GET_EC();
1344 
1345  if (WAITPID_USE_SIGCHLD) {
1346  waitpid_wait(&waitpid_state);
1347  }
1348  else {
1349  waitpid_no_SIGCHLD(&waitpid_state);
1350  }
1351 
1352  if (waitpid_state.ret == 0) return Qnil;
1353 
1354  if (waitpid_state.ret > 0 && ruby_nocldwait) {
1355  waitpid_state.ret = -1;
1356  waitpid_state.errnum = ECHILD;
1357  }
1358 
1359  return rb_process_status_new(waitpid_state.ret, waitpid_state.status, waitpid_state.errnum);
1360 }
1361 
1362 /*
1363  * call-seq:
1364  * Process::Status.wait(pid=-1, flags=0) -> Process::Status
1365  *
1366  * Waits for a child process to exit and returns a Process::Status object
1367  * containing information on that process. Which child it waits on
1368  * depends on the value of _pid_:
1369  *
1370  * > 0:: Waits for the child whose process ID equals _pid_.
1371  *
1372  * 0:: Waits for any child whose process group ID equals that of the
1373  * calling process.
1374  *
1375  * -1:: Waits for any child process (the default if no _pid_ is
1376  * given).
1377  *
1378  * < -1:: Waits for any child whose process group ID equals the absolute
1379  * value of _pid_.
1380  *
1381  * The _flags_ argument may be a logical or of the flag values
1382  * Process::WNOHANG (do not block if no child available)
1383  * or Process::WUNTRACED (return stopped children that
1384  * haven't been reported). Not all flags are available on all
1385  * platforms, but a flag value of zero will work on all platforms.
1386  *
1387  * Returns +nil+ if there are no child processes.
1388  * Not available on all platforms.
1389  *
1390  * May invoke the scheduler hook _process_wait_.
1391  *
1392  * fork { exit 99 } #=> 27429
1393  * Process::Status.wait #=> pid 27429 exit 99
1394  * $? #=> nil
1395  *
1396  * pid = fork { sleep 3 } #=> 27440
1397  * Time.now #=> 2008-03-08 19:56:16 +0900
1398  * Process::Status.wait(pid, Process::WNOHANG) #=> nil
1399  * Time.now #=> 2008-03-08 19:56:16 +0900
1400  * Process::Status.wait(pid, 0) #=> pid 27440 exit 99
1401  * Time.now #=> 2008-03-08 19:56:19 +0900
1402  *
1403  * This is an EXPERIMENTAL FEATURE.
1404  */
1405 
1406 VALUE
1407 rb_process_status_waitv(int argc, VALUE *argv, VALUE _)
1408 {
1409  rb_check_arity(argc, 0, 2);
1410 
1411  rb_pid_t pid = -1;
1412  int flags = 0;
1413 
1414  if (argc >= 1) {
1415  pid = NUM2PIDT(argv[0]);
1416  }
1417 
1418  if (argc >= 2) {
1419  flags = RB_NUM2INT(argv[1]);
1420  }
1421 
1422  return rb_process_status_wait(pid, flags);
1423 }
1424 
1425 rb_pid_t
1426 rb_waitpid(rb_pid_t pid, int *st, int flags)
1427 {
1428  VALUE status = rb_process_status_wait(pid, flags);
1429  if (NIL_P(status)) return 0;
1430 
1431  struct rb_process_status *data = RTYPEDDATA_DATA(status);
1432  pid = data->pid;
1433 
1434  if (st) *st = data->status;
1435 
1436  if (pid == -1) {
1437  errno = data->error;
1438  }
1439  else {
1440  GET_THREAD()->last_status = status;
1441  }
1442 
1443  return pid;
1444 }
1445 
1446 static VALUE
1447 proc_wait(int argc, VALUE *argv)
1448 {
1449  rb_pid_t pid;
1450  int flags, status;
1451 
1452  flags = 0;
1453  if (rb_check_arity(argc, 0, 2) == 0) {
1454  pid = -1;
1455  }
1456  else {
1457  VALUE vflags;
1458  pid = NUM2PIDT(argv[0]);
1459  if (argc == 2 && !NIL_P(vflags = argv[1])) {
1460  flags = NUM2UINT(vflags);
1461  }
1462  }
1463 
1464  if ((pid = rb_waitpid(pid, &status, flags)) < 0)
1465  rb_sys_fail(0);
1466 
1467  if (pid == 0) {
1468  rb_last_status_clear();
1469  return Qnil;
1470  }
1471 
1472  return PIDT2NUM(pid);
1473 }
1474 
1475 /* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
1476  has historically been documented as if it didn't take any arguments
1477  despite the fact that it's just an alias for ::waitpid(). The way I
1478  have it below is more truthful, but a little confusing.
1479 
1480  I also took the liberty of putting in the pid values, as they're
1481  pretty useful, and it looked as if the original 'ri' output was
1482  supposed to contain them after "[...]depending on the value of
1483  aPid:".
1484 
1485  The 'ansi' and 'bs' formats of the ri output don't display the
1486  definition list for some reason, but the plain text one does.
1487  */
1488 
1489 /*
1490  * call-seq:
1491  * Process.wait() -> integer
1492  * Process.wait(pid=-1, flags=0) -> integer
1493  * Process.waitpid(pid=-1, flags=0) -> integer
1494  *
1495  * Waits for a child process to exit, returns its process id, and
1496  * sets <code>$?</code> to a Process::Status object
1497  * containing information on that process. Which child it waits on
1498  * depends on the value of _pid_:
1499  *
1500  * > 0:: Waits for the child whose process ID equals _pid_.
1501  *
1502  * 0:: Waits for any child whose process group ID equals that of the
1503  * calling process.
1504  *
1505  * -1:: Waits for any child process (the default if no _pid_ is
1506  * given).
1507  *
1508  * < -1:: Waits for any child whose process group ID equals the absolute
1509  * value of _pid_.
1510  *
1511  * The _flags_ argument may be a logical or of the flag values
1512  * Process::WNOHANG (do not block if no child available)
1513  * or Process::WUNTRACED (return stopped children that
1514  * haven't been reported). Not all flags are available on all
1515  * platforms, but a flag value of zero will work on all platforms.
1516  *
1517  * Calling this method raises a SystemCallError if there are no child
1518  * processes. Not available on all platforms.
1519  *
1520  * include Process
1521  * fork { exit 99 } #=> 27429
1522  * wait #=> 27429
1523  * $?.exitstatus #=> 99
1524  *
1525  * pid = fork { sleep 3 } #=> 27440
1526  * Time.now #=> 2008-03-08 19:56:16 +0900
1527  * waitpid(pid, Process::WNOHANG) #=> nil
1528  * Time.now #=> 2008-03-08 19:56:16 +0900
1529  * waitpid(pid, 0) #=> 27440
1530  * Time.now #=> 2008-03-08 19:56:19 +0900
1531  */
1532 
1533 static VALUE
1534 proc_m_wait(int c, VALUE *v, VALUE _)
1535 {
1536  return proc_wait(c, v);
1537 }
1538 
1539 
1540 /*
1541  * call-seq:
1542  * Process.wait2(pid=-1, flags=0) -> [pid, status]
1543  * Process.waitpid2(pid=-1, flags=0) -> [pid, status]
1544  *
1545  * Waits for a child process to exit (see Process::waitpid for exact
1546  * semantics) and returns an array containing the process id and the
1547  * exit status (a Process::Status object) of that
1548  * child. Raises a SystemCallError if there are no child processes.
1549  *
1550  * Process.fork { exit 99 } #=> 27437
1551  * pid, status = Process.wait2
1552  * pid #=> 27437
1553  * status.exitstatus #=> 99
1554  */
1555 
1556 static VALUE
1557 proc_wait2(int argc, VALUE *argv, VALUE _)
1558 {
1559  VALUE pid = proc_wait(argc, argv);
1560  if (NIL_P(pid)) return Qnil;
1561  return rb_assoc_new(pid, rb_last_status_get());
1562 }
1563 
1564 
1565 /*
1566  * call-seq:
1567  * Process.waitall -> [ [pid1,status1], ...]
1568  *
1569  * Waits for all children, returning an array of
1570  * _pid_/_status_ pairs (where _status_ is a
1571  * Process::Status object).
1572  *
1573  * fork { sleep 0.2; exit 2 } #=> 27432
1574  * fork { sleep 0.1; exit 1 } #=> 27433
1575  * fork { exit 0 } #=> 27434
1576  * p Process.waitall
1577  *
1578  * <em>produces</em>:
1579  *
1580  * [[30982, #<Process::Status: pid 30982 exit 0>],
1581  * [30979, #<Process::Status: pid 30979 exit 1>],
1582  * [30976, #<Process::Status: pid 30976 exit 2>]]
1583  */
1584 
1585 static VALUE
1586 proc_waitall(VALUE _)
1587 {
1588  VALUE result;
1589  rb_pid_t pid;
1590  int status;
1591 
1592  result = rb_ary_new();
1593  rb_last_status_clear();
1594 
1595  for (pid = -1;;) {
1596  pid = rb_waitpid(-1, &status, 0);
1597  if (pid == -1) {
1598  int e = errno;
1599  if (e == ECHILD)
1600  break;
1601  rb_syserr_fail(e, 0);
1602  }
1604  }
1605  return result;
1606 }
1607 
1608 static VALUE rb_cWaiter;
1609 
1610 static VALUE
1611 detach_process_pid(VALUE thread)
1612 {
1613  return rb_thread_local_aref(thread, id_pid);
1614 }
1615 
1616 static VALUE
1617 detach_process_watcher(void *arg)
1618 {
1619  rb_pid_t cpid, pid = (rb_pid_t)(VALUE)arg;
1620  int status;
1621 
1622  while ((cpid = rb_waitpid(pid, &status, 0)) == 0) {
1623  /* wait while alive */
1624  }
1625  return rb_last_status_get();
1626 }
1627 
1628 VALUE
1629 rb_detach_process(rb_pid_t pid)
1630 {
1631  VALUE watcher = rb_thread_create(detach_process_watcher, (void*)(VALUE)pid);
1632  rb_thread_local_aset(watcher, id_pid, PIDT2NUM(pid));
1633  RBASIC_SET_CLASS(watcher, rb_cWaiter);
1634  return watcher;
1635 }
1636 
1637 
1638 /*
1639  * call-seq:
1640  * Process.detach(pid) -> thread
1641  *
1642  * Some operating systems retain the status of terminated child
1643  * processes until the parent collects that status (normally using
1644  * some variant of <code>wait()</code>). If the parent never collects
1645  * this status, the child stays around as a <em>zombie</em> process.
1646  * Process::detach prevents this by setting up a separate Ruby thread
1647  * whose sole job is to reap the status of the process _pid_ when it
1648  * terminates. Use #detach only when you do not intend to explicitly
1649  * wait for the child to terminate.
1650  *
1651  * The waiting thread returns the exit status of the detached process
1652  * when it terminates, so you can use Thread#join to
1653  * know the result. If specified _pid_ is not a valid child process
1654  * ID, the thread returns +nil+ immediately.
1655  *
1656  * The waiting thread has #pid method which returns the pid.
1657  *
1658  * In this first example, we don't reap the first child process, so
1659  * it appears as a zombie in the process status display.
1660  *
1661  * p1 = fork { sleep 0.1 }
1662  * p2 = fork { sleep 0.2 }
1663  * Process.waitpid(p2)
1664  * sleep 2
1665  * system("ps -ho pid,state -p #{p1}")
1666  *
1667  * <em>produces:</em>
1668  *
1669  * 27389 Z
1670  *
1671  * In the next example, Process::detach is used to reap
1672  * the child automatically.
1673  *
1674  * p1 = fork { sleep 0.1 }
1675  * p2 = fork { sleep 0.2 }
1676  * Process.detach(p1)
1677  * Process.waitpid(p2)
1678  * sleep 2
1679  * system("ps -ho pid,state -p #{p1}")
1680  *
1681  * <em>(produces no output)</em>
1682  */
1683 
1684 static VALUE
1685 proc_detach(VALUE obj, VALUE pid)
1686 {
1687  return rb_detach_process(NUM2PIDT(pid));
1688 }
1689 
1690 /* This function should be async-signal-safe. Actually it is. */
1691 static void
1692 before_exec_async_signal_safe(void)
1693 {
1694 }
1695 
1696 static void
1697 before_exec_non_async_signal_safe(void)
1698 {
1699  /*
1700  * On Mac OS X 10.5.x (Leopard) or earlier, exec() may return ENOTSUP
1701  * if the process have multiple threads. Therefore we have to kill
1702  * internal threads temporary. [ruby-core:10583]
1703  * This is also true on Haiku. It returns Errno::EPERM against exec()
1704  * in multiple threads.
1705  *
1706  * Nowadays, we always stop the timer thread completely to allow redirects.
1707  */
1708  rb_thread_stop_timer_thread();
1709 }
1710 
1711 #define WRITE_CONST(fd, str) (void)(write((fd),(str),sizeof(str)-1)<0)
1712 #ifdef _WIN32
1713 int rb_w32_set_nonblock2(int fd, int nonblock);
1714 #endif
1715 
1716 static int
1717 set_blocking(int fd)
1718 {
1719 #ifdef _WIN32
1720  return rb_w32_set_nonblock2(fd, 0);
1721 #elif defined(F_GETFL) && defined(F_SETFL)
1722  int fl = fcntl(fd, F_GETFL); /* async-signal-safe */
1723 
1724  /* EBADF ought to be possible */
1725  if (fl == -1) return fl;
1726  if (fl & O_NONBLOCK) {
1727  fl &= ~O_NONBLOCK;
1728  return fcntl(fd, F_SETFL, fl);
1729  }
1730  return 0;
1731 #endif
1732 }
1733 
1734 static void
1735 stdfd_clear_nonblock(void)
1736 {
1737  /* many programs cannot deal with non-blocking stdin/stdout/stderr */
1738  int fd;
1739  for (fd = 0; fd < 3; fd++) {
1740  (void)set_blocking(fd); /* can't do much about errors anyhow */
1741  }
1742 }
1743 
1744 static void
1745 before_exec(void)
1746 {
1747  before_exec_non_async_signal_safe();
1748  before_exec_async_signal_safe();
1749 }
1750 
1751 /* This function should be async-signal-safe. Actually it is. */
1752 static void
1753 after_exec_async_signal_safe(void)
1754 {
1755 }
1756 
1757 static void
1758 after_exec_non_async_signal_safe(void)
1759 {
1760  rb_thread_reset_timer_thread();
1761  rb_thread_start_timer_thread();
1762 }
1763 
1764 static void
1765 after_exec(void)
1766 {
1767  after_exec_async_signal_safe();
1768  after_exec_non_async_signal_safe();
1769 }
1770 
1771 #if defined HAVE_WORKING_FORK || defined HAVE_DAEMON
1772 static void
1773 before_fork_ruby(void)
1774 {
1775  before_exec();
1776 }
1777 
1778 static void
1779 after_fork_ruby(void)
1780 {
1781  rb_threadptr_pending_interrupt_clear(GET_THREAD());
1782  after_exec();
1783 }
1784 #endif
1785 
1786 #if defined(HAVE_WORKING_FORK)
1787 
1788 /* try_with_sh and exec_with_sh should be async-signal-safe. Actually it is.*/
1789 #define try_with_sh(err, prog, argv, envp) ((err == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0)
1790 static void
1791 exec_with_sh(const char *prog, char **argv, char **envp)
1792 {
1793  *argv = (char *)prog;
1794  *--argv = (char *)"sh";
1795  if (envp)
1796  execve("/bin/sh", argv, envp); /* async-signal-safe */
1797  else
1798  execv("/bin/sh", argv); /* async-signal-safe (since SUSv4) */
1799 }
1800 
1801 #else
1802 #define try_with_sh(err, prog, argv, envp) (void)0
1803 #endif
1804 
1805 /* This function should be async-signal-safe. Actually it is. */
1806 static int
1807 proc_exec_cmd(const char *prog, VALUE argv_str, VALUE envp_str)
1808 {
1809  char **argv;
1810 #ifndef _WIN32
1811  char **envp;
1812  int err;
1813 #endif
1814 
1815  argv = ARGVSTR2ARGV(argv_str);
1816 
1817  if (!prog) {
1818  return ENOENT;
1819  }
1820 
1821 #ifdef _WIN32
1822  rb_w32_uaspawn(P_OVERLAY, prog, argv);
1823  return errno;
1824 #else
1825  envp = envp_str ? RB_IMEMO_TMPBUF_PTR(envp_str) : NULL;
1826  if (envp_str)
1827  execve(prog, argv, envp); /* async-signal-safe */
1828  else
1829  execv(prog, argv); /* async-signal-safe (since SUSv4) */
1830  err = errno;
1831  try_with_sh(err, prog, argv, envp); /* try_with_sh() is async-signal-safe. */
1832  return err;
1833 #endif
1834 }
1835 
1836 /* This function should be async-signal-safe. Actually it is. */
1837 static int
1838 proc_exec_sh(const char *str, VALUE envp_str)
1839 {
1840  const char *s;
1841 
1842  s = str;
1843  while (*s == ' ' || *s == '\t' || *s == '\n')
1844  s++;
1845 
1846  if (!*s) {
1847  return ENOENT;
1848  }
1849 
1850 #ifdef _WIN32
1851  rb_w32_uspawn(P_OVERLAY, (char *)str, 0);
1852 #elif defined(__CYGWIN32__)
1853  {
1854  char fbuf[MAXPATHLEN];
1855  char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
1856  int status = -1;
1857  if (shell)
1858  execl(shell, "sh", "-c", str, (char *) NULL);
1859  else
1860  status = system(str);
1861  if (status != -1)
1862  exit(status);
1863  }
1864 #else
1865  if (envp_str)
1866  execle("/bin/sh", "sh", "-c", str, (char *)NULL, RB_IMEMO_TMPBUF_PTR(envp_str)); /* async-signal-safe */
1867  else
1868  execl("/bin/sh", "sh", "-c", str, (char *)NULL); /* async-signal-safe (since SUSv4) */
1869 #endif /* _WIN32 */
1870  return errno;
1871 }
1872 
1873 int
1874 rb_proc_exec(const char *str)
1875 {
1876  int ret;
1877  before_exec();
1878  ret = proc_exec_sh(str, Qfalse);
1879  after_exec();
1880  errno = ret;
1881  return -1;
1882 }
1883 
1884 static void
1885 mark_exec_arg(void *ptr)
1886 {
1887  struct rb_execarg *eargp = ptr;
1888  if (eargp->use_shell)
1889  rb_gc_mark(eargp->invoke.sh.shell_script);
1890  else {
1891  rb_gc_mark(eargp->invoke.cmd.command_name);
1892  rb_gc_mark(eargp->invoke.cmd.command_abspath);
1893  rb_gc_mark(eargp->invoke.cmd.argv_str);
1894  rb_gc_mark(eargp->invoke.cmd.argv_buf);
1895  }
1896  rb_gc_mark(eargp->redirect_fds);
1897  rb_gc_mark(eargp->envp_str);
1898  rb_gc_mark(eargp->envp_buf);
1899  rb_gc_mark(eargp->dup2_tmpbuf);
1900  rb_gc_mark(eargp->rlimit_limits);
1901  rb_gc_mark(eargp->fd_dup2);
1902  rb_gc_mark(eargp->fd_close);
1903  rb_gc_mark(eargp->fd_open);
1904  rb_gc_mark(eargp->fd_dup2_child);
1905  rb_gc_mark(eargp->env_modification);
1906  rb_gc_mark(eargp->path_env);
1907  rb_gc_mark(eargp->chdir_dir);
1908 }
1909 
1910 static size_t
1911 memsize_exec_arg(const void *ptr)
1912 {
1913  return sizeof(struct rb_execarg);
1914 }
1915 
1916 static const rb_data_type_t exec_arg_data_type = {
1917  "exec_arg",
1918  {mark_exec_arg, RUBY_TYPED_DEFAULT_FREE, memsize_exec_arg},
1919  0, 0, RUBY_TYPED_FREE_IMMEDIATELY
1920 };
1921 
1922 #ifdef _WIN32
1923 # define DEFAULT_PROCESS_ENCODING rb_utf8_encoding()
1924 #endif
1925 #ifdef DEFAULT_PROCESS_ENCODING
1926 # define EXPORT_STR(str) rb_str_export_to_enc((str), DEFAULT_PROCESS_ENCODING)
1927 # define EXPORT_DUP(str) export_dup(str)
1928 static VALUE
1929 export_dup(VALUE str)
1930 {
1931  VALUE newstr = EXPORT_STR(str);
1932  if (newstr == str) newstr = rb_str_dup(str);
1933  return newstr;
1934 }
1935 #else
1936 # define EXPORT_STR(str) (str)
1937 # define EXPORT_DUP(str) rb_str_dup(str)
1938 #endif
1939 
1940 #if !defined(HAVE_WORKING_FORK) && defined(HAVE_SPAWNV)
1941 # define USE_SPAWNV 1
1942 #else
1943 # define USE_SPAWNV 0
1944 #endif
1945 #ifndef P_NOWAIT
1946 # define P_NOWAIT _P_NOWAIT
1947 #endif
1948 
1949 #if USE_SPAWNV
1950 #if defined(_WIN32)
1951 #define proc_spawn_cmd_internal(argv, prog) rb_w32_uaspawn(P_NOWAIT, (prog), (argv))
1952 #else
1953 static rb_pid_t
1954 proc_spawn_cmd_internal(char **argv, char *prog)
1955 {
1956  char fbuf[MAXPATHLEN];
1957  rb_pid_t status;
1958 
1959  if (!prog)
1960  prog = argv[0];
1961  prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
1962  if (!prog)
1963  return -1;
1964 
1965  before_exec();
1966  status = spawnv(P_NOWAIT, prog, (const char **)argv);
1967  if (status == -1 && errno == ENOEXEC) {
1968  *argv = (char *)prog;
1969  *--argv = (char *)"sh";
1970  status = spawnv(P_NOWAIT, "/bin/sh", (const char **)argv);
1971  after_exec();
1972  if (status == -1) errno = ENOEXEC;
1973  }
1974  return status;
1975 }
1976 #endif
1977 
1978 static rb_pid_t
1979 proc_spawn_cmd(char **argv, VALUE prog, struct rb_execarg *eargp)
1980 {
1981  rb_pid_t pid = -1;
1982 
1983  if (argv[0]) {
1984 #if defined(_WIN32)
1985  DWORD flags = 0;
1986  if (eargp->new_pgroup_given && eargp->new_pgroup_flag) {
1987  flags = CREATE_NEW_PROCESS_GROUP;
1988  }
1989  pid = rb_w32_uaspawn_flags(P_NOWAIT, prog ? RSTRING_PTR(prog) : 0, argv, flags);
1990 #else
1991  pid = proc_spawn_cmd_internal(argv, prog ? RSTRING_PTR(prog) : 0);
1992 #endif
1993  }
1994  return pid;
1995 }
1996 
1997 #if defined(_WIN32)
1998 #define proc_spawn_sh(str) rb_w32_uspawn(P_NOWAIT, (str), 0)
1999 #else
2000 static rb_pid_t
2001 proc_spawn_sh(char *str)
2002 {
2003  char fbuf[MAXPATHLEN];
2004  rb_pid_t status;
2005 
2006  char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
2007  before_exec();
2008  status = spawnl(P_NOWAIT, (shell ? shell : "/bin/sh"), "sh", "-c", str, (char*)NULL);
2009  after_exec();
2010  return status;
2011 }
2012 #endif
2013 #endif
2014 
2015 static VALUE
2016 hide_obj(VALUE obj)
2017 {
2018  RBASIC_CLEAR_CLASS(obj);
2019  return obj;
2020 }
2021 
2022 static VALUE
2023 check_exec_redirect_fd(VALUE v, int iskey)
2024 {
2025  VALUE tmp;
2026  int fd;
2027  if (FIXNUM_P(v)) {
2028  fd = FIX2INT(v);
2029  }
2030  else if (SYMBOL_P(v)) {
2031  ID id = rb_check_id(&v);
2032  if (id == id_in)
2033  fd = 0;
2034  else if (id == id_out)
2035  fd = 1;
2036  else if (id == id_err)
2037  fd = 2;
2038  else
2039  goto wrong;
2040  }
2041  else if (!NIL_P(tmp = rb_io_check_io(v))) {
2042  rb_io_t *fptr;
2043  GetOpenFile(tmp, fptr);
2044  if (fptr->tied_io_for_writing)
2045  rb_raise(rb_eArgError, "duplex IO redirection");
2046  fd = fptr->fd;
2047  }
2048  else {
2049  goto wrong;
2050  }
2051  if (fd < 0) {
2052  rb_raise(rb_eArgError, "negative file descriptor");
2053  }
2054 #ifdef _WIN32
2055  else if (fd >= 3 && iskey) {
2056  rb_raise(rb_eArgError, "wrong file descriptor (%d)", fd);
2057  }
2058 #endif
2059  return INT2FIX(fd);
2060 
2061  wrong:
2062  rb_raise(rb_eArgError, "wrong exec redirect");
2064 }
2065 
2066 static VALUE
2067 check_exec_redirect1(VALUE ary, VALUE key, VALUE param)
2068 {
2069  if (ary == Qfalse) {
2070  ary = hide_obj(rb_ary_new());
2071  }
2072  if (!RB_TYPE_P(key, T_ARRAY)) {
2073  VALUE fd = check_exec_redirect_fd(key, !NIL_P(param));
2074  rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
2075  }
2076  else {
2077  int i;
2078  for (i = 0 ; i < RARRAY_LEN(key); i++) {
2079  VALUE v = RARRAY_AREF(key, i);
2080  VALUE fd = check_exec_redirect_fd(v, !NIL_P(param));
2081  rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
2082  }
2083  }
2084  return ary;
2085 }
2086 
2087 static void
2088 check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
2089 {
2090  VALUE param;
2091  VALUE path, flags, perm;
2092  VALUE tmp;
2093  ID id;
2094 
2095  switch (TYPE(val)) {
2096  case T_SYMBOL:
2097  id = rb_check_id(&val);
2098  if (id == id_close) {
2099  param = Qnil;
2100  eargp->fd_close = check_exec_redirect1(eargp->fd_close, key, param);
2101  }
2102  else if (id == id_in) {
2103  param = INT2FIX(0);
2104  eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
2105  }
2106  else if (id == id_out) {
2107  param = INT2FIX(1);
2108  eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
2109  }
2110  else if (id == id_err) {
2111  param = INT2FIX(2);
2112  eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
2113  }
2114  else {
2115  rb_raise(rb_eArgError, "wrong exec redirect symbol: %"PRIsVALUE,
2116  val);
2117  }
2118  break;
2119 
2120  case T_FILE:
2121  io:
2122  val = check_exec_redirect_fd(val, 0);
2123  /* fall through */
2124  case T_FIXNUM:
2125  param = val;
2126  eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
2127  break;
2128 
2129  case T_ARRAY:
2130  path = rb_ary_entry(val, 0);
2131  if (RARRAY_LEN(val) == 2 && SYMBOL_P(path) &&
2132  path == ID2SYM(id_child)) {
2133  param = check_exec_redirect_fd(rb_ary_entry(val, 1), 0);
2134  eargp->fd_dup2_child = check_exec_redirect1(eargp->fd_dup2_child, key, param);
2135  }
2136  else {
2137  FilePathValue(path);
2138  flags = rb_ary_entry(val, 1);
2139  if (NIL_P(flags))
2140  flags = INT2NUM(O_RDONLY);
2141  else if (RB_TYPE_P(flags, T_STRING))
2142  flags = INT2NUM(rb_io_modestr_oflags(StringValueCStr(flags)));
2143  else
2144  flags = rb_to_int(flags);
2145  perm = rb_ary_entry(val, 2);
2146  perm = NIL_P(perm) ? INT2FIX(0644) : rb_to_int(perm);
2147  param = hide_obj(rb_ary_new3(4, hide_obj(EXPORT_DUP(path)),
2148  flags, perm, Qnil));
2149  eargp->fd_open = check_exec_redirect1(eargp->fd_open, key, param);
2150  }
2151  break;
2152 
2153  case T_STRING:
2154  path = val;
2155  FilePathValue(path);
2156  if (RB_TYPE_P(key, T_FILE))
2157  key = check_exec_redirect_fd(key, 1);
2158  if (FIXNUM_P(key) && (FIX2INT(key) == 1 || FIX2INT(key) == 2))
2159  flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
2160  else if (RB_TYPE_P(key, T_ARRAY)) {
2161  int i;
2162  for (i = 0; i < RARRAY_LEN(key); i++) {
2163  VALUE v = RARRAY_AREF(key, i);
2164  VALUE fd = check_exec_redirect_fd(v, 1);
2165  if (FIX2INT(fd) != 1 && FIX2INT(fd) != 2) break;
2166  }
2167  if (i == RARRAY_LEN(key))
2168  flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
2169  else
2170  flags = INT2NUM(O_RDONLY);
2171  }
2172  else
2173  flags = INT2NUM(O_RDONLY);
2174  perm = INT2FIX(0644);
2175  param = hide_obj(rb_ary_new3(4, hide_obj(EXPORT_DUP(path)),
2176  flags, perm, Qnil));
2177  eargp->fd_open = check_exec_redirect1(eargp->fd_open, key, param);
2178  break;
2179 
2180  default:
2181  tmp = val;
2182  val = rb_io_check_io(tmp);
2183  if (!NIL_P(val)) goto io;
2184  rb_raise(rb_eArgError, "wrong exec redirect action");
2185  }
2186 
2187 }
2188 
2189 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
2190 static int rlimit_type_by_sym(VALUE key);
2191 
2192 static void
2193 rb_execarg_addopt_rlimit(struct rb_execarg *eargp, int rtype, VALUE val)
2194 {
2195  VALUE ary = eargp->rlimit_limits;
2196  VALUE tmp, softlim, hardlim;
2197  if (eargp->rlimit_limits == Qfalse)
2198  ary = eargp->rlimit_limits = hide_obj(rb_ary_new());
2199  else
2200  ary = eargp->rlimit_limits;
2201  tmp = rb_check_array_type(val);
2202  if (!NIL_P(tmp)) {
2203  if (RARRAY_LEN(tmp) == 1)
2204  softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0));
2205  else if (RARRAY_LEN(tmp) == 2) {
2206  softlim = rb_to_int(rb_ary_entry(tmp, 0));
2207  hardlim = rb_to_int(rb_ary_entry(tmp, 1));
2208  }
2209  else {
2210  rb_raise(rb_eArgError, "wrong exec rlimit option");
2211  }
2212  }
2213  else {
2214  softlim = hardlim = rb_to_int(val);
2215  }
2216  tmp = hide_obj(rb_ary_new3(3, INT2NUM(rtype), softlim, hardlim));
2217  rb_ary_push(ary, tmp);
2218 }
2219 #endif
2220 
2221 #define TO_BOOL(val, name) NIL_P(val) ? 0 : rb_bool_expected((val), name)
2222 int
2223 rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
2224 {
2225  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2226 
2227  ID id;
2228 
2229  switch (TYPE(key)) {
2230  case T_SYMBOL:
2231 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
2232  {
2233  int rtype = rlimit_type_by_sym(key);
2234  if (rtype != -1) {
2235  rb_execarg_addopt_rlimit(eargp, rtype, val);
2236  RB_GC_GUARD(execarg_obj);
2237  return ST_CONTINUE;
2238  }
2239  }
2240 #endif
2241  if (!(id = rb_check_id(&key))) return ST_STOP;
2242 #ifdef HAVE_SETPGID
2243  if (id == id_pgroup) {
2244  rb_pid_t pgroup;
2245  if (eargp->pgroup_given) {
2246  rb_raise(rb_eArgError, "pgroup option specified twice");
2247  }
2248  if (!RTEST(val))
2249  pgroup = -1; /* asis(-1) means "don't call setpgid()". */
2250  else if (val == Qtrue)
2251  pgroup = 0; /* new process group. */
2252  else {
2253  pgroup = NUM2PIDT(val);
2254  if (pgroup < 0) {
2255  rb_raise(rb_eArgError, "negative process group ID : %ld", (long)pgroup);
2256  }
2257  }
2258  eargp->pgroup_given = 1;
2259  eargp->pgroup_pgid = pgroup;
2260  }
2261  else
2262 #endif
2263 #ifdef _WIN32
2264  if (id == id_new_pgroup) {
2265  if (eargp->new_pgroup_given) {
2266  rb_raise(rb_eArgError, "new_pgroup option specified twice");
2267  }
2268  eargp->new_pgroup_given = 1;
2269  eargp->new_pgroup_flag = TO_BOOL(val, "new_pgroup");
2270  }
2271  else
2272 #endif
2273  if (id == id_unsetenv_others) {
2274  if (eargp->unsetenv_others_given) {
2275  rb_raise(rb_eArgError, "unsetenv_others option specified twice");
2276  }
2277  eargp->unsetenv_others_given = 1;
2278  eargp->unsetenv_others_do = TO_BOOL(val, "unsetenv_others");
2279  }
2280  else if (id == id_chdir) {
2281  if (eargp->chdir_given) {
2282  rb_raise(rb_eArgError, "chdir option specified twice");
2283  }
2284  FilePathValue(val);
2285  val = rb_str_encode_ospath(val);
2286  eargp->chdir_given = 1;
2287  eargp->chdir_dir = hide_obj(EXPORT_DUP(val));
2288  }
2289  else if (id == id_umask) {
2290  mode_t cmask = NUM2MODET(val);
2291  if (eargp->umask_given) {
2292  rb_raise(rb_eArgError, "umask option specified twice");
2293  }
2294  eargp->umask_given = 1;
2295  eargp->umask_mask = cmask;
2296  }
2297  else if (id == id_close_others) {
2298  if (eargp->close_others_given) {
2299  rb_raise(rb_eArgError, "close_others option specified twice");
2300  }
2301  eargp->close_others_given = 1;
2302  eargp->close_others_do = TO_BOOL(val, "close_others");
2303  }
2304  else if (id == id_in) {
2305  key = INT2FIX(0);
2306  goto redirect;
2307  }
2308  else if (id == id_out) {
2309  key = INT2FIX(1);
2310  goto redirect;
2311  }
2312  else if (id == id_err) {
2313  key = INT2FIX(2);
2314  goto redirect;
2315  }
2316  else if (id == id_uid) {
2317 #ifdef HAVE_SETUID
2318  if (eargp->uid_given) {
2319  rb_raise(rb_eArgError, "uid option specified twice");
2320  }
2321  check_uid_switch();
2322  {
2323  eargp->uid = OBJ2UID(val);
2324  eargp->uid_given = 1;
2325  }
2326 #else
2328  "uid option is unimplemented on this machine");
2329 #endif
2330  }
2331  else if (id == id_gid) {
2332 #ifdef HAVE_SETGID
2333  if (eargp->gid_given) {
2334  rb_raise(rb_eArgError, "gid option specified twice");
2335  }
2336  check_gid_switch();
2337  {
2338  eargp->gid = OBJ2GID(val);
2339  eargp->gid_given = 1;
2340  }
2341 #else
2343  "gid option is unimplemented on this machine");
2344 #endif
2345  }
2346  else if (id == id_exception) {
2347  if (eargp->exception_given) {
2348  rb_raise(rb_eArgError, "exception option specified twice");
2349  }
2350  eargp->exception_given = 1;
2351  eargp->exception = TO_BOOL(val, "exception");
2352  }
2353  else {
2354  return ST_STOP;
2355  }
2356  break;
2357 
2358  case T_FIXNUM:
2359  case T_FILE:
2360  case T_ARRAY:
2361 redirect:
2362  check_exec_redirect(key, val, eargp);
2363  break;
2364 
2365  default:
2366  return ST_STOP;
2367  }
2368 
2369  RB_GC_GUARD(execarg_obj);
2370  return ST_CONTINUE;
2371 }
2372 
2373 static int
2374 check_exec_options_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
2375 {
2376  VALUE key = (VALUE)st_key;
2377  VALUE val = (VALUE)st_val;
2378  VALUE execarg_obj = (VALUE)arg;
2379  if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) {
2380  if (SYMBOL_P(key))
2381  rb_raise(rb_eArgError, "wrong exec option symbol: % "PRIsVALUE,
2382  key);
2383  rb_raise(rb_eArgError, "wrong exec option");
2384  }
2385  return ST_CONTINUE;
2386 }
2387 
2388 static int
2389 check_exec_options_i_extract(st_data_t st_key, st_data_t st_val, st_data_t arg)
2390 {
2391  VALUE key = (VALUE)st_key;
2392  VALUE val = (VALUE)st_val;
2393  VALUE *args = (VALUE *)arg;
2394  VALUE execarg_obj = args[0];
2395  if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) {
2396  VALUE nonopts = args[1];
2397  if (NIL_P(nonopts)) args[1] = nonopts = rb_hash_new();
2398  rb_hash_aset(nonopts, key, val);
2399  }
2400  return ST_CONTINUE;
2401 }
2402 
2403 static int
2404 check_exec_fds_1(struct rb_execarg *eargp, VALUE h, int maxhint, VALUE ary)
2405 {
2406  long i;
2407 
2408  if (ary != Qfalse) {
2409  for (i = 0; i < RARRAY_LEN(ary); i++) {
2410  VALUE elt = RARRAY_AREF(ary, i);
2411  int fd = FIX2INT(RARRAY_AREF(elt, 0));
2412  if (RTEST(rb_hash_lookup(h, INT2FIX(fd)))) {
2413  rb_raise(rb_eArgError, "fd %d specified twice", fd);
2414  }
2415  if (ary == eargp->fd_dup2)
2416  rb_hash_aset(h, INT2FIX(fd), Qtrue);
2417  else if (ary == eargp->fd_dup2_child)
2418  rb_hash_aset(h, INT2FIX(fd), RARRAY_AREF(elt, 1));
2419  else /* ary == eargp->fd_close */
2420  rb_hash_aset(h, INT2FIX(fd), INT2FIX(-1));
2421  if (maxhint < fd)
2422  maxhint = fd;
2423  if (ary == eargp->fd_dup2 || ary == eargp->fd_dup2_child) {
2424  fd = FIX2INT(RARRAY_AREF(elt, 1));
2425  if (maxhint < fd)
2426  maxhint = fd;
2427  }
2428  }
2429  }
2430  return maxhint;
2431 }
2432 
2433 static VALUE
2434 check_exec_fds(struct rb_execarg *eargp)
2435 {
2436  VALUE h = rb_hash_new();
2437  VALUE ary;
2438  int maxhint = -1;
2439  long i;
2440 
2441  maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_dup2);
2442  maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_close);
2443  maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_dup2_child);
2444 
2445  if (eargp->fd_dup2_child) {
2446  ary = eargp->fd_dup2_child;
2447  for (i = 0; i < RARRAY_LEN(ary); i++) {
2448  VALUE elt = RARRAY_AREF(ary, i);
2449  int newfd = FIX2INT(RARRAY_AREF(elt, 0));
2450  int oldfd = FIX2INT(RARRAY_AREF(elt, 1));
2451  int lastfd = oldfd;
2452  VALUE val = rb_hash_lookup(h, INT2FIX(lastfd));
2453  long depth = 0;
2454  while (FIXNUM_P(val) && 0 <= FIX2INT(val)) {
2455  lastfd = FIX2INT(val);
2456  val = rb_hash_lookup(h, val);
2457  if (RARRAY_LEN(ary) < depth)
2458  rb_raise(rb_eArgError, "cyclic child fd redirection from %d", oldfd);
2459  depth++;
2460  }
2461  if (val != Qtrue)
2462  rb_raise(rb_eArgError, "child fd %d is not redirected", oldfd);
2463  if (oldfd != lastfd) {
2464  VALUE val2;
2465  rb_ary_store(elt, 1, INT2FIX(lastfd));
2466  rb_hash_aset(h, INT2FIX(newfd), INT2FIX(lastfd));
2467  val = INT2FIX(oldfd);
2468  while (FIXNUM_P(val2 = rb_hash_lookup(h, val))) {
2469  rb_hash_aset(h, val, INT2FIX(lastfd));
2470  val = val2;
2471  }
2472  }
2473  }
2474  }
2475 
2476  eargp->close_others_maxhint = maxhint;
2477  return h;
2478 }
2479 
2480 static void
2481 rb_check_exec_options(VALUE opthash, VALUE execarg_obj)
2482 {
2483  if (RHASH_EMPTY_P(opthash))
2484  return;
2485  rb_hash_stlike_foreach(opthash, check_exec_options_i, (st_data_t)execarg_obj);
2486 }
2487 
2488 VALUE
2489 rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
2490 {
2491  VALUE args[2];
2492  if (RHASH_EMPTY_P(opthash))
2493  return Qnil;
2494  args[0] = execarg_obj;
2495  args[1] = Qnil;
2496  rb_hash_stlike_foreach(opthash, check_exec_options_i_extract, (st_data_t)args);
2497  return args[1];
2498 }
2499 
2500 #ifdef ENV_IGNORECASE
2501 #define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
2502 #else
2503 #define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
2504 #endif
2505 
2506 static int
2507 check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
2508 {
2509  VALUE key = (VALUE)st_key;
2510  VALUE val = (VALUE)st_val;
2511  VALUE env = ((VALUE *)arg)[0];
2512  VALUE *path = &((VALUE *)arg)[1];
2513  char *k;
2514 
2515  k = StringValueCStr(key);
2516  if (strchr(k, '='))
2517  rb_raise(rb_eArgError, "environment name contains a equal : %"PRIsVALUE, key);
2518 
2519  if (!NIL_P(val))
2520  StringValueCStr(val);
2521 
2522  key = EXPORT_STR(key);
2523  if (!NIL_P(val)) val = EXPORT_STR(val);
2524 
2525  if (ENVMATCH(k, PATH_ENV)) {
2526  *path = val;
2527  }
2528  rb_ary_push(env, hide_obj(rb_assoc_new(key, val)));
2529 
2530  return ST_CONTINUE;
2531 }
2532 
2533 static VALUE
2534 rb_check_exec_env(VALUE hash, VALUE *path)
2535 {
2536  VALUE env[2];
2537 
2538  env[0] = hide_obj(rb_ary_new());
2539  env[1] = Qfalse;
2540  rb_hash_stlike_foreach(hash, check_exec_env_i, (st_data_t)env);
2541  *path = env[1];
2542 
2543  return env[0];
2544 }
2545 
2546 static VALUE
2547 rb_check_argv(int argc, VALUE *argv)
2548 {
2549  VALUE tmp, prog;
2550  int i;
2551 
2553 
2554  prog = 0;
2555  tmp = rb_check_array_type(argv[0]);
2556  if (!NIL_P(tmp)) {
2557  if (RARRAY_LEN(tmp) != 2) {
2558  rb_raise(rb_eArgError, "wrong first argument");
2559  }
2560  prog = RARRAY_AREF(tmp, 0);
2561  argv[0] = RARRAY_AREF(tmp, 1);
2562  SafeStringValue(prog);
2563  StringValueCStr(prog);
2564  prog = rb_str_new_frozen(prog);
2565  }
2566  for (i = 0; i < argc; i++) {
2567  SafeStringValue(argv[i]);
2568  argv[i] = rb_str_new_frozen(argv[i]);
2569  StringValueCStr(argv[i]);
2570  }
2571  return prog;
2572 }
2573 
2574 static VALUE
2575 check_hash(VALUE obj)
2576 {
2577  if (RB_SPECIAL_CONST_P(obj)) return Qnil;
2578  switch (RB_BUILTIN_TYPE(obj)) {
2579  case T_STRING:
2580  case T_ARRAY:
2581  return Qnil;
2582  default:
2583  break;
2584  }
2585  return rb_check_hash_type(obj);
2586 }
2587 
2588 static VALUE
2589 rb_exec_getargs(int *argc_p, VALUE **argv_p, int accept_shell, VALUE *env_ret, VALUE *opthash_ret)
2590 {
2591  VALUE hash, prog;
2592 
2593  if (0 < *argc_p) {
2594  hash = check_hash((*argv_p)[*argc_p-1]);
2595  if (!NIL_P(hash)) {
2596  *opthash_ret = hash;
2597  (*argc_p)--;
2598  }
2599  }
2600 
2601  if (0 < *argc_p) {
2602  hash = check_hash((*argv_p)[0]);
2603  if (!NIL_P(hash)) {
2604  *env_ret = hash;
2605  (*argc_p)--;
2606  (*argv_p)++;
2607  }
2608  }
2609  prog = rb_check_argv(*argc_p, *argv_p);
2610  if (!prog) {
2611  prog = (*argv_p)[0];
2612  if (accept_shell && *argc_p == 1) {
2613  *argc_p = 0;
2614  *argv_p = 0;
2615  }
2616  }
2617  return prog;
2618 }
2619 
2620 #ifndef _WIN32
2621 struct string_part {
2622  const char *ptr;
2623  size_t len;
2624 };
2625 
2626 static int
2627 compare_posix_sh(const void *key, const void *el)
2628 {
2629  const struct string_part *word = key;
2630  int ret = strncmp(word->ptr, el, word->len);
2631  if (!ret && ((const char *)el)[word->len]) ret = -1;
2632  return ret;
2633 }
2634 #endif
2635 
2636 static void
2637 rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VALUE execarg_obj)
2638 {
2639  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2640  char fbuf[MAXPATHLEN];
2641 
2642  MEMZERO(eargp, struct rb_execarg, 1);
2643 
2644  if (!NIL_P(opthash)) {
2645  rb_check_exec_options(opthash, execarg_obj);
2646  }
2647  if (!NIL_P(env)) {
2648  env = rb_check_exec_env(env, &eargp->path_env);
2649  eargp->env_modification = env;
2650  }
2651 
2652  prog = EXPORT_STR(prog);
2653  eargp->use_shell = argc == 0;
2654  if (eargp->use_shell)
2655  eargp->invoke.sh.shell_script = prog;
2656  else
2657  eargp->invoke.cmd.command_name = prog;
2658 
2659 #ifndef _WIN32
2660  if (eargp->use_shell) {
2661  static const char posix_sh_cmds[][9] = {
2662  "!", /* reserved */
2663  ".", /* special built-in */
2664  ":", /* special built-in */
2665  "break", /* special built-in */
2666  "case", /* reserved */
2667  "continue", /* special built-in */
2668  "do", /* reserved */
2669  "done", /* reserved */
2670  "elif", /* reserved */
2671  "else", /* reserved */
2672  "esac", /* reserved */
2673  "eval", /* special built-in */
2674  "exec", /* special built-in */
2675  "exit", /* special built-in */
2676  "export", /* special built-in */
2677  "fi", /* reserved */
2678  "for", /* reserved */
2679  "if", /* reserved */
2680  "in", /* reserved */
2681  "readonly", /* special built-in */
2682  "return", /* special built-in */
2683  "set", /* special built-in */
2684  "shift", /* special built-in */
2685  "then", /* reserved */
2686  "times", /* special built-in */
2687  "trap", /* special built-in */
2688  "unset", /* special built-in */
2689  "until", /* reserved */
2690  "while", /* reserved */
2691  };
2692  const char *p;
2693  struct string_part first = {0, 0};
2694  int has_meta = 0;
2695  /*
2696  * meta characters:
2697  *
2698  * * Pathname Expansion
2699  * ? Pathname Expansion
2700  * {} Grouping Commands
2701  * [] Pathname Expansion
2702  * <> Redirection
2703  * () Grouping Commands
2704  * ~ Tilde Expansion
2705  * & AND Lists, Asynchronous Lists
2706  * | OR Lists, Pipelines
2707  * \ Escape Character
2708  * $ Parameter Expansion
2709  * ; Sequential Lists
2710  * ' Single-Quotes
2711  * ` Command Substitution
2712  * " Double-Quotes
2713  * \n Lists
2714  *
2715  * # Comment
2716  * = Assignment preceding command name
2717  * % (used in Parameter Expansion)
2718  */
2719  for (p = RSTRING_PTR(prog); *p; p++) {
2720  if (*p == ' ' || *p == '\t') {
2721  if (first.ptr && !first.len) first.len = p - first.ptr;
2722  }
2723  else {
2724  if (!first.ptr) first.ptr = p;
2725  }
2726  if (!has_meta && strchr("*?{}[]<>()~&|\\$;'`\"\n#", *p))
2727  has_meta = 1;
2728  if (!first.len) {
2729  if (*p == '=') {
2730  has_meta = 1;
2731  }
2732  else if (*p == '/') {
2733  first.len = 0x100; /* longer than any posix_sh_cmds */
2734  }
2735  }
2736  if (has_meta)
2737  break;
2738  }
2739  if (!has_meta && first.ptr) {
2740  if (!first.len) first.len = p - first.ptr;
2741  if (first.len > 0 && first.len <= sizeof(posix_sh_cmds[0]) &&
2742  bsearch(&first, posix_sh_cmds, numberof(posix_sh_cmds), sizeof(posix_sh_cmds[0]), compare_posix_sh))
2743  has_meta = 1;
2744  }
2745  if (!has_meta) {
2746  /* avoid shell since no shell meta character found. */
2747  eargp->use_shell = 0;
2748  }
2749  if (!eargp->use_shell) {
2750  VALUE argv_buf;
2751  argv_buf = hide_obj(rb_str_buf_new(0));
2752  p = RSTRING_PTR(prog);
2753  while (*p) {
2754  while (*p == ' ' || *p == '\t')
2755  p++;
2756  if (*p) {
2757  const char *w = p;
2758  while (*p && *p != ' ' && *p != '\t')
2759  p++;
2760  rb_str_buf_cat(argv_buf, w, p-w);
2761  rb_str_buf_cat(argv_buf, "", 1); /* append '\0' */
2762  }
2763  }
2764  eargp->invoke.cmd.argv_buf = argv_buf;
2765  eargp->invoke.cmd.command_name =
2766  hide_obj(rb_str_subseq(argv_buf, 0, strlen(RSTRING_PTR(argv_buf))));
2767  rb_enc_copy(eargp->invoke.cmd.command_name, prog);
2768  }
2769  }
2770 #endif
2771 
2772  if (!eargp->use_shell) {
2773  const char *abspath;
2774  const char *path_env = 0;
2775  if (RTEST(eargp->path_env)) path_env = RSTRING_PTR(eargp->path_env);
2776  abspath = dln_find_exe_r(RSTRING_PTR(eargp->invoke.cmd.command_name),
2777  path_env, fbuf, sizeof(fbuf));
2778  if (abspath)
2779  eargp->invoke.cmd.command_abspath = rb_str_new_cstr(abspath);
2780  else
2781  eargp->invoke.cmd.command_abspath = Qnil;
2782  }
2783 
2784  if (!eargp->use_shell && !eargp->invoke.cmd.argv_buf) {
2785  int i;
2786  VALUE argv_buf;
2787  argv_buf = rb_str_buf_new(0);
2788  hide_obj(argv_buf);
2789  for (i = 0; i < argc; i++) {
2790  VALUE arg = argv[i];
2791  const char *s = StringValueCStr(arg);
2792 #ifdef DEFAULT_PROCESS_ENCODING
2793  arg = EXPORT_STR(arg);
2794  s = RSTRING_PTR(arg);
2795 #endif
2796  rb_str_buf_cat(argv_buf, s, RSTRING_LEN(arg) + 1); /* include '\0' */
2797  }
2798  eargp->invoke.cmd.argv_buf = argv_buf;
2799  }
2800 
2801  if (!eargp->use_shell) {
2802  const char *p, *ep, *null=NULL;
2803  VALUE argv_str;
2804  argv_str = hide_obj(rb_str_buf_new(sizeof(char*) * (argc + 2)));
2805  rb_str_buf_cat(argv_str, (char *)&null, sizeof(null)); /* place holder for /bin/sh of try_with_sh. */
2806  p = RSTRING_PTR(eargp->invoke.cmd.argv_buf);
2807  ep = p + RSTRING_LEN(eargp->invoke.cmd.argv_buf);
2808  while (p < ep) {
2809  rb_str_buf_cat(argv_str, (char *)&p, sizeof(p));
2810  p += strlen(p) + 1;
2811  }
2812  rb_str_buf_cat(argv_str, (char *)&null, sizeof(null)); /* terminator for execve. */
2813  eargp->invoke.cmd.argv_str =
2814  rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(argv_str);
2815  }
2816  RB_GC_GUARD(execarg_obj);
2817 }
2818 
2819 struct rb_execarg *
2820 rb_execarg_get(VALUE execarg_obj)
2821 {
2822  struct rb_execarg *eargp;
2823  TypedData_Get_Struct(execarg_obj, struct rb_execarg, &exec_arg_data_type, eargp);
2824  return eargp;
2825 }
2826 
2827 static VALUE
2828 rb_execarg_init(int argc, const VALUE *orig_argv, int accept_shell, VALUE execarg_obj)
2829 {
2830  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2831  VALUE prog, ret;
2832  VALUE env = Qnil, opthash = Qnil;
2833  VALUE argv_buf;
2834  VALUE *argv = ALLOCV_N(VALUE, argv_buf, argc);
2835  MEMCPY(argv, orig_argv, VALUE, argc);
2836  prog = rb_exec_getargs(&argc, &argv, accept_shell, &env, &opthash);
2837  rb_exec_fillarg(prog, argc, argv, env, opthash, execarg_obj);
2838  ALLOCV_END(argv_buf);
2839  ret = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
2840  RB_GC_GUARD(execarg_obj);
2841  return ret;
2842 }
2843 
2844 VALUE
2845 rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt)
2846 {
2847  VALUE execarg_obj;
2848  struct rb_execarg *eargp;
2849  execarg_obj = TypedData_Make_Struct(0, struct rb_execarg, &exec_arg_data_type, eargp);
2850  rb_execarg_init(argc, argv, accept_shell, execarg_obj);
2851  if (!allow_exc_opt && eargp->exception_given) {
2852  rb_raise(rb_eArgError, "exception option is not allowed");
2853  }
2854  return execarg_obj;
2855 }
2856 
2857 void
2858 rb_execarg_setenv(VALUE execarg_obj, VALUE env)
2859 {
2860  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2861  env = !NIL_P(env) ? rb_check_exec_env(env, &eargp->path_env) : Qfalse;
2862  eargp->env_modification = env;
2863 }
2864 
2865 static int
2866 fill_envp_buf_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
2867 {
2868  VALUE key = (VALUE)st_key;
2869  VALUE val = (VALUE)st_val;
2870  VALUE envp_buf = (VALUE)arg;
2871 
2872  rb_str_buf_cat2(envp_buf, StringValueCStr(key));
2873  rb_str_buf_cat2(envp_buf, "=");
2874  rb_str_buf_cat2(envp_buf, StringValueCStr(val));
2875  rb_str_buf_cat(envp_buf, "", 1); /* append '\0' */
2876 
2877  return ST_CONTINUE;
2878 }
2879 
2880 
2881 static long run_exec_dup2_tmpbuf_size(long n);
2882 
2883 struct open_struct {
2884  VALUE fname;
2885  int oflags;
2886  mode_t perm;
2887  int ret;
2888  int err;
2889 };
2890 
2891 static void *
2892 open_func(void *ptr)
2893 {
2894  struct open_struct *data = ptr;
2895  const char *fname = RSTRING_PTR(data->fname);
2896  data->ret = parent_redirect_open(fname, data->oflags, data->perm);
2897  data->err = errno;
2898  return NULL;
2899 }
2900 
2901 static void
2902 rb_execarg_allocate_dup2_tmpbuf(struct rb_execarg *eargp, long len)
2903 {
2904  VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
2905  rb_imemo_tmpbuf_set_ptr(tmpbuf, ruby_xmalloc(run_exec_dup2_tmpbuf_size(len)));
2906  eargp->dup2_tmpbuf = tmpbuf;
2907 }
2908 
2909 static VALUE
2910 rb_execarg_parent_start1(VALUE execarg_obj)
2911 {
2912  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
2913  int unsetenv_others;
2914  VALUE envopts;
2915  VALUE ary;
2916 
2917  ary = eargp->fd_open;
2918  if (ary != Qfalse) {
2919  long i;
2920  for (i = 0; i < RARRAY_LEN(ary); i++) {
2921  VALUE elt = RARRAY_AREF(ary, i);
2922  int fd = FIX2INT(RARRAY_AREF(elt, 0));
2923  VALUE param = RARRAY_AREF(elt, 1);
2924  VALUE vpath = RARRAY_AREF(param, 0);
2925  int flags = NUM2INT(RARRAY_AREF(param, 1));
2926  mode_t perm = NUM2MODET(RARRAY_AREF(param, 2));
2927  VALUE fd2v = RARRAY_AREF(param, 3);
2928  int fd2;
2929  if (NIL_P(fd2v)) {
2930  struct open_struct open_data;
2931  again:
2932  open_data.fname = vpath;
2933  open_data.oflags = flags;
2934  open_data.perm = perm;
2935  open_data.ret = -1;
2936  open_data.err = EINTR;
2937  rb_thread_call_without_gvl2(open_func, (void *)&open_data, RUBY_UBF_IO, 0);
2938  if (open_data.ret == -1) {
2939  if (open_data.err == EINTR) {
2941  goto again;
2942  }
2943  rb_syserr_fail_str(open_data.err, vpath);
2944  }
2945  fd2 = open_data.ret;
2946  rb_update_max_fd(fd2);
2947  RARRAY_ASET(param, 3, INT2FIX(fd2));
2949  }
2950  else {
2951  fd2 = NUM2INT(fd2v);
2952  }
2953  rb_execarg_addopt(execarg_obj, INT2FIX(fd), INT2FIX(fd2));
2954  }
2955  }
2956 
2957  eargp->redirect_fds = check_exec_fds(eargp);
2958 
2959  ary = eargp->fd_dup2;
2960  if (ary != Qfalse) {
2961  rb_execarg_allocate_dup2_tmpbuf(eargp, RARRAY_LEN(ary));
2962  }
2963 
2964  unsetenv_others = eargp->unsetenv_others_given && eargp->unsetenv_others_do;
2965  envopts = eargp->env_modification;
2966  if (ALWAYS_NEED_ENVP || unsetenv_others || envopts != Qfalse) {
2967  VALUE envtbl, envp_str, envp_buf;
2968  char *p, *ep;
2969  if (unsetenv_others) {
2970  envtbl = rb_hash_new();
2971  }
2972  else {
2973  envtbl = rb_env_to_hash();
2974  }
2975  hide_obj(envtbl);
2976  if (envopts != Qfalse) {
2977  st_table *stenv = RHASH_TBL_RAW(envtbl);
2978  long i;
2979  for (i = 0; i < RARRAY_LEN(envopts); i++) {
2980  VALUE pair = RARRAY_AREF(envopts, i);
2981  VALUE key = RARRAY_AREF(pair, 0);
2982  VALUE val = RARRAY_AREF(pair, 1);
2983  if (NIL_P(val)) {
2984  st_data_t stkey = (st_data_t)key;
2985  st_delete(stenv, &stkey, NULL);
2986  }
2987  else {
2988  st_insert(stenv, (st_data_t)key, (st_data_t)val);
2989  RB_OBJ_WRITTEN(envtbl, Qundef, key);
2990  RB_OBJ_WRITTEN(envtbl, Qundef, val);
2991  }
2992  }
2993  }
2994  envp_buf = rb_str_buf_new(0);
2995  hide_obj(envp_buf);
2996  rb_hash_stlike_foreach(envtbl, fill_envp_buf_i, (st_data_t)envp_buf);
2997  envp_str = rb_str_buf_new(sizeof(char*) * (RHASH_SIZE(envtbl) + 1));
2998  hide_obj(envp_str);
2999  p = RSTRING_PTR(envp_buf);
3000  ep = p + RSTRING_LEN(envp_buf);
3001  while (p < ep) {
3002  rb_str_buf_cat(envp_str, (char *)&p, sizeof(p));
3003  p += strlen(p) + 1;
3004  }
3005  p = NULL;
3006  rb_str_buf_cat(envp_str, (char *)&p, sizeof(p));
3007  eargp->envp_str =
3008  rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(envp_str);
3009  eargp->envp_buf = envp_buf;
3010 
3011  /*
3012  char **tmp_envp = (char **)RSTRING_PTR(envp_str);
3013  while (*tmp_envp) {
3014  printf("%s\n", *tmp_envp);
3015  tmp_envp++;
3016  }
3017  */
3018  }
3019 
3020  RB_GC_GUARD(execarg_obj);
3021  return Qnil;
3022 }
3023 
3024 void
3025 rb_execarg_parent_start(VALUE execarg_obj)
3026 {
3027  int state;
3028  rb_protect(rb_execarg_parent_start1, execarg_obj, &state);
3029  if (state) {
3030  rb_execarg_parent_end(execarg_obj);
3031  rb_jump_tag(state);
3032  }
3033 }
3034 
3035 static VALUE
3036 execarg_parent_end(VALUE execarg_obj)
3037 {
3038  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
3039  int err = errno;
3040  VALUE ary;
3041 
3042  ary = eargp->fd_open;
3043  if (ary != Qfalse) {
3044  long i;
3045  for (i = 0; i < RARRAY_LEN(ary); i++) {
3046  VALUE elt = RARRAY_AREF(ary, i);
3047  VALUE param = RARRAY_AREF(elt, 1);
3048  VALUE fd2v;
3049  int fd2;
3050  fd2v = RARRAY_AREF(param, 3);
3051  if (!NIL_P(fd2v)) {
3052  fd2 = FIX2INT(fd2v);
3053  parent_redirect_close(fd2);
3054  RARRAY_ASET(param, 3, Qnil);
3055  }
3056  }
3057  }
3058 
3059  errno = err;
3060  return execarg_obj;
3061 }
3062 
3063 void
3064 rb_execarg_parent_end(VALUE execarg_obj)
3065 {
3066  execarg_parent_end(execarg_obj);
3067  RB_GC_GUARD(execarg_obj);
3068 }
3069 
3070 static void
3071 rb_exec_fail(struct rb_execarg *eargp, int err, const char *errmsg)
3072 {
3073  if (!errmsg || !*errmsg) return;
3074  if (strcmp(errmsg, "chdir") == 0) {
3075  rb_sys_fail_str(eargp->chdir_dir);
3076  }
3077  rb_sys_fail(errmsg);
3078 }
3079 
3080 #if 0
3081 void
3082 rb_execarg_fail(VALUE execarg_obj, int err, const char *errmsg)
3083 {
3084  if (!errmsg || !*errmsg) return;
3085  rb_exec_fail(rb_execarg_get(execarg_obj), err, errmsg);
3086  RB_GC_GUARD(execarg_obj);
3087 }
3088 #endif
3089 
3090 VALUE
3091 rb_f_exec(int argc, const VALUE *argv)
3092 {
3093  VALUE execarg_obj, fail_str;
3094  struct rb_execarg *eargp;
3095 #define CHILD_ERRMSG_BUFLEN 80
3096  char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
3097  int err, state;
3098 
3099  execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
3100  eargp = rb_execarg_get(execarg_obj);
3101  if (mjit_enabled) mjit_finish(false); // avoid leaking resources, and do not leave files. XXX: JIT-ed handle can leak after exec error is rescued.
3102  before_exec(); /* stop timer thread before redirects */
3103 
3104  rb_protect(rb_execarg_parent_start1, execarg_obj, &state);
3105  if (state) {
3106  execarg_parent_end(execarg_obj);
3107  after_exec(); /* restart timer thread */
3108  rb_jump_tag(state);
3109  }
3110 
3111  fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
3112 
3113  err = exec_async_signal_safe(eargp, errmsg, sizeof(errmsg));
3114  after_exec(); /* restart timer thread */
3115 
3116  rb_exec_fail(eargp, err, errmsg);
3117  RB_GC_GUARD(execarg_obj);
3118  rb_syserr_fail_str(err, fail_str);
3120 }
3121 
3122 NORETURN(static VALUE f_exec(int c, const VALUE *a, VALUE _));
3123 
3124 /*
3125  * call-seq:
3126  * exec([env,] command... [,options])
3127  *
3128  * Replaces the current process by running the given external _command_, which
3129  * can take one of the following forms:
3130  *
3131  * [<code>exec(commandline)</code>]
3132  * command line string which is passed to the standard shell
3133  * [<code>exec(cmdname, arg1, ...)</code>]
3134  * command name and one or more arguments (no shell)
3135  * [<code>exec([cmdname, argv0], arg1, ...)</code>]
3136  * command name, argv[0] and zero or more arguments (no shell)
3137  *
3138  * In the first form, the string is taken as a command line that is subject to
3139  * shell expansion before being executed.
3140  *
3141  * The standard shell always means <code>"/bin/sh"</code> on Unix-like systems,
3142  * otherwise, <code>ENV["RUBYSHELL"]</code> or <code>ENV["COMSPEC"]</code> on
3143  * Windows and similar. The command is passed as an argument to the
3144  * <code>"-c"</code> switch to the shell, except in the case of +COMSPEC+.
3145  *
3146  * If the string from the first form (<code>exec("command")</code>) follows
3147  * these simple rules:
3148  *
3149  * * no meta characters
3150  * * not starting with shell reserved word or special built-in
3151  * * Ruby invokes the command directly without shell
3152  *
3153  * You can force shell invocation by adding ";" to the string (because ";" is
3154  * a meta character).
3155  *
3156  * Note that this behavior is observable by pid obtained
3157  * (return value of spawn() and IO#pid for IO.popen) is the pid of the invoked
3158  * command, not shell.
3159  *
3160  * In the second form (<code>exec("command1", "arg1", ...)</code>), the first
3161  * is taken as a command name and the rest are passed as parameters to command
3162  * with no shell expansion.
3163  *
3164  * In the third form (<code>exec(["command", "argv0"], "arg1", ...)</code>),
3165  * starting a two-element array at the beginning of the command, the first
3166  * element is the command to be executed, and the second argument is used as
3167  * the <code>argv[0]</code> value, which may show up in process listings.
3168  *
3169  * In order to execute the command, one of the <code>exec(2)</code> system
3170  * calls are used, so the running command may inherit some of the environment
3171  * of the original program (including open file descriptors).
3172  *
3173  * This behavior is modified by the given +env+ and +options+ parameters. See
3174  * ::spawn for details.
3175  *
3176  * If the command fails to execute (typically Errno::ENOENT when
3177  * it was not found) a SystemCallError exception is raised.
3178  *
3179  * This method modifies process attributes according to given +options+ before
3180  * <code>exec(2)</code> system call. See ::spawn for more details about the
3181  * given +options+.
3182  *
3183  * The modified attributes may be retained when <code>exec(2)</code> system
3184  * call fails.
3185  *
3186  * For example, hard resource limits are not restorable.
3187  *
3188  * Consider to create a child process using ::spawn or Kernel#system if this
3189  * is not acceptable.
3190  *
3191  * exec "echo *" # echoes list of files in current directory
3192  * # never get here
3193  *
3194  * exec "echo", "*" # echoes an asterisk
3195  * # never get here
3196  */
3197 
3198 static VALUE
3199 f_exec(int c, const VALUE *a, VALUE _)
3200 {
3201  rb_f_exec(c, a);
3203 }
3204 
3205 #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
3206 #define ERRMSG1(str, a) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a)); } while (0)
3207 #define ERRMSG2(str, a, b) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a), (b)); } while (0)
3208 
3209 static int fd_get_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
3210 static int fd_set_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
3211 static int fd_clear_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
3212 
3213 static int
3214 save_redirect_fd(int fd, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
3215 {
3216  if (sargp) {
3217  VALUE newary, redirection;
3218  int save_fd = redirect_cloexec_dup(fd), cloexec;
3219  if (save_fd == -1) {
3220  if (errno == EBADF)
3221  return 0;
3222  ERRMSG("dup");
3223  return -1;
3224  }
3225  rb_update_max_fd(save_fd);
3226  newary = sargp->fd_dup2;
3227  if (newary == Qfalse) {
3228  newary = hide_obj(rb_ary_new());
3229  sargp->fd_dup2 = newary;
3230  }
3231  cloexec = fd_get_cloexec(fd, errmsg, errmsg_buflen);
3232  redirection = hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd)));
3233  if (cloexec) rb_ary_push(redirection, Qtrue);
3234  rb_ary_push(newary, redirection);
3235 
3236  newary = sargp->fd_close;
3237  if (newary == Qfalse) {
3238  newary = hide_obj(rb_ary_new());
3239  sargp->fd_close = newary;
3240  }
3241  rb_ary_push(newary, hide_obj(rb_assoc_new(INT2FIX(save_fd), Qnil)));
3242  }
3243 
3244  return 0;
3245 }
3246 
3247 static int
3248 intcmp(const void *a, const void *b)
3249 {
3250  return *(int*)a - *(int*)b;
3251 }
3252 
3253 static int
3254 intrcmp(const void *a, const void *b)
3255 {
3256  return *(int*)b - *(int*)a;
3257 }
3258 
3260  int oldfd;
3261  int newfd;
3262  long older_index;
3263  long num_newer;
3264  int cloexec;
3265 };
3266 
3267 static long
3268 run_exec_dup2_tmpbuf_size(long n)
3269 {
3270  return sizeof(struct run_exec_dup2_fd_pair) * n;
3271 }
3272 
3273 /* This function should be async-signal-safe. Actually it is. */
3274 static int
3275 fd_get_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
3276 {
3277 #ifdef F_GETFD
3278  int ret = 0;
3279  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
3280  if (ret == -1) {
3281  ERRMSG("fcntl(F_GETFD)");
3282  return -1;
3283  }
3284  if (ret & FD_CLOEXEC) return 1;
3285 #endif
3286  return 0;
3287 }
3288 
3289 /* This function should be async-signal-safe. Actually it is. */
3290 static int
3291 fd_set_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
3292 {
3293 #ifdef F_GETFD
3294  int ret = 0;
3295  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
3296  if (ret == -1) {
3297  ERRMSG("fcntl(F_GETFD)");
3298  return -1;
3299  }
3300  if (!(ret & FD_CLOEXEC)) {
3301  ret |= FD_CLOEXEC;
3302  ret = fcntl(fd, F_SETFD, ret); /* async-signal-safe */
3303  if (ret == -1) {
3304  ERRMSG("fcntl(F_SETFD)");
3305  return -1;
3306  }
3307  }
3308 #endif
3309  return 0;
3310 }
3311 
3312 /* This function should be async-signal-safe. Actually it is. */
3313 static int
3314 fd_clear_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
3315 {
3316 #ifdef F_GETFD
3317  int ret;
3318  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
3319  if (ret == -1) {
3320  ERRMSG("fcntl(F_GETFD)");
3321  return -1;
3322  }
3323  if (ret & FD_CLOEXEC) {
3324  ret &= ~FD_CLOEXEC;
3325  ret = fcntl(fd, F_SETFD, ret); /* async-signal-safe */
3326  if (ret == -1) {
3327  ERRMSG("fcntl(F_SETFD)");
3328  return -1;
3329  }
3330  }
3331 #endif
3332  return 0;
3333 }
3334 
3335 /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
3336 static int
3337 run_exec_dup2(VALUE ary, VALUE tmpbuf, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
3338 {
3339  long n, i;
3340  int ret;
3341  int extra_fd = -1;
3342  struct rb_imemo_tmpbuf_struct *buf = (void *)tmpbuf;
3343  struct run_exec_dup2_fd_pair *pairs = (void *)buf->ptr;
3344 
3345  n = RARRAY_LEN(ary);
3346 
3347  /* initialize oldfd and newfd: O(n) */
3348  for (i = 0; i < n; i++) {
3349  VALUE elt = RARRAY_AREF(ary, i);
3350  pairs[i].oldfd = FIX2INT(RARRAY_AREF(elt, 1));
3351  pairs[i].newfd = FIX2INT(RARRAY_AREF(elt, 0)); /* unique */
3352  pairs[i].cloexec = RARRAY_LEN(elt) > 2 && RTEST(RARRAY_AREF(elt, 2));
3353  pairs[i].older_index = -1;
3354  }
3355 
3356  /* sort the table by oldfd: O(n log n) */
3357  if (!sargp)
3358  qsort(pairs, n, sizeof(struct run_exec_dup2_fd_pair), intcmp); /* hopefully async-signal-safe */
3359  else
3360  qsort(pairs, n, sizeof(struct run_exec_dup2_fd_pair), intrcmp);
3361 
3362  /* initialize older_index and num_newer: O(n log n) */
3363  for (i = 0; i < n; i++) {
3364  int newfd = pairs[i].newfd;
3365  struct run_exec_dup2_fd_pair key, *found;
3366  key.oldfd = newfd;
3367  found = bsearch(&key, pairs, n, sizeof(struct run_exec_dup2_fd_pair), intcmp); /* hopefully async-signal-safe */
3368  pairs[i].num_newer = 0;
3369  if (found) {
3370  while (pairs < found && (found-1)->oldfd == newfd)
3371  found--;
3372  while (found < pairs+n && found->oldfd == newfd) {
3373  pairs[i].num_newer++;
3374  found->older_index = i;
3375  found++;
3376  }
3377  }
3378  }
3379 
3380  /* non-cyclic redirection: O(n) */
3381  for (i = 0; i < n; i++) {
3382  long j = i;
3383  while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
3384  if (save_redirect_fd(pairs[j].newfd, sargp, errmsg, errmsg_buflen) < 0) /* async-signal-safe */
3385  goto fail;
3386  ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd); /* async-signal-safe */
3387  if (ret == -1) {
3388  ERRMSG("dup2");
3389  goto fail;
3390  }
3391  if (pairs[j].cloexec &&
3392  fd_set_cloexec(pairs[j].newfd, errmsg, errmsg_buflen)) {
3393  goto fail;
3394  }
3395  rb_update_max_fd(pairs[j].newfd); /* async-signal-safe but don't need to call it in a child process. */
3396  pairs[j].oldfd = -1;
3397  j = pairs[j].older_index;
3398  if (j != -1)
3399  pairs[j].num_newer--;
3400  }
3401  }
3402 
3403  /* cyclic redirection: O(n) */
3404  for (i = 0; i < n; i++) {
3405  long j;
3406  if (pairs[i].oldfd == -1)
3407  continue;
3408  if (pairs[i].oldfd == pairs[i].newfd) { /* self cycle */
3409  if (fd_clear_cloexec(pairs[i].oldfd, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
3410  goto fail;
3411  pairs[i].oldfd = -1;
3412  continue;
3413  }
3414  if (extra_fd == -1) {
3415  extra_fd = redirect_dup(pairs[i].oldfd); /* async-signal-safe */
3416  if (extra_fd == -1) {
3417  ERRMSG("dup");
3418  goto fail;
3419  }
3420  rb_update_max_fd(extra_fd);
3421  }
3422  else {
3423  ret = redirect_dup2(pairs[i].oldfd, extra_fd); /* async-signal-safe */
3424  if (ret == -1) {
3425  ERRMSG("dup2");
3426  goto fail;
3427  }
3428  rb_update_max_fd(extra_fd);
3429  }
3430  pairs[i].oldfd = extra_fd;
3431  j = pairs[i].older_index;
3432  pairs[i].older_index = -1;
3433  while (j != -1) {
3434  ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd); /* async-signal-safe */
3435  if (ret == -1) {
3436  ERRMSG("dup2");
3437  goto fail;
3438  }
3439  rb_update_max_fd(ret);
3440  pairs[j].oldfd = -1;
3441  j = pairs[j].older_index;
3442  }
3443  }
3444  if (extra_fd != -1) {
3445  ret = redirect_close(extra_fd); /* async-signal-safe */
3446  if (ret == -1) {
3447  ERRMSG("close");
3448  goto fail;
3449  }
3450  }
3451 
3452  return 0;
3453 
3454  fail:
3455  return -1;
3456 }
3457 
3458 /* This function should be async-signal-safe. Actually it is. */
3459 static int
3460 run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
3461 {
3462  long i;
3463  int ret;
3464 
3465  for (i = 0; i < RARRAY_LEN(ary); i++) {
3466  VALUE elt = RARRAY_AREF(ary, i);
3467  int fd = FIX2INT(RARRAY_AREF(elt, 0));
3468  ret = redirect_close(fd); /* async-signal-safe */
3469  if (ret == -1) {
3470  ERRMSG("close");
3471  return -1;
3472  }
3473  }
3474  return 0;
3475 }
3476 
3477 /* This function should be async-signal-safe when sargp is NULL. Actually it is. */
3478 static int
3479 run_exec_dup2_child(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
3480 {
3481  long i;
3482  int ret;
3483 
3484  for (i = 0; i < RARRAY_LEN(ary); i++) {
3485  VALUE elt = RARRAY_AREF(ary, i);
3486  int newfd = FIX2INT(RARRAY_AREF(elt, 0));
3487  int oldfd = FIX2INT(RARRAY_AREF(elt, 1));
3488 
3489  if (save_redirect_fd(newfd, sargp, errmsg, errmsg_buflen) < 0) /* async-signal-safe */
3490  return -1;
3491  ret = redirect_dup2(oldfd, newfd); /* async-signal-safe */
3492  if (ret == -1) {
3493  ERRMSG("dup2");
3494  return -1;
3495  }
3496  rb_update_max_fd(newfd);
3497  }
3498  return 0;
3499 }
3500 
3501 #ifdef HAVE_SETPGID
3502 /* This function should be async-signal-safe when sargp is NULL. Actually it is. */
3503 static int
3504 run_exec_pgroup(const struct rb_execarg *eargp, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
3505 {
3506  /*
3507  * If FD_CLOEXEC is available, rb_fork_async_signal_safe waits the child's execve.
3508  * So setpgid is done in the child when rb_fork_async_signal_safe is returned in
3509  * the parent.
3510  * No race condition, even without setpgid from the parent.
3511  * (Is there an environment which has setpgid but no FD_CLOEXEC?)
3512  */
3513  int ret;
3514  rb_pid_t pgroup;
3515 
3516  pgroup = eargp->pgroup_pgid;
3517  if (pgroup == -1)
3518  return 0;
3519 
3520  if (sargp) {
3521  /* maybe meaningless with no fork environment... */
3522  sargp->pgroup_given = 1;
3523  sargp->pgroup_pgid = getpgrp();
3524  }
3525 
3526  if (pgroup == 0) {
3527  pgroup = getpid(); /* async-signal-safe */
3528  }
3529  ret = setpgid(getpid(), pgroup); /* async-signal-safe */
3530  if (ret == -1) ERRMSG("setpgid");
3531  return ret;
3532 }
3533 #endif
3534 
3535 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
3536 /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
3537 static int
3538 run_exec_rlimit(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
3539 {
3540  long i;
3541  for (i = 0; i < RARRAY_LEN(ary); i++) {
3542  VALUE elt = RARRAY_AREF(ary, i);
3543  int rtype = NUM2INT(RARRAY_AREF(elt, 0));
3544  struct rlimit rlim;
3545  if (sargp) {
3546  VALUE tmp, newary;
3547  if (getrlimit(rtype, &rlim) == -1) {
3548  ERRMSG("getrlimit");
3549  return -1;
3550  }
3551  tmp = hide_obj(rb_ary_new3(3, RARRAY_AREF(elt, 0),
3552  RLIM2NUM(rlim.rlim_cur),
3553  RLIM2NUM(rlim.rlim_max)));
3554  if (sargp->rlimit_limits == Qfalse)
3555  newary = sargp->rlimit_limits = hide_obj(rb_ary_new());
3556  else
3557  newary = sargp->rlimit_limits;
3558  rb_ary_push(newary, tmp);
3559  }
3560  rlim.rlim_cur = NUM2RLIM(RARRAY_AREF(elt, 1));
3561  rlim.rlim_max = NUM2RLIM(RARRAY_AREF(elt, 2));
3562  if (setrlimit(rtype, &rlim) == -1) { /* hopefully async-signal-safe */
3563  ERRMSG("setrlimit");
3564  return -1;
3565  }
3566  }
3567  return 0;
3568 }
3569 #endif
3570 
3571 #if !defined(HAVE_WORKING_FORK)
3572 static VALUE
3573 save_env_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
3574 {
3575  rb_ary_push(ary, hide_obj(rb_ary_dup(argv[0])));
3576  return Qnil;
3577 }
3578 
3579 static void
3580 save_env(struct rb_execarg *sargp)
3581 {
3582  if (!sargp)
3583  return;
3584  if (sargp->env_modification == Qfalse) {
3585  VALUE env = rb_envtbl();
3586  if (RTEST(env)) {
3587  VALUE ary = hide_obj(rb_ary_new());
3588  rb_block_call(env, idEach, 0, 0, save_env_i,
3589  (VALUE)ary);
3590  sargp->env_modification = ary;
3591  }
3592  sargp->unsetenv_others_given = 1;
3593  sargp->unsetenv_others_do = 1;
3594  }
3595 }
3596 #endif
3597 
3598 #ifdef _WIN32
3599 #undef chdir
3600 #define chdir(p) rb_w32_uchdir(p)
3601 #endif
3602 
3603 /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
3604 int
3605 rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
3606 {
3607  VALUE obj;
3608 
3609  if (sargp) {
3610  /* assume that sargp is always NULL on fork-able environments */
3611  MEMZERO(sargp, struct rb_execarg, 1);
3612  sargp->redirect_fds = Qnil;
3613  }
3614 
3615 #ifdef HAVE_SETPGID
3616  if (eargp->pgroup_given) {
3617  if (run_exec_pgroup(eargp, sargp, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
3618  return -1;
3619  }
3620 #endif
3621 
3622 #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
3623  obj = eargp->rlimit_limits;
3624  if (obj != Qfalse) {
3625  if (run_exec_rlimit(obj, sargp, errmsg, errmsg_buflen) == -1) /* hopefully async-signal-safe */
3626  return -1;
3627  }
3628 #endif
3629 
3630 #if !defined(HAVE_WORKING_FORK)
3631  if (eargp->unsetenv_others_given && eargp->unsetenv_others_do) {
3632  save_env(sargp);
3633  rb_env_clear();
3634  }
3635 
3636  obj = eargp->env_modification;
3637  if (obj != Qfalse) {
3638  long i;
3639  save_env(sargp);
3640  for (i = 0; i < RARRAY_LEN(obj); i++) {
3641  VALUE pair = RARRAY_AREF(obj, i);
3642  VALUE key = RARRAY_AREF(pair, 0);
3643  VALUE val = RARRAY_AREF(pair, 1);
3644  if (NIL_P(val))
3645  ruby_setenv(StringValueCStr(key), 0);
3646  else
3648  }
3649  }
3650 #endif
3651 
3652  if (eargp->umask_given) {
3653  mode_t mask = eargp->umask_mask;
3654  mode_t oldmask = umask(mask); /* never fail */ /* async-signal-safe */
3655  if (sargp) {
3656  sargp->umask_given = 1;
3657  sargp->umask_mask = oldmask;
3658  }
3659  }
3660 
3661  obj = eargp->fd_dup2;
3662  if (obj != Qfalse) {
3663  if (run_exec_dup2(obj, eargp->dup2_tmpbuf, sargp, errmsg, errmsg_buflen) == -1) /* hopefully async-signal-safe */
3664  return -1;
3665  }
3666 
3667  obj = eargp->fd_close;
3668  if (obj != Qfalse) {
3669  if (sargp)
3670  rb_warn("cannot close fd before spawn");
3671  else {
3672  if (run_exec_close(obj, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
3673  return -1;
3674  }
3675  }
3676 
3677 #ifdef HAVE_WORKING_FORK
3678  if (eargp->close_others_do) {
3679  rb_close_before_exec(3, eargp->close_others_maxhint, eargp->redirect_fds); /* async-signal-safe */
3680  }
3681 #endif
3682 
3683  obj = eargp->fd_dup2_child;
3684  if (obj != Qfalse) {
3685  if (run_exec_dup2_child(obj, sargp, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
3686  return -1;
3687  }
3688 
3689  if (eargp->chdir_given) {
3690  if (sargp) {
3691  sargp->chdir_given = 1;
3692  sargp->chdir_dir = hide_obj(rb_dir_getwd_ospath());
3693  }
3694  if (chdir(RSTRING_PTR(eargp->chdir_dir)) == -1) { /* async-signal-safe */
3695  ERRMSG("chdir");
3696  return -1;
3697  }
3698  }
3699 
3700 #ifdef HAVE_SETGID
3701  if (eargp->gid_given) {
3702  if (setgid(eargp->gid) < 0) {
3703  ERRMSG("setgid");
3704  return -1;
3705  }
3706  }
3707 #endif
3708 #ifdef HAVE_SETUID
3709  if (eargp->uid_given) {
3710  if (setuid(eargp->uid) < 0) {
3711  ERRMSG("setuid");
3712  return -1;
3713  }
3714  }
3715 #endif
3716 
3717  if (sargp) {
3718  VALUE ary = sargp->fd_dup2;
3719  if (ary != Qfalse) {
3720  rb_execarg_allocate_dup2_tmpbuf(sargp, RARRAY_LEN(ary));
3721  }
3722  }
3723  {
3724  int preserve = errno;
3725  stdfd_clear_nonblock();
3726  errno = preserve;
3727  }
3728 
3729  return 0;
3730 }
3731 
3732 /* This function should be async-signal-safe. Hopefully it is. */
3733 int
3734 rb_exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
3735 {
3736  errno = exec_async_signal_safe(eargp, errmsg, errmsg_buflen);
3737  return -1;
3738 }
3739 
3740 static int
3741 exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
3742 {
3743 #if !defined(HAVE_WORKING_FORK)
3744  struct rb_execarg sarg, *const sargp = &sarg;
3745 #else
3746  struct rb_execarg *const sargp = NULL;
3747 #endif
3748  int err;
3749 
3750  if (rb_execarg_run_options(eargp, sargp, errmsg, errmsg_buflen) < 0) { /* hopefully async-signal-safe */
3751  return errno;
3752  }
3753 
3754  if (eargp->use_shell) {
3755  err = proc_exec_sh(RSTRING_PTR(eargp->invoke.sh.shell_script), eargp->envp_str); /* async-signal-safe */
3756  }
3757  else {
3758  char *abspath = NULL;
3759  if (!NIL_P(eargp->invoke.cmd.command_abspath))
3760  abspath = RSTRING_PTR(eargp->invoke.cmd.command_abspath);
3761  err = proc_exec_cmd(abspath, eargp->invoke.cmd.argv_str, eargp->envp_str); /* async-signal-safe */
3762  }
3763 #if !defined(HAVE_WORKING_FORK)
3764  rb_execarg_run_options(sargp, NULL, errmsg, errmsg_buflen);
3765 #endif
3766 
3767  return err;
3768 }
3769 
3770 #ifdef HAVE_WORKING_FORK
3771 /* This function should be async-signal-safe. Hopefully it is. */
3772 static int
3773 rb_exec_atfork(void* arg, char *errmsg, size_t errmsg_buflen)
3774 {
3775  return rb_exec_async_signal_safe(arg, errmsg, errmsg_buflen); /* hopefully async-signal-safe */
3776 }
3777 
3778 #if SIZEOF_INT == SIZEOF_LONG
3779 #define proc_syswait (VALUE (*)(VALUE))rb_syswait
3780 #else
3781 static VALUE
3782 proc_syswait(VALUE pid)
3783 {
3784  rb_syswait((int)pid);
3785  return Qnil;
3786 }
3787 #endif
3788 
3789 static int
3790 move_fds_to_avoid_crash(int *fdp, int n, VALUE fds)
3791 {
3792  int min = 0;
3793  int i;
3794  for (i = 0; i < n; i++) {
3795  int ret;
3796  while (RTEST(rb_hash_lookup(fds, INT2FIX(fdp[i])))) {
3797  if (min <= fdp[i])
3798  min = fdp[i]+1;
3799  while (RTEST(rb_hash_lookup(fds, INT2FIX(min))))
3800  min++;
3801  ret = rb_cloexec_fcntl_dupfd(fdp[i], min);
3802  if (ret == -1)
3803  return -1;
3804  rb_update_max_fd(ret);
3805  close(fdp[i]);
3806  fdp[i] = ret;
3807  }
3808  }
3809  return 0;
3810 }
3811 
3812 static int
3813 pipe_nocrash(int filedes[2], VALUE fds)
3814 {
3815  int ret;
3816  ret = rb_pipe(filedes);
3817  if (ret == -1)
3818  return -1;
3819  if (RTEST(fds)) {
3820  int save = errno;
3821  if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
3822  close(filedes[0]);
3823  close(filedes[1]);
3824  return -1;
3825  }
3826  errno = save;
3827  }
3828  return ret;
3829 }
3830 
3831 #ifndef O_BINARY
3832 #define O_BINARY 0
3833 #endif
3834 
3835 static VALUE
3836 rb_thread_sleep_that_takes_VALUE_as_sole_argument(VALUE n)
3837 {
3839  return Qundef;
3840 }
3841 
3842 static int
3843 handle_fork_error(int err, struct rb_process_status *status, int *ep, volatile int *try_gc_p)
3844 {
3845  int state = 0;
3846 
3847  switch (err) {
3848  case ENOMEM:
3849  if ((*try_gc_p)-- > 0 && !rb_during_gc()) {
3850  rb_gc();
3851  return 0;
3852  }
3853  break;
3854  case EAGAIN:
3855 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
3856  case EWOULDBLOCK:
3857 #endif
3858  if (!status && !ep) {
3859  rb_thread_sleep(1);
3860  return 0;
3861  }
3862  else {
3863  rb_protect(rb_thread_sleep_that_takes_VALUE_as_sole_argument, INT2FIX(1), &state);
3864  if (status) status->status = state;
3865  if (!state) return 0;
3866  }
3867  break;
3868  }
3869  if (ep) {
3870  close(ep[0]);
3871  close(ep[1]);
3872  errno = err;
3873  }
3874  if (state && !status) rb_jump_tag(state);
3875  return -1;
3876 }
3877 
3878 #define prefork() ( \
3879  rb_io_flush(rb_stdout), \
3880  rb_io_flush(rb_stderr) \
3881  )
3882 
3883 /*
3884  * Forks child process, and returns the process ID in the parent
3885  * process.
3886  *
3887  * If +status+ is given, protects from any exceptions and sets the
3888  * jump status to it, and returns -1. If failed to fork new process
3889  * but no exceptions occurred, sets 0 to it. Otherwise, if forked
3890  * successfully, the value of +status+ is undetermined.
3891  *
3892  * In the child process, just returns 0 if +chfunc+ is +NULL+.
3893  * Otherwise +chfunc+ will be called with +charg+, and then the child
3894  * process exits with +EXIT_SUCCESS+ when it returned zero.
3895  *
3896  * In the case of the function is called and returns non-zero value,
3897  * the child process exits with non-+EXIT_SUCCESS+ value (normally
3898  * 127). And, on the platforms where +FD_CLOEXEC+ is available,
3899  * +errno+ is propagated to the parent process, and this function
3900  * returns -1 in the parent process. On the other platforms, just
3901  * returns pid.
3902  *
3903  * If fds is not Qnil, internal pipe for the errno propagation is
3904  * arranged to avoid conflicts of the hash keys in +fds+.
3905  *
3906  * +chfunc+ must not raise any exceptions.
3907  */
3908 
3909 static ssize_t
3910 write_retry(int fd, const void *buf, size_t len)
3911 {
3912  ssize_t w;
3913 
3914  do {
3915  w = write(fd, buf, len);
3916  } while (w < 0 && errno == EINTR);
3917 
3918  return w;
3919 }
3920 
3921 static ssize_t
3922 read_retry(int fd, void *buf, size_t len)
3923 {
3924  ssize_t r;
3925 
3926  if (set_blocking(fd) != 0) {
3927 #ifndef _WIN32
3928  rb_async_bug_errno("set_blocking failed reading child error", errno);
3929 #endif
3930  }
3931 
3932  do {
3933  r = read(fd, buf, len);
3934  } while (r < 0 && errno == EINTR);
3935 
3936  return r;
3937 }
3938 
3939 static void
3940 send_child_error(int fd, char *errmsg, size_t errmsg_buflen)
3941 {
3942  int err;
3943 
3944  err = errno;
3945  if (write_retry(fd, &err, sizeof(err)) < 0) err = errno;
3946  if (errmsg && 0 < errmsg_buflen) {
3947  errmsg[errmsg_buflen-1] = '\0';
3948  errmsg_buflen = strlen(errmsg);
3949  if (errmsg_buflen > 0 && write_retry(fd, errmsg, errmsg_buflen) < 0)
3950  err = errno;
3951  }
3952 }
3953 
3954 static int
3955 recv_child_error(int fd, int *errp, char *errmsg, size_t errmsg_buflen)
3956 {
3957  int err;
3958  ssize_t size;
3959  if ((size = read_retry(fd, &err, sizeof(err))) < 0) {
3960  err = errno;
3961  }
3962  *errp = err;
3963  if (size == sizeof(err) &&
3964  errmsg && 0 < errmsg_buflen) {
3965  ssize_t ret = read_retry(fd, errmsg, errmsg_buflen-1);
3966  if (0 <= ret) {
3967  errmsg[ret] = '\0';
3968  }
3969  }
3970  close(fd);
3971  return size != 0;
3972 }
3973 
3974 #ifdef HAVE_WORKING_VFORK
3975 #if !defined(HAVE_GETRESUID) && defined(HAVE_GETUIDX)
3976 /* AIX 7.1 */
3977 static int
3978 getresuid(rb_uid_t *ruid, rb_uid_t *euid, rb_uid_t *suid)
3979 {
3980  rb_uid_t ret;
3981 
3982  *ruid = getuid();
3983  *euid = geteuid();
3984  ret = getuidx(ID_SAVED);
3985  if (ret == (rb_uid_t)-1)
3986  return -1;
3987  *suid = ret;
3988  return 0;
3989 }
3990 #define HAVE_GETRESUID
3991 #endif
3992 
3993 #if !defined(HAVE_GETRESGID) && defined(HAVE_GETGIDX)
3994 /* AIX 7.1 */
3995 static int
3996 getresgid(rb_gid_t *rgid, rb_gid_t *egid, rb_gid_t *sgid)
3997 {
3998  rb_gid_t ret;
3999 
4000  *rgid = getgid();
4001  *egid = getegid();
4002  ret = getgidx(ID_SAVED);
4003  if (ret == (rb_gid_t)-1)
4004  return -1;
4005  *sgid = ret;
4006  return 0;
4007 }
4008 #define HAVE_GETRESGID
4009 #endif
4010 
4011 static int
4012 has_privilege(void)
4013 {
4014  /*
4015  * has_privilege() is used to choose vfork() or fork().
4016  *
4017  * If the process has privilege, the parent process or
4018  * the child process can change UID/GID.
4019  * If vfork() is used to create the child process and
4020  * the parent or child process change effective UID/GID,
4021  * different privileged processes shares memory.
4022  * It is a bad situation.
4023  * So, fork() should be used.
4024  */
4025 
4026  rb_uid_t ruid, euid;
4027  rb_gid_t rgid, egid;
4028 
4029 #if defined HAVE_ISSETUGID
4030  if (issetugid())
4031  return 1;
4032 #endif
4033 
4034 #ifdef HAVE_GETRESUID
4035  {
4036  int ret;
4037  rb_uid_t suid;
4038  ret = getresuid(&ruid, &euid, &suid);
4039  if (ret == -1)
4040  rb_sys_fail("getresuid(2)");
4041  if (euid != suid)
4042  return 1;
4043  }
4044 #else
4045  ruid = getuid();
4046  euid = geteuid();
4047 #endif
4048 
4049  if (euid == 0 || euid != ruid)
4050  return 1;
4051 
4052 #ifdef HAVE_GETRESGID
4053  {
4054  int ret;
4055  rb_gid_t sgid;
4056  ret = getresgid(&rgid, &egid, &sgid);
4057  if (ret == -1)
4058  rb_sys_fail("getresgid(2)");
4059  if (egid != sgid)
4060  return 1;
4061  }
4062 #else
4063  rgid = getgid();
4064  egid = getegid();
4065 #endif
4066 
4067  if (egid != rgid)
4068  return 1;
4069 
4070  return 0;
4071 }
4072 #endif
4073 
4074 struct child_handler_disabler_state
4075 {
4076  sigset_t sigmask;
4077 };
4078 
4079 static void
4080 disable_child_handler_before_fork(struct child_handler_disabler_state *old)
4081 {
4082 #ifdef HAVE_PTHREAD_SIGMASK
4083  int ret;
4084  sigset_t all;
4085 
4086  ret = sigfillset(&all);
4087  if (ret == -1)
4088  rb_sys_fail("sigfillset");
4089 
4090  ret = pthread_sigmask(SIG_SETMASK, &all, &old->sigmask); /* not async-signal-safe */
4091  if (ret != 0) {
4092  rb_syserr_fail(ret, "pthread_sigmask");
4093  }
4094 #else
4095 # pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous"
4096 #endif
4097 }
4098 
4099 static void
4100 disable_child_handler_fork_parent(struct child_handler_disabler_state *old)
4101 {
4102 #ifdef HAVE_PTHREAD_SIGMASK
4103  int ret;
4104 
4105  ret = pthread_sigmask(SIG_SETMASK, &old->sigmask, NULL); /* not async-signal-safe */
4106  if (ret != 0) {
4107  rb_syserr_fail(ret, "pthread_sigmask");
4108  }
4109 #else
4110 # pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous"
4111 #endif
4112 }
4113 
4114 /* This function should be async-signal-safe. Actually it is. */
4115 static int
4116 disable_child_handler_fork_child(struct child_handler_disabler_state *old, char *errmsg, size_t errmsg_buflen)
4117 {
4118  int sig;
4119  int ret;
4120 
4121  for (sig = 1; sig < NSIG; sig++) {
4122  sig_t handler = signal(sig, SIG_DFL);
4123 
4124  if (handler == SIG_ERR && errno == EINVAL) {
4125  continue; /* Ignore invalid signal number */
4126  }
4127  if (handler == SIG_ERR) {
4128  ERRMSG("signal to obtain old action");
4129  return -1;
4130  }
4131 #ifdef SIGPIPE
4132  if (sig == SIGPIPE) {
4133  continue;
4134  }
4135 #endif
4136  /* it will be reset to SIG_DFL at execve time, instead */
4137  if (handler == SIG_IGN) {
4138  signal(sig, SIG_IGN);
4139  }
4140  }
4141 
4142  /* non-Ruby child process, ensure cmake can see SIGCHLD */
4143  sigemptyset(&old->sigmask);
4144  ret = sigprocmask(SIG_SETMASK, &old->sigmask, NULL); /* async-signal-safe */
4145  if (ret != 0) {
4146  ERRMSG("sigprocmask");
4147  return -1;
4148  }
4149  return 0;
4150 }
4151 
4152 static rb_pid_t
4153 retry_fork_async_signal_safe(struct rb_process_status *status, int *ep,
4154  int (*chfunc)(void*, char *, size_t), void *charg,
4155  char *errmsg, size_t errmsg_buflen,
4156  struct waitpid_state *w)
4157 {
4158  rb_pid_t pid;
4159  volatile int try_gc = 1;
4160  struct child_handler_disabler_state old;
4161  int err;
4162  rb_nativethread_lock_t *const volatile waitpid_lock_init =
4163  (w && WAITPID_USE_SIGCHLD) ? &GET_VM()->waitpid_lock : 0;
4164 
4165  while (1) {
4166  rb_nativethread_lock_t *waitpid_lock = waitpid_lock_init;
4167  prefork();
4168  disable_child_handler_before_fork(&old);
4169  if (waitpid_lock) {
4170  rb_native_mutex_lock(waitpid_lock);
4171  }
4172 #ifdef HAVE_WORKING_VFORK
4173  if (!has_privilege())
4174  pid = vfork();
4175  else
4176  pid = rb_fork();
4177 #else
4178  pid = rb_fork();
4179 #endif
4180  if (pid == 0) {/* fork succeed, child process */
4181  int ret;
4182  close(ep[0]);
4183  ret = disable_child_handler_fork_child(&old, errmsg, errmsg_buflen); /* async-signal-safe */
4184  if (ret == 0) {
4185  ret = chfunc(charg, errmsg, errmsg_buflen);
4186  if (!ret) _exit(EXIT_SUCCESS);
4187  }
4188  send_child_error(ep[1], errmsg, errmsg_buflen);
4189 #if EXIT_SUCCESS == 127
4190  _exit(EXIT_FAILURE);
4191 #else
4192  _exit(127);
4193 #endif
4194  }
4195  err = errno;
4196  waitpid_lock = waitpid_lock_init;
4197  if (waitpid_lock) {
4198  if (pid > 0 && w != WAITPID_LOCK_ONLY) {
4199  w->pid = pid;
4200  list_add(&GET_VM()->waiting_pids, &w->wnode);
4201  }
4202  rb_native_mutex_unlock(waitpid_lock);
4203  }
4204  disable_child_handler_fork_parent(&old);
4205  if (0 < pid) /* fork succeed, parent process */
4206  return pid;
4207  /* fork failed */
4208  if (handle_fork_error(err, status, ep, &try_gc))
4209  return -1;
4210  }
4211 }
4212 
4213 static rb_pid_t
4214 fork_check_err(struct rb_process_status *status, int (*chfunc)(void*, char *, size_t), void *charg,
4215  VALUE fds, char *errmsg, size_t errmsg_buflen,
4216  struct rb_execarg *eargp)
4217 {
4218  rb_pid_t pid;
4219  int err;
4220  int ep[2];
4221  int error_occurred;
4222 
4223  struct waitpid_state *w = eargp && eargp->waitpid_state ? eargp->waitpid_state : 0;
4224 
4225  if (status) status->status = 0;
4226 
4227  if (pipe_nocrash(ep, fds)) return -1;
4228 
4229  pid = retry_fork_async_signal_safe(status, ep, chfunc, charg, errmsg, errmsg_buflen, w);
4230 
4231  if (status) status->pid = pid;
4232 
4233  if (pid < 0) {
4234  if (status) status->error = errno;
4235 
4236  return pid;
4237  }
4238 
4239  close(ep[1]);
4240 
4241  error_occurred = recv_child_error(ep[0], &err, errmsg, errmsg_buflen);
4242 
4243  if (error_occurred) {
4244  if (status) {
4245  int state = 0;
4246  status->error = err;
4247 
4248  VM_ASSERT((w == 0 || w == WAITPID_LOCK_ONLY) &&
4249  "only used by extensions");
4250  rb_protect(proc_syswait, (VALUE)pid, &state);
4251 
4252  status->status = state;
4253  }
4254  else if (!w || w == WAITPID_LOCK_ONLY) {
4255  rb_syswait(pid);
4256  }
4257 
4258  errno = err;
4259  return -1;
4260  }
4261 
4262  return pid;
4263 }
4264 
4265 /*
4266  * The "async_signal_safe" name is a lie, but it is used by pty.c and
4267  * maybe other exts. fork() is not async-signal-safe due to pthread_atfork
4268  * and future POSIX revisions will remove it from a list of signal-safe
4269  * functions. rb_waitpid is not async-signal-safe since MJIT, either.
4270  * For our purposes, we do not need async-signal-safety, here
4271  */
4272 rb_pid_t
4273 rb_fork_async_signal_safe(int *status,
4274  int (*chfunc)(void*, char *, size_t), void *charg,
4275  VALUE fds, char *errmsg, size_t errmsg_buflen)
4276 {
4277  struct rb_process_status process_status;
4278 
4279  rb_pid_t result = fork_check_err(&process_status, chfunc, charg, fds, errmsg, errmsg_buflen, 0);
4280 
4281  if (status) {
4282  *status = process_status.status;
4283  }
4284 
4285  return result;
4286 }
4287 
4288 static rb_pid_t
4289 rb_fork_ruby2(struct rb_process_status *status)
4290 {
4291  rb_pid_t pid;
4292  int try_gc = 1, err;
4293  struct child_handler_disabler_state old;
4294 
4295  if (status) status->status = 0;
4296 
4297  while (1) {
4298  prefork();
4299  if (mjit_enabled) mjit_pause(false); // Don't leave locked mutex to child. Note: child_handler must be enabled to pause MJIT.
4300  disable_child_handler_before_fork(&old);
4301  before_fork_ruby();
4302  pid = rb_fork();
4303  err = errno;
4304  if (status) {
4305  status->pid = pid;
4306  status->error = err;
4307  }
4308  after_fork_ruby();
4309  disable_child_handler_fork_parent(&old); /* yes, bad name */
4310 
4311  if (mjit_enabled && pid > 0) mjit_resume(); /* child (pid == 0) is cared by rb_thread_atfork */
4312 
4313  if (pid >= 0) { /* fork succeed */
4314  if (pid == 0) rb_thread_atfork();
4315  return pid;
4316  }
4317 
4318  /* fork failed */
4319  if (handle_fork_error(err, status, NULL, &try_gc)) {
4320  return -1;
4321  }
4322  }
4323 }
4324 
4325 rb_pid_t
4326 rb_fork_ruby(int *status)
4327 {
4328  struct rb_process_status process_status = {0};
4329 
4330  rb_pid_t pid = rb_fork_ruby2(&process_status);
4331 
4332  if (status) *status = process_status.status;
4333 
4334  return pid;
4335 }
4336 
4337 rb_pid_t
4338 rb_call_proc__fork(void)
4339 {
4340  VALUE pid = rb_funcall(rb_mProcess, rb_intern("_fork"), 0);
4341 
4342  return NUM2PIDT(pid);
4343 }
4344 #endif
4345 
4346 #if defined(HAVE_WORKING_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
4347 /*
4348  * call-seq:
4349  * Process._fork -> integer
4350  *
4351  * An internal API for fork. Do not call this method directly.
4352  * Currently, this is called via Kernel#fork, Process.fork, and
4353  * IO.popen with <tt>"-"</tt>.
4354  *
4355  * This method is not for casual code but for application monitoring
4356  * libraries. You can add custom code before and after fork events
4357  * by overriding this method.
4358  */
4359 VALUE
4360 rb_proc__fork(VALUE _obj)
4361 {
4362  rb_pid_t pid = rb_fork_ruby(NULL);
4363 
4364  if (pid == -1) {
4365  rb_sys_fail("fork(2)");
4366  }
4367 
4368  return PIDT2NUM(pid);
4369 }
4370 
4371 /*
4372  * call-seq:
4373  * Kernel.fork [{ block }] -> integer or nil
4374  * Process.fork [{ block }] -> integer or nil
4375  *
4376  * Creates a subprocess. If a block is specified, that block is run
4377  * in the subprocess, and the subprocess terminates with a status of
4378  * zero. Otherwise, the +fork+ call returns twice, once in the
4379  * parent, returning the process ID of the child, and once in the
4380  * child, returning _nil_. The child process can exit using
4381  * Kernel.exit! to avoid running any <code>at_exit</code>
4382  * functions. The parent process should use Process.wait to collect
4383  * the termination statuses of its children or use Process.detach to
4384  * register disinterest in their status; otherwise, the operating
4385  * system may accumulate zombie processes.
4386  *
4387  * The thread calling fork is the only thread in the created child process.
4388  * fork doesn't copy other threads.
4389  *
4390  * If fork is not usable, Process.respond_to?(:fork) returns false.
4391  *
4392  * Note that fork(2) is not available on some platforms like Windows and NetBSD 4.
4393  * Therefore you should use spawn() instead of fork().
4394  */
4395 
4396 static VALUE
4397 rb_f_fork(VALUE obj)
4398 {
4399  rb_pid_t pid;
4400 
4401  pid = rb_call_proc__fork();
4402 
4403  if (pid == 0) {
4404  if (rb_block_given_p()) {
4405  int status;
4406  rb_protect(rb_yield, Qundef, &status);
4407  ruby_stop(status);
4408  }
4409  return Qnil;
4410  }
4411 
4412  return PIDT2NUM(pid);
4413 }
4414 #else
4415 #define rb_proc__fork rb_f_notimplement
4416 #define rb_f_fork rb_f_notimplement
4417 #endif
4418 
4419 static int
4420 exit_status_code(VALUE status)
4421 {
4422  int istatus;
4423 
4424  switch (status) {
4425  case Qtrue:
4426  istatus = EXIT_SUCCESS;
4427  break;
4428  case Qfalse:
4429  istatus = EXIT_FAILURE;
4430  break;
4431  default:
4432  istatus = NUM2INT(status);
4433 #if EXIT_SUCCESS != 0
4434  if (istatus == 0)
4435  istatus = EXIT_SUCCESS;
4436 #endif
4437  break;
4438  }
4439  return istatus;
4440 }
4441 
4442 NORETURN(static VALUE rb_f_exit_bang(int argc, VALUE *argv, VALUE obj));
4443 /*
4444  * call-seq:
4445  * Process.exit!(status=false)
4446  *
4447  * Exits the process immediately. No exit handlers are
4448  * run. <em>status</em> is returned to the underlying system as the
4449  * exit status.
4450  *
4451  * Process.exit!(true)
4452  */
4453 
4454 static VALUE
4455 rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
4456 {
4457  int istatus;
4458 
4459  if (rb_check_arity(argc, 0, 1) == 1) {
4460  istatus = exit_status_code(argv[0]);
4461  }
4462  else {
4463  istatus = EXIT_FAILURE;
4464  }
4465  _exit(istatus);
4466 
4468 }
4469 
4470 void
4471 rb_exit(int status)
4472 {
4473  if (GET_EC()->tag) {
4474  VALUE args[2];
4475 
4476  args[0] = INT2NUM(status);
4477  args[1] = rb_str_new2("exit");
4479  }
4480  ruby_stop(status);
4481 }
4482 
4483 VALUE
4484 rb_f_exit(int argc, const VALUE *argv)
4485 {
4486  int istatus;
4487 
4488  if (rb_check_arity(argc, 0, 1) == 1) {
4489  istatus = exit_status_code(argv[0]);
4490  }
4491  else {
4492  istatus = EXIT_SUCCESS;
4493  }
4494  rb_exit(istatus);
4495 
4497 }
4498 
4499 NORETURN(static VALUE f_exit(int c, const VALUE *a, VALUE _));
4500 /*
4501  * call-seq:
4502  * exit(status=true)
4503  * Kernel::exit(status=true)
4504  * Process::exit(status=true)
4505  *
4506  * Initiates the termination of the Ruby script by raising the
4507  * SystemExit exception. This exception may be caught. The
4508  * optional parameter is used to return a status code to the invoking
4509  * environment.
4510  * +true+ and +FALSE+ of _status_ means success and failure
4511  * respectively. The interpretation of other integer values are
4512  * system dependent.
4513  *
4514  * begin
4515  * exit
4516  * puts "never get here"
4517  * rescue SystemExit
4518  * puts "rescued a SystemExit exception"
4519  * end
4520  * puts "after begin block"
4521  *
4522  * <em>produces:</em>
4523  *
4524  * rescued a SystemExit exception
4525  * after begin block
4526  *
4527  * Just prior to termination, Ruby executes any <code>at_exit</code>
4528  * functions (see Kernel::at_exit) and runs any object finalizers
4529  * (see ObjectSpace::define_finalizer).
4530  *
4531  * at_exit { puts "at_exit function" }
4532  * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
4533  * exit
4534  *
4535  * <em>produces:</em>
4536  *
4537  * at_exit function
4538  * in finalizer
4539  */
4540 
4541 static VALUE
4542 f_exit(int c, const VALUE *a, VALUE _)
4543 {
4544  rb_f_exit(c, a);
4546 }
4547 
4548 VALUE
4549 rb_f_abort(int argc, const VALUE *argv)
4550 {
4551  rb_check_arity(argc, 0, 1);
4552  if (argc == 0) {
4553  rb_execution_context_t *ec = GET_EC();
4554  VALUE errinfo = rb_ec_get_errinfo(ec);
4555  if (!NIL_P(errinfo)) {
4556  rb_ec_error_print(ec, errinfo);
4557  }
4558  rb_exit(EXIT_FAILURE);
4559  }
4560  else {
4561  VALUE args[2];
4562 
4563  args[1] = args[0] = argv[0];
4564  StringValue(args[0]);
4565  rb_io_puts(1, args, rb_ractor_stderr());
4566  args[0] = INT2NUM(EXIT_FAILURE);
4568  }
4569 
4571 }
4572 
4573 NORETURN(static VALUE f_abort(int c, const VALUE *a, VALUE _));
4574 
4575 /*
4576  * call-seq:
4577  * abort
4578  * Kernel::abort([msg])
4579  * Process.abort([msg])
4580  *
4581  * Terminate execution immediately, effectively by calling
4582  * <code>Kernel.exit(false)</code>. If _msg_ is given, it is written
4583  * to STDERR prior to terminating.
4584  */
4585 
4586 static VALUE
4587 f_abort(int c, const VALUE *a, VALUE _)
4588 {
4589  rb_f_abort(c, a);
4591 }
4592 
4593 void
4594 rb_syswait(rb_pid_t pid)
4595 {
4596  int status;
4597 
4598  rb_waitpid(pid, &status, 0);
4599 }
4600 
4601 #if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV && !defined __EMSCRIPTEN__
4602 char *
4603 rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
4604 {
4605  VALUE cmd = *prog;
4606  if (eargp && !eargp->use_shell) {
4607  VALUE str = eargp->invoke.cmd.argv_str;
4608  VALUE buf = eargp->invoke.cmd.argv_buf;
4609  char *p, **argv = ARGVSTR2ARGV(str);
4610  long i, argc = ARGVSTR2ARGC(str);
4611  const char *start = RSTRING_PTR(buf);
4612  cmd = rb_str_new(start, RSTRING_LEN(buf));
4613  p = RSTRING_PTR(cmd);
4614  for (i = 1; i < argc; ++i) {
4615  p[argv[i] - start - 1] = ' ';
4616  }
4617  *prog = cmd;
4618  return p;
4619  }
4620  return StringValueCStr(*prog);
4621 }
4622 #endif
4623 
4624 static rb_pid_t
4625 rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
4626 {
4627  rb_pid_t pid;
4628 #if !defined HAVE_WORKING_FORK || USE_SPAWNV
4629  VALUE prog;
4630  struct rb_execarg sarg;
4631 # if !defined HAVE_SPAWNV
4632  int status;
4633 # endif
4634 #endif
4635 
4636 #if defined HAVE_WORKING_FORK && !USE_SPAWNV
4637  pid = fork_check_err(eargp->status, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen, eargp);
4638 #else
4639  prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
4640 
4641  if (rb_execarg_run_options(eargp, &sarg, errmsg, errmsg_buflen) < 0) {
4642  return -1;
4643  }
4644 
4645  if (prog && !eargp->use_shell) {
4646  char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
4647  argv[0] = RSTRING_PTR(prog);
4648  }
4649 # if defined HAVE_SPAWNV
4650  if (eargp->use_shell) {
4651  pid = proc_spawn_sh(RSTRING_PTR(prog));
4652  }
4653  else {
4654  char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
4655  pid = proc_spawn_cmd(argv, prog, eargp);
4656  }
4657 
4658  if (pid == -1) {
4659  rb_last_status_set(0x7f << 8, pid);
4660  }
4661 # else
4662  status = system(rb_execarg_commandline(eargp, &prog));
4663  pid = 1; /* dummy */
4664  rb_last_status_set((status & 0xff) << 8, pid);
4665 # endif
4666 
4667  if (eargp->waitpid_state && eargp->waitpid_state != WAITPID_LOCK_ONLY) {
4668  eargp->waitpid_state->pid = pid;
4669  }
4670 
4671  rb_execarg_run_options(&sarg, NULL, errmsg, errmsg_buflen);
4672 #endif
4673 
4674  return pid;
4675 }
4676 
4677 struct spawn_args {
4678  VALUE execarg;
4679  struct {
4680  char *ptr;
4681  size_t buflen;
4682  } errmsg;
4683 };
4684 
4685 static VALUE
4686 do_spawn_process(VALUE arg)
4687 {
4688  struct spawn_args *argp = (struct spawn_args *)arg;
4689  rb_execarg_parent_start1(argp->execarg);
4690  return (VALUE)rb_spawn_process(DATA_PTR(argp->execarg),
4691  argp->errmsg.ptr, argp->errmsg.buflen);
4692 }
4693 
4694 static rb_pid_t
4695 rb_execarg_spawn(VALUE execarg_obj, char *errmsg, size_t errmsg_buflen)
4696 {
4697  struct spawn_args args;
4698  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
4699 
4700  /*
4701  * Prevent a race with MJIT where the compiler process where
4702  * can hold an FD of ours in between vfork + execve
4703  */
4704  if (!eargp->waitpid_state && mjit_enabled) {
4705  eargp->waitpid_state = WAITPID_LOCK_ONLY;
4706  }
4707 
4708  args.execarg = execarg_obj;
4709  args.errmsg.ptr = errmsg;
4710  args.errmsg.buflen = errmsg_buflen;
4711  return (rb_pid_t)rb_ensure(do_spawn_process, (VALUE)&args,
4712  execarg_parent_end, execarg_obj);
4713 }
4714 
4715 static rb_pid_t
4716 rb_spawn_internal(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
4717 {
4718  VALUE execarg_obj;
4719 
4720  execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
4721  return rb_execarg_spawn(execarg_obj, errmsg, errmsg_buflen);
4722 }
4723 
4724 rb_pid_t
4725 rb_spawn_err(int argc, const VALUE *argv, char *errmsg, size_t errmsg_buflen)
4726 {
4727  return rb_spawn_internal(argc, argv, errmsg, errmsg_buflen);
4728 }
4729 
4730 rb_pid_t
4731 rb_spawn(int argc, const VALUE *argv)
4732 {
4733  return rb_spawn_internal(argc, argv, NULL, 0);
4734 }
4735 
4736 /*
4737  * call-seq:
4738  * system([env,] command... [,options], exception: false) -> true, false or nil
4739  *
4740  * Executes _command..._ in a subshell.
4741  * _command..._ is one of following forms.
4742  *
4743  * [<code>commandline</code>]
4744  * command line string which is passed to the standard shell
4745  * [<code>cmdname, arg1, ...</code>]
4746  * command name and one or more arguments (no shell)
4747  * [<code>[cmdname, argv0], arg1, ...</code>]
4748  * command name, <code>argv[0]</code> and zero or more arguments (no shell)
4749  *
4750  * system returns +true+ if the command gives zero exit status,
4751  * +false+ for non zero exit status.
4752  * Returns +nil+ if command execution fails.
4753  * An error status is available in <code>$?</code>.
4754  *
4755  * If the <code>exception: true</code> argument is passed, the method
4756  * raises an exception instead of returning +false+ or +nil+.
4757  *
4758  * The arguments are processed in the same way as
4759  * for Kernel#spawn.
4760  *
4761  * The hash arguments, env and options, are same as #exec and #spawn.
4762  * See Kernel#spawn for details.
4763  *
4764  * system("echo *")
4765  * system("echo", "*")
4766  *
4767  * <em>produces:</em>
4768  *
4769  * config.h main.rb
4770  * *
4771  *
4772  * Error handling:
4773  *
4774  * system("cat nonexistent.txt")
4775  * # => false
4776  * system("catt nonexistent.txt")
4777  * # => nil
4778  *
4779  * system("cat nonexistent.txt", exception: true)
4780  * # RuntimeError (Command failed with exit 1: cat)
4781  * system("catt nonexistent.txt", exception: true)
4782  * # Errno::ENOENT (No such file or directory - catt)
4783  *
4784  * See Kernel#exec for the standard shell.
4785  */
4786 
4787 static VALUE
4788 rb_f_system(int argc, VALUE *argv, VALUE _)
4789 {
4790  VALUE execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE);
4791  struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
4792 
4793  struct rb_process_status status = {0};
4794  eargp->status = &status;
4795 
4796  rb_last_status_clear();
4797 
4798  // This function can set the thread's last status.
4799  // May be different from waitpid_state.pid on exec failure.
4800  rb_pid_t pid = rb_execarg_spawn(execarg_obj, 0, 0);
4801 
4802  if (pid > 0) {
4803  VALUE status = rb_process_status_wait(pid, 0);
4804  struct rb_process_status *data = RTYPEDDATA_DATA(status);
4805 
4806  // Set the last status:
4807  rb_obj_freeze(status);
4808  GET_THREAD()->last_status = status;
4809 
4810  if (data->status == EXIT_SUCCESS) {
4811  return Qtrue;
4812  }
4813 
4814  if (data->error != 0) {
4815  if (eargp->exception) {
4816  VALUE command = eargp->invoke.sh.shell_script;
4817  RB_GC_GUARD(execarg_obj);
4818  rb_syserr_fail_str(data->error, command);
4819  }
4820  else {
4821  return Qnil;
4822  }
4823  }
4824  else if (eargp->exception) {
4825  VALUE command = eargp->invoke.sh.shell_script;
4826  VALUE str = rb_str_new_cstr("Command failed with");
4827  rb_str_cat_cstr(pst_message_status(str, data->status), ": ");
4828  rb_str_append(str, command);
4829  RB_GC_GUARD(execarg_obj);
4831  }
4832  else {
4833  return Qfalse;
4834  }
4835 
4836  RB_GC_GUARD(status);
4837  }
4838 
4839  if (eargp->exception) {
4840  VALUE command = eargp->invoke.sh.shell_script;
4841  RB_GC_GUARD(execarg_obj);
4842  rb_syserr_fail_str(errno, command);
4843  }
4844  else {
4845  return Qnil;
4846  }
4847 }
4848 
4849 /*
4850  * call-seq:
4851  * spawn([env,] command... [,options]) -> pid
4852  * Process.spawn([env,] command... [,options]) -> pid
4853  *
4854  * spawn executes specified command and return its pid.
4855  *
4856  * pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
4857  * Process.wait pid
4858  *
4859  * pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
4860  * Process.wait pid
4861  *
4862  * This method is similar to Kernel#system but it doesn't wait for the command
4863  * to finish.
4864  *
4865  * The parent process should
4866  * use Process.wait to collect
4867  * the termination status of its child or
4868  * use Process.detach to register
4869  * disinterest in their status;
4870  * otherwise, the operating system may accumulate zombie processes.
4871  *
4872  * spawn has bunch of options to specify process attributes:
4873  *
4874  * env: hash
4875  * name => val : set the environment variable
4876  * name => nil : unset the environment variable
4877  *
4878  * the keys and the values except for +nil+ must be strings.
4879  * command...:
4880  * commandline : command line string which is passed to the standard shell
4881  * cmdname, arg1, ... : command name and one or more arguments (This form does not use the shell. See below for caveats.)
4882  * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
4883  * options: hash
4884  * clearing environment variables:
4885  * :unsetenv_others => true : clear environment variables except specified by env
4886  * :unsetenv_others => false : don't clear (default)
4887  * process group:
4888  * :pgroup => true or 0 : make a new process group
4889  * :pgroup => pgid : join the specified process group
4890  * :pgroup => nil : don't change the process group (default)
4891  * create new process group: Windows only
4892  * :new_pgroup => true : the new process is the root process of a new process group
4893  * :new_pgroup => false : don't create a new process group (default)
4894  * resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
4895  * :rlimit_resourcename => limit
4896  * :rlimit_resourcename => [cur_limit, max_limit]
4897  * umask:
4898  * :umask => int
4899  * redirection:
4900  * key:
4901  * FD : single file descriptor in child process
4902  * [FD, FD, ...] : multiple file descriptor in child process
4903  * value:
4904  * FD : redirect to the file descriptor in parent process
4905  * string : redirect to file with open(string, "r" or "w")
4906  * [string] : redirect to file with open(string, File::RDONLY)
4907  * [string, open_mode] : redirect to file with open(string, open_mode, 0644)
4908  * [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
4909  * [:child, FD] : redirect to the redirected file descriptor
4910  * :close : close the file descriptor in child process
4911  * FD is one of follows
4912  * :in : the file descriptor 0 which is the standard input
4913  * :out : the file descriptor 1 which is the standard output
4914  * :err : the file descriptor 2 which is the standard error
4915  * integer : the file descriptor of specified the integer
4916  * io : the file descriptor specified as io.fileno
4917  * file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
4918  * :close_others => false : inherit
4919  * current directory:
4920  * :chdir => str
4921  *
4922  * The <code>cmdname, arg1, ...</code> form does not use the shell.
4923  * However, on different OSes, different things are provided as
4924  * built-in commands. An example of this is +'echo'+, which is a
4925  * built-in on Windows, but is a normal program on Linux and Mac OS X.
4926  * This means that <code>Process.spawn 'echo', '%Path%'</code> will
4927  * display the contents of the <tt>%Path%</tt> environment variable
4928  * on Windows, but <code>Process.spawn 'echo', '$PATH'</code> prints
4929  * the literal <tt>$PATH</tt>.
4930  *
4931  * If a hash is given as +env+, the environment is
4932  * updated by +env+ before <code>exec(2)</code> in the child process.
4933  * If a pair in +env+ has nil as the value, the variable is deleted.
4934  *
4935  * # set FOO as BAR and unset BAZ.
4936  * pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
4937  *
4938  * If a hash is given as +options+,
4939  * it specifies
4940  * process group,
4941  * create new process group,
4942  * resource limit,
4943  * current directory,
4944  * umask and
4945  * redirects for the child process.
4946  * Also, it can be specified to clear environment variables.
4947  *
4948  * The <code>:unsetenv_others</code> key in +options+ specifies
4949  * to clear environment variables, other than specified by +env+.
4950  *
4951  * pid = spawn(command, :unsetenv_others=>true) # no environment variable
4952  * pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
4953  *
4954  * The <code>:pgroup</code> key in +options+ specifies a process group.
4955  * The corresponding value should be true, zero, a positive integer, or nil.
4956  * true and zero cause the process to be a process leader of a new process group.
4957  * A non-zero positive integer causes the process to join the provided process group.
4958  * The default value, nil, causes the process to remain in the same process group.
4959  *
4960  * pid = spawn(command, :pgroup=>true) # process leader
4961  * pid = spawn(command, :pgroup=>10) # belongs to the process group 10
4962  *
4963  * The <code>:new_pgroup</code> key in +options+ specifies to pass
4964  * +CREATE_NEW_PROCESS_GROUP+ flag to <code>CreateProcessW()</code> that is
4965  * Windows API. This option is only for Windows.
4966  * true means the new process is the root process of the new process group.
4967  * The new process has CTRL+C disabled. This flag is necessary for
4968  * <code>Process.kill(:SIGINT, pid)</code> on the subprocess.
4969  * :new_pgroup is false by default.
4970  *
4971  * pid = spawn(command, :new_pgroup=>true) # new process group
4972  * pid = spawn(command, :new_pgroup=>false) # same process group
4973  *
4974  * The <code>:rlimit_</code><em>foo</em> key specifies a resource limit.
4975  * <em>foo</em> should be one of resource types such as <code>core</code>.
4976  * The corresponding value should be an integer or an array which have one or
4977  * two integers: same as cur_limit and max_limit arguments for
4978  * Process.setrlimit.
4979  *
4980  * cur, max = Process.getrlimit(:CORE)
4981  * pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
4982  * pid = spawn(command, :rlimit_core=>max) # enable core dump
4983  * pid = spawn(command, :rlimit_core=>0) # never dump core.
4984  *
4985  * The <code>:umask</code> key in +options+ specifies the umask.
4986  *
4987  * pid = spawn(command, :umask=>077)
4988  *
4989  * The :in, :out, :err, an integer, an IO and an array key specifies a redirection.
4990  * The redirection maps a file descriptor in the child process.
4991  *
4992  * For example, stderr can be merged into stdout as follows:
4993  *
4994  * pid = spawn(command, :err=>:out)
4995  * pid = spawn(command, 2=>1)
4996  * pid = spawn(command, STDERR=>:out)
4997  * pid = spawn(command, STDERR=>STDOUT)
4998  *
4999  * The hash keys specifies a file descriptor in the child process
5000  * started by #spawn.
5001  * :err, 2 and STDERR specifies the standard error stream (stderr).
5002  *
5003  * The hash values specifies a file descriptor in the parent process
5004  * which invokes #spawn.
5005  * :out, 1 and STDOUT specifies the standard output stream (stdout).
5006  *
5007  * In the above example,
5008  * the standard output in the child process is not specified.
5009  * So it is inherited from the parent process.
5010  *
5011  * The standard input stream (stdin) can be specified by :in, 0 and STDIN.
5012  *
5013  * A filename can be specified as a hash value.
5014  *
5015  * pid = spawn(command, :in=>"/dev/null") # read mode
5016  * pid = spawn(command, :out=>"/dev/null") # write mode
5017  * pid = spawn(command, :err=>"log") # write mode
5018  * pid = spawn(command, [:out, :err]=>"/dev/null") # write mode
5019  * pid = spawn(command, 3=>"/dev/null") # read mode
5020  *
5021  * For stdout and stderr (and combination of them),
5022  * it is opened in write mode.
5023  * Otherwise read mode is used.
5024  *
5025  * For specifying flags and permission of file creation explicitly,
5026  * an array is used instead.
5027  *
5028  * pid = spawn(command, :in=>["file"]) # read mode is assumed
5029  * pid = spawn(command, :in=>["file", "r"])
5030  * pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
5031  * pid = spawn(command, :out=>["log", "w", 0600])
5032  * pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
5033  *
5034  * The array specifies a filename, flags and permission.
5035  * The flags can be a string or an integer.
5036  * If the flags is omitted or nil, File::RDONLY is assumed.
5037  * The permission should be an integer.
5038  * If the permission is omitted or nil, 0644 is assumed.
5039  *
5040  * If an array of IOs and integers are specified as a hash key,
5041  * all the elements are redirected.
5042  *
5043  * # stdout and stderr is redirected to log file.
5044  * # The file "log" is opened just once.
5045  * pid = spawn(command, [:out, :err]=>["log", "w"])
5046  *
5047  * Another way to merge multiple file descriptors is [:child, fd].
5048  * \[:child, fd] means the file descriptor in the child process.
5049  * This is different from fd.
5050  * For example, :err=>:out means redirecting child stderr to parent stdout.
5051  * But :err=>[:child, :out] means redirecting child stderr to child stdout.
5052  * They differ if stdout is redirected in the child process as follows.
5053  *
5054  * # stdout and stderr is redirected to log file.
5055  * # The file "log" is opened just once.
5056  * pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
5057  *
5058  * \[:child, :out] can be used to merge stderr into stdout in IO.popen.
5059  * In this case, IO.popen redirects stdout to a pipe in the child process
5060  * and [:child, :out] refers the redirected stdout.
5061  *
5062  * io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
5063  * p io.read #=> "out\nerr\n"
5064  *
5065  * The <code>:chdir</code> key in +options+ specifies the current directory.
5066  *
5067  * pid = spawn(command, :chdir=>"/var/tmp")
5068  *
5069  * spawn closes all non-standard unspecified descriptors by default.
5070  * The "standard" descriptors are 0, 1 and 2.
5071  * This behavior is specified by :close_others option.
5072  * :close_others doesn't affect the standard descriptors which are
5073  * closed only if :close is specified explicitly.
5074  *
5075  * pid = spawn(command, :close_others=>true) # close 3,4,5,... (default)
5076  * pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
5077  *
5078  * :close_others is false by default for spawn and IO.popen.
5079  *
5080  * Note that fds which close-on-exec flag is already set are closed
5081  * regardless of :close_others option.
5082  *
5083  * So IO.pipe and spawn can be used as IO.popen.
5084  *
5085  * # similar to r = IO.popen(command)
5086  * r, w = IO.pipe
5087  * pid = spawn(command, :out=>w) # r, w is closed in the child process.
5088  * w.close
5089  *
5090  * :close is specified as a hash value to close a fd individually.
5091  *
5092  * f = open(foo)
5093  * system(command, f=>:close) # don't inherit f.
5094  *
5095  * If a file descriptor need to be inherited,
5096  * io=>io can be used.
5097  *
5098  * # valgrind has --log-fd option for log destination.
5099  * # log_w=>log_w indicates log_w.fileno inherits to child process.
5100  * log_r, log_w = IO.pipe
5101  * pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
5102  * log_w.close
5103  * p log_r.read
5104  *
5105  * It is also possible to exchange file descriptors.
5106  *
5107  * pid = spawn(command, :out=>:err, :err=>:out)
5108  *
5109  * The hash keys specify file descriptors in the child process.
5110  * The hash values specifies file descriptors in the parent process.
5111  * So the above specifies exchanging stdout and stderr.
5112  * Internally, +spawn+ uses an extra file descriptor to resolve such cyclic
5113  * file descriptor mapping.
5114  *
5115  * See Kernel.exec for the standard shell.
5116  */
5117 
5118 static VALUE
5119 rb_f_spawn(int argc, VALUE *argv, VALUE _)
5120 {
5121  rb_pid_t pid;
5122  char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
5123  VALUE execarg_obj, fail_str;
5124  struct rb_execarg *eargp;
5125 
5126  execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
5127  eargp = rb_execarg_get(execarg_obj);
5128  fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
5129 
5130  pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));
5131 
5132  if (pid == -1) {
5133  int err = errno;
5134  rb_exec_fail(eargp, err, errmsg);
5135  RB_GC_GUARD(execarg_obj);
5136  rb_syserr_fail_str(err, fail_str);
5137  }
5138 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
5139  return PIDT2NUM(pid);
5140 #else
5141  return Qnil;
5142 #endif
5143 }
5144 
5145 /*
5146  * call-seq:
5147  * sleep([duration]) -> integer
5148  *
5149  * Suspends the current thread for _duration_ seconds (which may be any number,
5150  * including a +Float+ with fractional seconds). Returns the actual number of
5151  * seconds slept (rounded), which may be less than that asked for if another
5152  * thread calls Thread#run. Called without an argument, sleep()
5153  * will sleep forever.
5154  *
5155  * Time.new #=> 2008-03-08 19:56:19 +0900
5156  * sleep 1.2 #=> 1
5157  * Time.new #=> 2008-03-08 19:56:20 +0900
5158  * sleep 1.9 #=> 2
5159  * Time.new #=> 2008-03-08 19:56:22 +0900
5160  */
5161 
5162 static VALUE
5163 rb_f_sleep(int argc, VALUE *argv, VALUE _)
5164 {
5165  time_t beg = time(0);
5166  VALUE scheduler = rb_fiber_scheduler_current();
5167 
5168  if (scheduler != Qnil) {
5169  rb_fiber_scheduler_kernel_sleepv(scheduler, argc, argv);
5170  }
5171  else {
5172  if (argc == 0) {
5174  }
5175  else {
5176  rb_check_arity(argc, 0, 1);
5178  }
5179  }
5180 
5181  time_t end = time(0) - beg;
5182 
5183  return TIMET2NUM(end);
5184 }
5185 
5186 
5187 #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
5188 /*
5189  * call-seq:
5190  * Process.getpgrp -> integer
5191  *
5192  * Returns the process group ID for this process. Not available on
5193  * all platforms.
5194  *
5195  * Process.getpgid(0) #=> 25527
5196  * Process.getpgrp #=> 25527
5197  */
5198 
5199 static VALUE
5200 proc_getpgrp(VALUE _)
5201 {
5202  rb_pid_t pgrp;
5203 
5204 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
5205  pgrp = getpgrp();
5206  if (pgrp < 0) rb_sys_fail(0);
5207  return PIDT2NUM(pgrp);
5208 #else /* defined(HAVE_GETPGID) */
5209  pgrp = getpgid(0);
5210  if (pgrp < 0) rb_sys_fail(0);
5211  return PIDT2NUM(pgrp);
5212 #endif
5213 }
5214 #else
5215 #define proc_getpgrp rb_f_notimplement
5216 #endif
5217 
5218 
5219 #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
5220 /*
5221  * call-seq:
5222  * Process.setpgrp -> 0
5223  *
5224  * Equivalent to <code>setpgid(0,0)</code>. Not available on all
5225  * platforms.
5226  */
5227 
5228 static VALUE
5229 proc_setpgrp(VALUE _)
5230 {
5231  /* check for posix setpgid() first; this matches the posix */
5232  /* getpgrp() above. It appears that configure will set SETPGRP_VOID */
5233  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
5234  /* this confusion. */
5235 #ifdef HAVE_SETPGID
5236  if (setpgid(0,0) < 0) rb_sys_fail(0);
5237 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
5238  if (setpgrp() < 0) rb_sys_fail(0);
5239 #endif
5240  return INT2FIX(0);
5241 }
5242 #else
5243 #define proc_setpgrp rb_f_notimplement
5244 #endif
5245 
5246 
5247 #if defined(HAVE_GETPGID)
5248 /*
5249  * call-seq:
5250  * Process.getpgid(pid) -> integer
5251  *
5252  * Returns the process group ID for the given process id. Not
5253  * available on all platforms.
5254  *
5255  * Process.getpgid(Process.ppid()) #=> 25527
5256  */
5257 
5258 static VALUE
5259 proc_getpgid(VALUE obj, VALUE pid)
5260 {
5261  rb_pid_t i;
5262 
5263  i = getpgid(NUM2PIDT(pid));
5264  if (i < 0) rb_sys_fail(0);
5265  return PIDT2NUM(i);
5266 }
5267 #else
5268 #define proc_getpgid rb_f_notimplement
5269 #endif
5270 
5271 
5272 #ifdef HAVE_SETPGID
5273 /*
5274  * call-seq:
5275  * Process.setpgid(pid, integer) -> 0
5276  *
5277  * Sets the process group ID of _pid_ (0 indicates this
5278  * process) to <em>integer</em>. Not available on all platforms.
5279  */
5280 
5281 static VALUE
5282 proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
5283 {
5284  rb_pid_t ipid, ipgrp;
5285 
5286  ipid = NUM2PIDT(pid);
5287  ipgrp = NUM2PIDT(pgrp);
5288 
5289  if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
5290  return INT2FIX(0);
5291 }
5292 #else
5293 #define proc_setpgid rb_f_notimplement
5294 #endif
5295 
5296 
5297 #ifdef HAVE_GETSID
5298 /*
5299  * call-seq:
5300  * Process.getsid() -> integer
5301  * Process.getsid(pid) -> integer
5302  *
5303  * Returns the session ID for the given process id. If not given,
5304  * return current process sid. Not available on all platforms.
5305  *
5306  * Process.getsid() #=> 27422
5307  * Process.getsid(0) #=> 27422
5308  * Process.getsid(Process.pid()) #=> 27422
5309  */
5310 static VALUE
5311 proc_getsid(int argc, VALUE *argv, VALUE _)
5312 {
5313  rb_pid_t sid;
5314  rb_pid_t pid = 0;
5315 
5316  if (rb_check_arity(argc, 0, 1) == 1 && !NIL_P(argv[0]))
5317  pid = NUM2PIDT(argv[0]);
5318 
5319  sid = getsid(pid);
5320  if (sid < 0) rb_sys_fail(0);
5321  return PIDT2NUM(sid);
5322 }
5323 #else
5324 #define proc_getsid rb_f_notimplement
5325 #endif
5326 
5327 
5328 #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
5329 #if !defined(HAVE_SETSID)
5330 static rb_pid_t ruby_setsid(void);
5331 #define setsid() ruby_setsid()
5332 #endif
5333 /*
5334  * call-seq:
5335  * Process.setsid -> integer
5336  *
5337  * Establishes this process as a new session and process group
5338  * leader, with no controlling tty. Returns the session id. Not
5339  * available on all platforms.
5340  *
5341  * Process.setsid #=> 27422
5342  */
5343 
5344 static VALUE
5345 proc_setsid(VALUE _)
5346 {
5347  rb_pid_t pid;
5348 
5349  pid = setsid();
5350  if (pid < 0) rb_sys_fail(0);
5351  return PIDT2NUM(pid);
5352 }
5353 
5354 #if !defined(HAVE_SETSID)
5355 #define HAVE_SETSID 1
5356 static rb_pid_t
5357 ruby_setsid(void)
5358 {
5359  rb_pid_t pid;
5360  int ret;
5361 
5362  pid = getpid();
5363 #if defined(SETPGRP_VOID)
5364  ret = setpgrp();
5365  /* If `pid_t setpgrp(void)' is equivalent to setsid(),
5366  `ret' will be the same value as `pid', and following open() will fail.
5367  In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
5368 #else
5369  ret = setpgrp(0, pid);
5370 #endif
5371  if (ret == -1) return -1;
5372 
5373  if ((fd = rb_cloexec_open("/dev/tty", O_RDWR, 0)) >= 0) {
5374  rb_update_max_fd(fd);
5375  ioctl(fd, TIOCNOTTY, NULL);
5376  close(fd);
5377  }
5378  return pid;
5379 }
5380 #endif
5381 #else
5382 #define proc_setsid rb_f_notimplement
5383 #endif
5384 
5385 
5386 #ifdef HAVE_GETPRIORITY
5387 /*
5388  * call-seq:
5389  * Process.getpriority(kind, integer) -> integer
5390  *
5391  * Gets the scheduling priority for specified process, process group,
5392  * or user. <em>kind</em> indicates the kind of entity to find: one
5393  * of Process::PRIO_PGRP,
5394  * Process::PRIO_USER, or
5395  * Process::PRIO_PROCESS. _integer_ is an id
5396  * indicating the particular process, process group, or user (an id
5397  * of 0 means _current_). Lower priorities are more favorable
5398  * for scheduling. Not available on all platforms.
5399  *
5400  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
5401  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
5402  */
5403 
5404 static VALUE
5405 proc_getpriority(VALUE obj, VALUE which, VALUE who)
5406 {
5407  int prio, iwhich, iwho;
5408 
5409  iwhich = NUM2INT(which);
5410  iwho = NUM2INT(who);
5411 
5412  errno = 0;
5413  prio = getpriority(iwhich, iwho);
5414  if (errno) rb_sys_fail(0);
5415  return INT2FIX(prio);
5416 }
5417 #else
5418 #define proc_getpriority rb_f_notimplement
5419 #endif
5420 
5421 
5422 #ifdef HAVE_GETPRIORITY
5423 /*
5424  * call-seq:
5425  * Process.setpriority(kind, integer, priority) -> 0
5426  *
5427  * See Process.getpriority.
5428  *
5429  * Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0
5430  * Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0
5431  * Process.getpriority(Process::PRIO_USER, 0) #=> 19
5432  * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
5433  */
5434 
5435 static VALUE
5436 proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
5437 {
5438  int iwhich, iwho, iprio;
5439 
5440  iwhich = NUM2INT(which);
5441  iwho = NUM2INT(who);
5442  iprio = NUM2INT(prio);
5443 
5444  if (setpriority(iwhich, iwho, iprio) < 0)
5445  rb_sys_fail(0);
5446  return INT2FIX(0);
5447 }
5448 #else
5449 #define proc_setpriority rb_f_notimplement
5450 #endif
5451 
5452 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
5453 static int
5454 rlimit_resource_name2int(const char *name, long len, int casetype)
5455 {
5456  int resource;
5457  const char *p;
5458 #define RESCHECK(r) \
5459  do { \
5460  if (len == rb_strlen_lit(#r) && STRCASECMP(name, #r) == 0) { \
5461  resource = RLIMIT_##r; \
5462  goto found; \
5463  } \
5464  } while (0)
5465 
5466  switch (TOUPPER(*name)) {
5467  case 'A':
5468 #ifdef RLIMIT_AS
5469  RESCHECK(AS);
5470 #endif
5471  break;
5472 
5473  case 'C':
5474 #ifdef RLIMIT_CORE
5475  RESCHECK(CORE);
5476 #endif
5477 #ifdef RLIMIT_CPU
5478  RESCHECK(CPU);
5479 #endif
5480  break;
5481 
5482  case 'D':
5483 #ifdef RLIMIT_DATA
5484  RESCHECK(DATA);
5485 #endif
5486  break;
5487 
5488  case 'F':
5489 #ifdef RLIMIT_FSIZE
5490  RESCHECK(FSIZE);
5491 #endif
5492  break;
5493 
5494  case 'M':
5495 #ifdef RLIMIT_MEMLOCK
5496  RESCHECK(MEMLOCK);
5497 #endif
5498 #ifdef RLIMIT_MSGQUEUE
5499  RESCHECK(MSGQUEUE);
5500 #endif
5501  break;
5502 
5503  case 'N':
5504 #ifdef RLIMIT_NOFILE
5505  RESCHECK(NOFILE);
5506 #endif
5507 #ifdef RLIMIT_NPROC
5508  RESCHECK(NPROC);
5509 #endif
5510 #ifdef RLIMIT_NICE
5511  RESCHECK(NICE);
5512 #endif
5513  break;
5514 
5515  case 'R':
5516 #ifdef RLIMIT_RSS
5517  RESCHECK(RSS);
5518 #endif
5519 #ifdef RLIMIT_RTPRIO
5520  RESCHECK(RTPRIO);
5521 #endif
5522 #ifdef RLIMIT_RTTIME
5523  RESCHECK(RTTIME);
5524 #endif
5525  break;
5526 
5527  case 'S':
5528 #ifdef RLIMIT_STACK
5529  RESCHECK(STACK);
5530 #endif
5531 #ifdef RLIMIT_SBSIZE
5532  RESCHECK(SBSIZE);
5533 #endif
5534 #ifdef RLIMIT_SIGPENDING
5535  RESCHECK(SIGPENDING);
5536 #endif
5537  break;
5538  }
5539  return -1;
5540 
5541  found:
5542  switch (casetype) {
5543  case 0:
5544  for (p = name; *p; p++)
5545  if (!ISUPPER(*p))
5546  return -1;
5547  break;
5548 
5549  case 1:
5550  for (p = name; *p; p++)
5551  if (!ISLOWER(*p))
5552  return -1;
5553  break;
5554 
5555  default:
5556  rb_bug("unexpected casetype");
5557  }
5558  return resource;
5559 #undef RESCHECK
5560 }
5561 
5562 static int
5563 rlimit_type_by_hname(const char *name, long len)
5564 {
5565  return rlimit_resource_name2int(name, len, 0);
5566 }
5567 
5568 static int
5569 rlimit_type_by_lname(const char *name, long len)
5570 {
5571  return rlimit_resource_name2int(name, len, 1);
5572 }
5573 
5574 static int
5575 rlimit_type_by_sym(VALUE key)
5576 {
5577  VALUE name = rb_sym2str(key);
5578  const char *rname = RSTRING_PTR(name);
5579  long len = RSTRING_LEN(name);
5580  int rtype = -1;
5581  static const char prefix[] = "rlimit_";
5582  enum {prefix_len = sizeof(prefix)-1};
5583 
5584  if (len > prefix_len && strncmp(prefix, rname, prefix_len) == 0) {
5585  rtype = rlimit_type_by_lname(rname + prefix_len, len - prefix_len);
5586  }
5587 
5588  RB_GC_GUARD(key);
5589  return rtype;
5590 }
5591 
5592 static int
5593 rlimit_resource_type(VALUE rtype)
5594 {
5595  const char *name;
5596  long len;
5597  VALUE v;
5598  int r;
5599 
5600  switch (TYPE(rtype)) {
5601  case T_SYMBOL:
5602  v = rb_sym2str(rtype);
5603  name = RSTRING_PTR(v);
5604  len = RSTRING_LEN(v);
5605  break;
5606 
5607  default:
5608  v = rb_check_string_type(rtype);
5609  if (!NIL_P(v)) {
5610  rtype = v;
5611  case T_STRING:
5612  name = StringValueCStr(rtype);
5613  len = RSTRING_LEN(rtype);
5614  break;
5615  }
5616  /* fall through */
5617 
5618  case T_FIXNUM:
5619  case T_BIGNUM:
5620  return NUM2INT(rtype);
5621  }
5622 
5623  r = rlimit_type_by_hname(name, len);
5624  if (r != -1)
5625  return r;
5626 
5627  rb_raise(rb_eArgError, "invalid resource name: % "PRIsVALUE, rtype);
5628 
5629  UNREACHABLE_RETURN(-1);
5630 }
5631 
5632 static rlim_t
5633 rlimit_resource_value(VALUE rval)
5634 {
5635  const char *name;
5636  VALUE v;
5637 
5638  switch (TYPE(rval)) {
5639  case T_SYMBOL:
5640  v = rb_sym2str(rval);
5641  name = RSTRING_PTR(v);
5642  break;
5643 
5644  default:
5645  v = rb_check_string_type(rval);
5646  if (!NIL_P(v)) {
5647  rval = v;
5648  case T_STRING:
5649  name = StringValueCStr(rval);
5650  break;
5651  }
5652  /* fall through */
5653 
5654  case T_FIXNUM:
5655  case T_BIGNUM:
5656  return NUM2RLIM(rval);
5657  }
5658 
5659 #ifdef RLIM_INFINITY
5660  if (strcmp(name, "INFINITY") == 0) return RLIM_INFINITY;
5661 #endif
5662 #ifdef RLIM_SAVED_MAX
5663  if (strcmp(name, "SAVED_MAX") == 0) return RLIM_SAVED_MAX;
5664 #endif
5665 #ifdef RLIM_SAVED_CUR
5666  if (strcmp(name, "SAVED_CUR") == 0) return RLIM_SAVED_CUR;
5667 #endif
5668  rb_raise(rb_eArgError, "invalid resource value: %"PRIsVALUE, rval);
5669 
5670  UNREACHABLE_RETURN((rlim_t)-1);
5671 }
5672 #endif
5673 
5674 #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
5675 /*
5676  * call-seq:
5677  * Process.getrlimit(resource) -> [cur_limit, max_limit]
5678  *
5679  * Gets the resource limit of the process.
5680  * _cur_limit_ means current (soft) limit and
5681  * _max_limit_ means maximum (hard) limit.
5682  *
5683  * _resource_ indicates the kind of resource to limit.
5684  * It is specified as a symbol such as <code>:CORE</code>,
5685  * a string such as <code>"CORE"</code> or
5686  * a constant such as Process::RLIMIT_CORE.
5687  * See Process.setrlimit for details.
5688  *
5689  * _cur_limit_ and _max_limit_ may be Process::RLIM_INFINITY,
5690  * Process::RLIM_SAVED_MAX or
5691  * Process::RLIM_SAVED_CUR.
5692  * See Process.setrlimit and the system getrlimit(2) manual for details.
5693  */
5694 
5695 static VALUE
5696 proc_getrlimit(VALUE obj, VALUE resource)
5697 {
5698  struct rlimit rlim;
5699 
5700  if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
5701  rb_sys_fail("getrlimit");
5702  }
5703  return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
5704 }
5705 #else
5706 #define proc_getrlimit rb_f_notimplement
5707 #endif
5708 
5709 #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
5710 /*
5711  * call-seq:
5712  * Process.setrlimit(resource, cur_limit, max_limit) -> nil
5713  * Process.setrlimit(resource, cur_limit) -> nil
5714  *
5715  * Sets the resource limit of the process.
5716  * _cur_limit_ means current (soft) limit and
5717  * _max_limit_ means maximum (hard) limit.
5718  *
5719  * If _max_limit_ is not given, _cur_limit_ is used.
5720  *
5721  * _resource_ indicates the kind of resource to limit.
5722  * It should be a symbol such as <code>:CORE</code>,
5723  * a string such as <code>"CORE"</code> or
5724  * a constant such as Process::RLIMIT_CORE.
5725  * The available resources are OS dependent.
5726  * Ruby may support following resources.
5727  *
5728  * [AS] total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)
5729  * [CORE] core size (bytes) (SUSv3)
5730  * [CPU] CPU time (seconds) (SUSv3)
5731  * [DATA] data segment (bytes) (SUSv3)
5732  * [FSIZE] file size (bytes) (SUSv3)
5733  * [MEMLOCK] total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)
5734  * [MSGQUEUE] allocation for POSIX message queues (bytes) (GNU/Linux)
5735  * [NICE] ceiling on process's nice(2) value (number) (GNU/Linux)
5736  * [NOFILE] file descriptors (number) (SUSv3)
5737  * [NPROC] number of processes for the user (number) (4.4BSD, GNU/Linux)
5738  * [RSS] resident memory size (bytes) (4.2BSD, GNU/Linux)
5739  * [RTPRIO] ceiling on the process's real-time priority (number) (GNU/Linux)
5740  * [RTTIME] CPU time for real-time process (us) (GNU/Linux)
5741  * [SBSIZE] all socket buffers (bytes) (NetBSD, FreeBSD)
5742  * [SIGPENDING] number of queued signals allowed (signals) (GNU/Linux)
5743  * [STACK] stack size (bytes) (SUSv3)
5744  *
5745  * _cur_limit_ and _max_limit_ may be
5746  * <code>:INFINITY</code>, <code>"INFINITY"</code> or
5747  * Process::RLIM_INFINITY,
5748  * which means that the resource is not limited.
5749  * They may be Process::RLIM_SAVED_MAX,
5750  * Process::RLIM_SAVED_CUR and
5751  * corresponding symbols and strings too.
5752  * See system setrlimit(2) manual for details.
5753  *
5754  * The following example raises the soft limit of core size to
5755  * the hard limit to try to make core dump possible.
5756  *
5757  * Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
5758  *
5759  */
5760 
5761 static VALUE
5762 proc_setrlimit(int argc, VALUE *argv, VALUE obj)
5763 {
5764  VALUE resource, rlim_cur, rlim_max;
5765  struct rlimit rlim;
5766 
5767  rb_check_arity(argc, 2, 3);
5768  resource = argv[0];
5769  rlim_cur = argv[1];
5770  if (argc < 3 || NIL_P(rlim_max = argv[2]))
5771  rlim_max = rlim_cur;
5772 
5773  rlim.rlim_cur = rlimit_resource_value(rlim_cur);
5774  rlim.rlim_max = rlimit_resource_value(rlim_max);
5775 
5776  if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
5777  rb_sys_fail("setrlimit");
5778  }
5779  return Qnil;
5780 }
5781 #else
5782 #define proc_setrlimit rb_f_notimplement
5783 #endif
5784 
5785 static int under_uid_switch = 0;
5786 static void
5787 check_uid_switch(void)
5788 {
5789  if (under_uid_switch) {
5790  rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
5791  }
5792 }
5793 
5794 static int under_gid_switch = 0;
5795 static void
5796 check_gid_switch(void)
5797 {
5798  if (under_gid_switch) {
5799  rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
5800  }
5801 }
5802 
5803 
5804 #if defined(HAVE_PWD_H)
5810 VALUE
5811 rb_getlogin(void)
5812 {
5813 #if ( !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN) )
5814  return Qnil;
5815 #else
5816  char MAYBE_UNUSED(*login) = NULL;
5817 
5818 # ifdef USE_GETLOGIN_R
5819 
5820 #if defined(__FreeBSD__)
5821  typedef int getlogin_r_size_t;
5822 #else
5823  typedef size_t getlogin_r_size_t;
5824 #endif
5825 
5826  long loginsize = GETLOGIN_R_SIZE_INIT; /* maybe -1 */
5827 
5828  if (loginsize < 0)
5829  loginsize = GETLOGIN_R_SIZE_DEFAULT;
5830 
5831  VALUE maybe_result = rb_str_buf_new(loginsize);
5832 
5833  login = RSTRING_PTR(maybe_result);
5834  loginsize = rb_str_capacity(maybe_result);
5835  rb_str_set_len(maybe_result, loginsize);
5836 
5837  int gle;
5838  errno = 0;
5839  while ((gle = getlogin_r(login, (getlogin_r_size_t)loginsize)) != 0) {
5840 
5841  if (gle == ENOTTY || gle == ENXIO || gle == ENOENT) {
5842  rb_str_resize(maybe_result, 0);
5843  return Qnil;
5844  }
5845 
5846  if (gle != ERANGE || loginsize >= GETLOGIN_R_SIZE_LIMIT) {
5847  rb_str_resize(maybe_result, 0);
5848  rb_syserr_fail(gle, "getlogin_r");
5849  }
5850 
5851  rb_str_modify_expand(maybe_result, loginsize);
5852  login = RSTRING_PTR(maybe_result);
5853  loginsize = rb_str_capacity(maybe_result);
5854  }
5855 
5856  if (login == NULL) {
5857  rb_str_resize(maybe_result, 0);
5858  return Qnil;
5859  }
5860 
5861  return maybe_result;
5862 
5863 # elif USE_GETLOGIN
5864 
5865  errno = 0;
5866  login = getlogin();
5867  if (errno) {
5868  if (errno == ENOTTY || errno == ENXIO || errno == ENOENT) {
5869  return Qnil;
5870  }
5871  rb_syserr_fail(errno, "getlogin");
5872  }
5873 
5874  return login ? rb_str_new_cstr(login) : Qnil;
5875 # endif
5876 
5877 #endif
5878 }
5879 
5880 VALUE
5881 rb_getpwdirnam_for_login(VALUE login_name)
5882 {
5883 #if ( !defined(USE_GETPWNAM_R) && !defined(USE_GETPWNAM) )
5884  return Qnil;
5885 #else
5886 
5887  if (NIL_P(login_name)) {
5888  /* nothing to do; no name with which to query the password database */
5889  return Qnil;
5890  }
5891 
5892  char *login = RSTRING_PTR(login_name);
5893 
5894  struct passwd *pwptr;
5895 
5896 # ifdef USE_GETPWNAM_R
5897 
5898  struct passwd pwdnm;
5899  char *bufnm;
5900  long bufsizenm = GETPW_R_SIZE_INIT; /* maybe -1 */
5901 
5902  if (bufsizenm < 0)
5903  bufsizenm = GETPW_R_SIZE_DEFAULT;
5904 
5905  VALUE getpwnm_tmp = rb_str_tmp_new(bufsizenm);
5906 
5907  bufnm = RSTRING_PTR(getpwnm_tmp);
5908  bufsizenm = rb_str_capacity(getpwnm_tmp);
5909  rb_str_set_len(getpwnm_tmp, bufsizenm);
5910 
5911  int enm;
5912  errno = 0;
5913  while ((enm = getpwnam_r(login, &pwdnm, bufnm, bufsizenm, &pwptr)) != 0) {
5914 
5915  if (enm == ENOENT || enm== ESRCH || enm == EBADF || enm == EPERM) {
5916  /* not found; non-errors */
5917  rb_str_resize(getpwnm_tmp, 0);
5918  return Qnil;
5919  }
5920 
5921  if (enm != ERANGE || bufsizenm >= GETPW_R_SIZE_LIMIT) {
5922  rb_str_resize(getpwnm_tmp, 0);
5923  rb_syserr_fail(enm, "getpwnam_r");
5924  }
5925 
5926  rb_str_modify_expand(getpwnm_tmp, bufsizenm);
5927  bufnm = RSTRING_PTR(getpwnm_tmp);
5928  bufsizenm = rb_str_capacity(getpwnm_tmp);
5929  }
5930 
5931  if (pwptr == NULL) {
5932  /* no record in the password database for the login name */
5933  rb_str_resize(getpwnm_tmp, 0);
5934  return Qnil;
5935  }
5936 
5937  /* found it */
5938  VALUE result = rb_str_new_cstr(pwptr->pw_dir);
5939  rb_str_resize(getpwnm_tmp, 0);
5940  return result;
5941 
5942 # elif USE_GETPWNAM
5943 
5944  errno = 0;
5945  pwptr = getpwnam(login);
5946  if (pwptr) {
5947  /* found it */
5948  return rb_str_new_cstr(pwptr->pw_dir);
5949  }
5950  if (errno
5951  /* avoid treating as errors errno values that indicate "not found" */
5952  && ( errno != ENOENT && errno != ESRCH && errno != EBADF && errno != EPERM)) {
5953  rb_syserr_fail(errno, "getpwnam");
5954  }
5955 
5956  return Qnil; /* not found */
5957 # endif
5958 
5959 #endif
5960 }
5961 
5965 VALUE
5966 rb_getpwdiruid(void)
5967 {
5968 # if !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID)
5969  /* Should never happen... </famous-last-words> */
5970  return Qnil;
5971 # else
5972  uid_t ruid = getuid();
5973 
5974  struct passwd *pwptr;
5975 
5976 # ifdef USE_GETPWUID_R
5977 
5978  struct passwd pwdid;
5979  char *bufid;
5980  long bufsizeid = GETPW_R_SIZE_INIT; /* maybe -1 */
5981 
5982  if (bufsizeid < 0)
5983  bufsizeid = GETPW_R_SIZE_DEFAULT;
5984 
5985  VALUE getpwid_tmp = rb_str_tmp_new(bufsizeid);
5986 
5987  bufid = RSTRING_PTR(getpwid_tmp);
5988  bufsizeid = rb_str_capacity(getpwid_tmp);
5989  rb_str_set_len(getpwid_tmp, bufsizeid);
5990 
5991  int eid;
5992  errno = 0;
5993  while ((eid = getpwuid_r(ruid, &pwdid, bufid, bufsizeid, &pwptr)) != 0) {
5994 
5995  if (eid == ENOENT || eid== ESRCH || eid == EBADF || eid == EPERM) {
5996  /* not found; non-errors */
5997  rb_str_resize(getpwid_tmp, 0);
5998  return Qnil;
5999  }
6000 
6001  if (eid != ERANGE || bufsizeid >= GETPW_R_SIZE_LIMIT) {
6002  rb_str_resize(getpwid_tmp, 0);
6003  rb_syserr_fail(eid, "getpwuid_r");
6004  }
6005 
6006  rb_str_modify_expand(getpwid_tmp, bufsizeid);
6007  bufid = RSTRING_PTR(getpwid_tmp);
6008  bufsizeid = rb_str_capacity(getpwid_tmp);
6009  }
6010 
6011  if (pwptr == NULL) {
6012  /* no record in the password database for the uid */
6013  rb_str_resize(getpwid_tmp, 0);
6014  return Qnil;
6015  }
6016 
6017  /* found it */
6018  VALUE result = rb_str_new_cstr(pwptr->pw_dir);
6019  rb_str_resize(getpwid_tmp, 0);
6020  return result;
6021 
6022 # elif defined(USE_GETPWUID)
6023 
6024  errno = 0;
6025  pwptr = getpwuid(ruid);
6026  if (pwptr) {
6027  /* found it */
6028  return rb_str_new_cstr(pwptr->pw_dir);
6029  }
6030  if (errno
6031  /* avoid treating as errors errno values that indicate "not found" */
6032  && ( errno == ENOENT || errno == ESRCH || errno == EBADF || errno == EPERM)) {
6033  rb_syserr_fail(errno, "getpwuid");
6034  }
6035 
6036  return Qnil; /* not found */
6037 # endif
6038 
6039 #endif /* !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) */
6040 }
6041 #endif /* HAVE_PWD_H */
6042 
6043 
6044 /*********************************************************************
6045  * Document-class: Process::Sys
6046  *
6047  * The Process::Sys module contains UID and GID
6048  * functions which provide direct bindings to the system calls of the
6049  * same names instead of the more-portable versions of the same
6050  * functionality found in the Process,
6051  * Process::UID, and Process::GID modules.
6052  */
6053 
6054 #if defined(HAVE_PWD_H)
6055 static rb_uid_t
6056 obj2uid(VALUE id
6057 # ifdef USE_GETPWNAM_R
6058  , VALUE *getpw_tmp
6059 # endif
6060  )
6061 {
6062  rb_uid_t uid;
6063  VALUE tmp;
6064 
6065  if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
6066  uid = NUM2UIDT(id);
6067  }
6068  else {
6069  const char *usrname = StringValueCStr(id);
6070  struct passwd *pwptr;
6071 #ifdef USE_GETPWNAM_R
6072  struct passwd pwbuf;
6073  char *getpw_buf;
6074  long getpw_buf_len;
6075  int e;
6076  if (!*getpw_tmp) {
6077  getpw_buf_len = GETPW_R_SIZE_INIT;
6078  if (getpw_buf_len < 0) getpw_buf_len = GETPW_R_SIZE_DEFAULT;
6079  *getpw_tmp = rb_str_tmp_new(getpw_buf_len);
6080  }
6081  getpw_buf = RSTRING_PTR(*getpw_tmp);
6082  getpw_buf_len = rb_str_capacity(*getpw_tmp);
6083  rb_str_set_len(*getpw_tmp, getpw_buf_len);
6084  errno = 0;
6085  while ((e = getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) != 0) {
6086  if (e != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) {
6087  rb_str_resize(*getpw_tmp, 0);
6088  rb_syserr_fail(e, "getpwnam_r");
6089  }
6090  rb_str_modify_expand(*getpw_tmp, getpw_buf_len);
6091  getpw_buf = RSTRING_PTR(*getpw_tmp);
6092  getpw_buf_len = rb_str_capacity(*getpw_tmp);
6093  }
6094 #else
6095  pwptr = getpwnam(usrname);
6096 #endif
6097  if (!pwptr) {
6098 #ifndef USE_GETPWNAM_R
6099  endpwent();
6100 #endif
6101  rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, id);
6102  }
6103  uid = pwptr->pw_uid;
6104 #ifndef USE_GETPWNAM_R
6105  endpwent();
6106 #endif
6107  }
6108  return uid;
6109 }
6110 
6111 # ifdef p_uid_from_name
6112 /*
6113  * call-seq:
6114  * Process::UID.from_name(name) -> uid
6115  *
6116  * Get the user ID by the _name_.
6117  * If the user is not found, +ArgumentError+ will be raised.
6118  *
6119  * Process::UID.from_name("root") #=> 0
6120  * Process::UID.from_name("nosuchuser") #=> can't find user for nosuchuser (ArgumentError)
6121  */
6122 
6123 static VALUE
6124 p_uid_from_name(VALUE self, VALUE id)
6125 {
6126  return UIDT2NUM(OBJ2UID(id));
6127 }
6128 # endif
6129 #endif
6130 
6131 #if defined(HAVE_GRP_H)
6132 static rb_gid_t
6133 obj2gid(VALUE id
6134 # ifdef USE_GETGRNAM_R
6135  , VALUE *getgr_tmp
6136 # endif
6137  )
6138 {
6139  rb_gid_t gid;
6140  VALUE tmp;
6141 
6142  if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
6143  gid = NUM2GIDT(id);
6144  }
6145  else {
6146  const char *grpname = StringValueCStr(id);
6147  struct group *grptr;
6148 #ifdef USE_GETGRNAM_R
6149  struct group grbuf;
6150  char *getgr_buf;
6151  long getgr_buf_len;
6152  int e;
6153  if (!*getgr_tmp) {
6154  getgr_buf_len = GETGR_R_SIZE_INIT;
6155  if (getgr_buf_len < 0) getgr_buf_len = GETGR_R_SIZE_DEFAULT;
6156  *getgr_tmp = rb_str_tmp_new(getgr_buf_len);
6157  }
6158  getgr_buf = RSTRING_PTR(*getgr_tmp);
6159  getgr_buf_len = rb_str_capacity(*getgr_tmp);
6160  rb_str_set_len(*getgr_tmp, getgr_buf_len);
6161  errno = 0;
6162  while ((e = getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) != 0) {
6163  if (e != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) {
6164  rb_str_resize(*getgr_tmp, 0);
6165  rb_syserr_fail(e, "getgrnam_r");
6166  }
6167  rb_str_modify_expand(*getgr_tmp, getgr_buf_len);
6168  getgr_buf = RSTRING_PTR(*getgr_tmp);
6169  getgr_buf_len = rb_str_capacity(*getgr_tmp);
6170  }
6171 #elif defined(HAVE_GETGRNAM)
6172  grptr = getgrnam(grpname);
6173 #else
6174  grptr = NULL;
6175 #endif
6176  if (!grptr) {
6177 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
6178  endgrent();
6179 #endif
6180  rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, id);
6181  }
6182  gid = grptr->gr_gid;
6183 #if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
6184  endgrent();
6185 #endif
6186  }
6187  return gid;
6188 }
6189 
6190 # ifdef p_gid_from_name
6191 /*
6192  * call-seq:
6193  * Process::GID.from_name(name) -> gid
6194  *
6195  * Get the group ID by the _name_.
6196  * If the group is not found, +ArgumentError+ will be raised.
6197  *
6198  * Process::GID.from_name("wheel") #=> 0
6199  * Process::GID.from_name("nosuchgroup") #=> can't find group for nosuchgroup (ArgumentError)
6200  */
6201 
6202 static VALUE
6203 p_gid_from_name(VALUE self, VALUE id)
6204 {
6205  return GIDT2NUM(OBJ2GID(id));
6206 }
6207 # endif
6208 #endif
6209 
6210 #if defined HAVE_SETUID
6211 /*
6212  * call-seq:
6213  * Process::Sys.setuid(user) -> nil
6214  *
6215  * Set the user ID of the current process to _user_. Not
6216  * available on all platforms.
6217  *
6218  */
6219 
6220 static VALUE
6221 p_sys_setuid(VALUE obj, VALUE id)
6222 {
6223  check_uid_switch();
6224  if (setuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
6225  return Qnil;
6226 }
6227 #else
6228 #define p_sys_setuid rb_f_notimplement
6229 #endif
6230 
6231 
6232 #if defined HAVE_SETRUID
6233 /*
6234  * call-seq:
6235  * Process::Sys.setruid(user) -> nil
6236  *
6237  * Set the real user ID of the calling process to _user_.
6238  * Not available on all platforms.
6239  *
6240  */
6241 
6242 static VALUE
6243 p_sys_setruid(VALUE obj, VALUE id)
6244 {
6245  check_uid_switch();
6246  if (setruid(OBJ2UID(id)) != 0) rb_sys_fail(0);
6247  return Qnil;
6248 }
6249 #else
6250 #define p_sys_setruid rb_f_notimplement
6251 #endif
6252 
6253 
6254 #if defined HAVE_SETEUID
6255 /*
6256  * call-seq:
6257  * Process::Sys.seteuid(user) -> nil
6258  *
6259  * Set the effective user ID of the calling process to
6260  * _user_. Not available on all platforms.
6261  *
6262  */
6263 
6264 static VALUE
6265 p_sys_seteuid(VALUE obj, VALUE id)
6266 {
6267  check_uid_switch();
6268  if (seteuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
6269  return Qnil;
6270 }
6271 #else
6272 #define p_sys_seteuid rb_f_notimplement
6273 #endif
6274 
6275 
6276 #if defined HAVE_SETREUID
6277 /*
6278  * call-seq:
6279  * Process::Sys.setreuid(rid, eid) -> nil
6280  *
6281  * Sets the (user) real and/or effective user IDs of the current
6282  * process to _rid_ and _eid_, respectively. A value of
6283  * <code>-1</code> for either means to leave that ID unchanged. Not
6284  * available on all platforms.
6285  *
6286  */
6287 
6288 static VALUE
6289 p_sys_setreuid(VALUE obj, VALUE rid, VALUE eid)
6290 {
6291  rb_uid_t ruid, euid;
6292  PREPARE_GETPWNAM;
6293  check_uid_switch();
6294  ruid = OBJ2UID1(rid);
6295  euid = OBJ2UID1(eid);
6296  FINISH_GETPWNAM;
6297  if (setreuid(ruid, euid) != 0) rb_sys_fail(0);
6298  return Qnil;
6299 }
6300 #else
6301 #define p_sys_setreuid rb_f_notimplement
6302 #endif
6303 
6304 
6305 #if defined HAVE_SETRESUID
6306 /*
6307  * call-seq:
6308  * Process::Sys.setresuid(rid, eid, sid) -> nil
6309  *
6310  * Sets the (user) real, effective, and saved user IDs of the
6311  * current process to _rid_, _eid_, and _sid_ respectively. A
6312  * value of <code>-1</code> for any value means to
6313  * leave that ID unchanged. Not available on all platforms.
6314  *
6315  */
6316 
6317 static VALUE
6318 p_sys_setresuid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
6319 {
6320  rb_uid_t ruid, euid, suid;
6321  PREPARE_GETPWNAM;
6322  check_uid_switch();
6323  ruid = OBJ2UID1(rid);
6324  euid = OBJ2UID1(eid);
6325  suid = OBJ2UID1(sid);
6326  FINISH_GETPWNAM;
6327  if (setresuid(ruid, euid, suid) != 0) rb_sys_fail(0);
6328  return Qnil;
6329 }
6330 #else
6331 #define p_sys_setresuid rb_f_notimplement
6332 #endif
6333 
6334 
6335 /*
6336  * call-seq:
6337  * Process.uid -> integer
6338  * Process::UID.rid -> integer
6339  * Process::Sys.getuid -> integer
6340  *
6341  * Returns the (real) user ID of this process.
6342  *
6343  * Process.uid #=> 501
6344  */
6345 
6346 static VALUE
6347 proc_getuid(VALUE obj)
6348 {
6349  rb_uid_t uid = getuid();
6350  return UIDT2NUM(uid);
6351 }
6352 
6353 
6354 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
6355 /*
6356  * call-seq:
6357  * Process.uid= user -> numeric
6358  *
6359  * Sets the (user) user ID for this process. Not available on all
6360  * platforms.
6361  */
6362 
6363 static VALUE
6364 proc_setuid(VALUE obj, VALUE id)
6365 {
6366  rb_uid_t uid;
6367 
6368  check_uid_switch();
6369 
6370  uid = OBJ2UID(id);
6371 #if defined(HAVE_SETRESUID)
6372  if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
6373 #elif defined HAVE_SETREUID
6374  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
6375 #elif defined HAVE_SETRUID
6376  if (setruid(uid) < 0) rb_sys_fail(0);
6377 #elif defined HAVE_SETUID
6378  {
6379  if (geteuid() == uid) {
6380  if (setuid(uid) < 0) rb_sys_fail(0);
6381  }
6382  else {
6383  rb_notimplement();
6384  }
6385  }
6386 #endif
6387  return id;
6388 }
6389 #else
6390 #define proc_setuid rb_f_notimplement
6391 #endif
6392 
6393 
6394 /********************************************************************
6395  *
6396  * Document-class: Process::UID
6397  *
6398  * The Process::UID module contains a collection of
6399  * module functions which can be used to portably get, set, and
6400  * switch the current process's real, effective, and saved user IDs.
6401  *
6402  */
6403 
6404 static rb_uid_t SAVED_USER_ID = -1;
6405 
6406 #ifdef BROKEN_SETREUID
6407 int
6408 setreuid(rb_uid_t ruid, rb_uid_t euid)
6409 {
6410  if (ruid != (rb_uid_t)-1 && ruid != getuid()) {
6411  if (euid == (rb_uid_t)-1) euid = geteuid();
6412  if (setuid(ruid) < 0) return -1;
6413  }
6414  if (euid != (rb_uid_t)-1 && euid != geteuid()) {
6415  if (seteuid(euid) < 0) return -1;
6416  }
6417  return 0;
6418 }
6419 #endif
6420 
6421 /*
6422  * call-seq:
6423  * Process::UID.change_privilege(user) -> integer
6424  *
6425  * Change the current process's real and effective user ID to that
6426  * specified by _user_. Returns the new user ID. Not
6427  * available on all platforms.
6428  *
6429  * [Process.uid, Process.euid] #=> [0, 0]
6430  * Process::UID.change_privilege(31) #=> 31
6431  * [Process.uid, Process.euid] #=> [31, 31]
6432  */
6433 
6434 static VALUE
6435 p_uid_change_privilege(VALUE obj, VALUE id)
6436 {
6437  rb_uid_t uid;
6438 
6439  check_uid_switch();
6440 
6441  uid = OBJ2UID(id);
6442 
6443  if (geteuid() == 0) { /* root-user */
6444 #if defined(HAVE_SETRESUID)
6445  if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
6446  SAVED_USER_ID = uid;
6447 #elif defined(HAVE_SETUID)
6448  if (setuid(uid) < 0) rb_sys_fail(0);
6449  SAVED_USER_ID = uid;
6450 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6451  if (getuid() == uid) {
6452  if (SAVED_USER_ID == uid) {
6453  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
6454  }
6455  else {
6456  if (uid == 0) { /* (r,e,s) == (root, root, x) */
6457  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
6458  if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
6459  SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
6460  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
6461  SAVED_USER_ID = uid;
6462  }
6463  else {
6464  if (setreuid(0, -1) < 0) rb_sys_fail(0);
6465  SAVED_USER_ID = 0;
6466  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
6467  SAVED_USER_ID = uid;
6468  }
6469  }
6470  }
6471  else {
6472  if (setreuid(uid, uid) < 0) rb_sys_fail(0);
6473  SAVED_USER_ID = uid;
6474  }
6475 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
6476  if (getuid() == uid) {
6477  if (SAVED_USER_ID == uid) {
6478  if (seteuid(uid) < 0) rb_sys_fail(0);
6479  }
6480  else {
6481  if (uid == 0) {
6482  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
6483  SAVED_USER_ID = 0;
6484  if (setruid(0) < 0) rb_sys_fail(0);
6485  }
6486  else {
6487  if (setruid(0) < 0) rb_sys_fail(0);
6488  SAVED_USER_ID = 0;
6489  if (seteuid(uid) < 0) rb_sys_fail(0);
6490  if (setruid(uid) < 0) rb_sys_fail(0);
6491  SAVED_USER_ID = uid;
6492  }
6493  }
6494  }
6495  else {
6496  if (seteuid(uid) < 0) rb_sys_fail(0);
6497  if (setruid(uid) < 0) rb_sys_fail(0);
6498  SAVED_USER_ID = uid;
6499  }
6500 #else
6501  (void)uid;
6502  rb_notimplement();
6503 #endif
6504  }
6505  else { /* unprivileged user */
6506 #if defined(HAVE_SETRESUID)
6507  if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
6508  (geteuid() == uid)? (rb_uid_t)-1: uid,
6509  (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
6510  SAVED_USER_ID = uid;
6511 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
6512  if (SAVED_USER_ID == uid) {
6513  if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
6514  (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
6515  rb_sys_fail(0);
6516  }
6517  else if (getuid() != uid) {
6518  if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
6519  rb_sys_fail(0);
6520  SAVED_USER_ID = uid;
6521  }
6522  else if (/* getuid() == uid && */ geteuid() != uid) {
6523  if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
6524  SAVED_USER_ID = uid;
6525  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
6526  }
6527  else { /* getuid() == uid && geteuid() == uid */
6528  if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
6529  if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
6530  SAVED_USER_ID = uid;
6531  if (setreuid(uid, -1) < 0) rb_sys_fail(0);
6532  }
6533 #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
6534  if (SAVED_USER_ID == uid) {
6535  if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
6536  if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
6537  }
6538  else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
6539  if (getuid() != uid) {
6540  if (setruid(uid) < 0) rb_sys_fail(0);
6541  SAVED_USER_ID = uid;
6542  }
6543  else {
6544  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
6545  SAVED_USER_ID = uid;
6546  if (setruid(uid) < 0) rb_sys_fail(0);
6547  }
6548  }
6549  else if (/* geteuid() != uid && */ getuid() == uid) {
6550  if (seteuid(uid) < 0) rb_sys_fail(0);
6551  if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
6552  SAVED_USER_ID = uid;
6553  if (setruid(uid) < 0) rb_sys_fail(0);
6554  }
6555  else {
6556  rb_syserr_fail(EPERM, 0);
6557  }
6558 #elif defined HAVE_44BSD_SETUID
6559  if (getuid() == uid) {
6560  /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
6561  if (setuid(uid) < 0) rb_sys_fail(0);
6562  SAVED_USER_ID = uid;
6563  }
6564  else {
6565  rb_syserr_fail(EPERM, 0);
6566  }
6567 #elif defined HAVE_SETEUID
6568  if (getuid() == uid && SAVED_USER_ID == uid) {
6569  if (seteuid(uid) < 0) rb_sys_fail(0);
6570  }
6571  else {
6572  rb_syserr_fail(EPERM, 0);
6573  }
6574 #elif defined HAVE_SETUID
6575  if (getuid() == uid && SAVED_USER_ID == uid) {
6576  if (setuid(uid) < 0) rb_sys_fail(0);
6577  }
6578  else {
6579  rb_syserr_fail(EPERM, 0);
6580  }
6581 #else
6582  rb_notimplement();
6583 #endif
6584  }
6585  return id;
6586 }
6587 
6588 
6589 
6590 #if defined HAVE_SETGID
6591 /*
6592  * call-seq:
6593  * Process::Sys.setgid(group) -> nil
6594  *
6595  * Set the group ID of the current process to _group_. Not
6596  * available on all platforms.
6597  *
6598  */
6599 
6600 static VALUE
6601 p_sys_setgid(VALUE obj, VALUE id)
6602 {
6603  check_gid_switch();
6604  if (setgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
6605  return Qnil;
6606 }
6607 #else
6608 #define p_sys_setgid rb_f_notimplement
6609 #endif
6610 
6611 
6612 #if defined HAVE_SETRGID
6613 /*
6614  * call-seq:
6615  * Process::Sys.setrgid(group) -> nil
6616  *
6617  * Set the real group ID of the calling process to _group_.
6618  * Not available on all platforms.
6619  *
6620  */
6621 
6622 static VALUE
6623 p_sys_setrgid(VALUE obj, VALUE id)
6624 {
6625  check_gid_switch();
6626  if (setrgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
6627  return Qnil;
6628 }
6629 #else
6630 #define p_sys_setrgid rb_f_notimplement
6631 #endif
6632 
6633 
6634 #if defined HAVE_SETEGID
6635 /*
6636  * call-seq:
6637  * Process::Sys.setegid(group) -> nil
6638  *
6639  * Set the effective group ID of the calling process to
6640  * _group_. Not available on all platforms.
6641  *
6642  */
6643 
6644 static VALUE
6645 p_sys_setegid(VALUE obj, VALUE id)
6646 {
6647  check_gid_switch();
6648  if (setegid(OBJ2GID(id)) != 0) rb_sys_fail(0);
6649  return Qnil;
6650 }
6651 #else
6652 #define p_sys_setegid rb_f_notimplement
6653 #endif
6654 
6655 
6656 #if defined HAVE_SETREGID
6657 /*
6658  * call-seq:
6659  * Process::Sys.setregid(rid, eid) -> nil
6660  *
6661  * Sets the (group) real and/or effective group IDs of the current
6662  * process to <em>rid</em> and <em>eid</em>, respectively. A value of
6663  * <code>-1</code> for either means to leave that ID unchanged. Not
6664  * available on all platforms.
6665  *
6666  */
6667 
6668 static VALUE
6669 p_sys_setregid(VALUE obj, VALUE rid, VALUE eid)
6670 {
6671  rb_gid_t rgid, egid;
6672  check_gid_switch();
6673  rgid = OBJ2GID(rid);
6674  egid = OBJ2GID(eid);
6675  if (setregid(rgid, egid) != 0) rb_sys_fail(0);
6676  return Qnil;
6677 }
6678 #else
6679 #define p_sys_setregid rb_f_notimplement
6680 #endif
6681 
6682 #if defined HAVE_SETRESGID
6683 /*
6684  * call-seq:
6685  * Process::Sys.setresgid(rid, eid, sid) -> nil
6686  *
6687  * Sets the (group) real, effective, and saved user IDs of the
6688  * current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
6689  * respectively. A value of <code>-1</code> for any value means to
6690  * leave that ID unchanged. Not available on all platforms.
6691  *
6692  */
6693 
6694 static VALUE
6695 p_sys_setresgid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
6696 {
6697  rb_gid_t rgid, egid, sgid;
6698  check_gid_switch();
6699  rgid = OBJ2GID(rid);
6700  egid = OBJ2GID(eid);
6701  sgid = OBJ2GID(sid);
6702  if (setresgid(rgid, egid, sgid) != 0) rb_sys_fail(0);
6703  return Qnil;
6704 }
6705 #else
6706 #define p_sys_setresgid rb_f_notimplement
6707 #endif
6708 
6709 
6710 #if defined HAVE_ISSETUGID
6711 /*
6712  * call-seq:
6713  * Process::Sys.issetugid -> true or false
6714  *
6715  * Returns +true+ if the process was created as a result
6716  * of an execve(2) system call which had either of the setuid or
6717  * setgid bits set (and extra privileges were given as a result) or
6718  * if it has changed any of its real, effective or saved user or
6719  * group IDs since it began execution.
6720  *
6721  */
6722 
6723 static VALUE
6724 p_sys_issetugid(VALUE obj)
6725 {
6726  if (issetugid()) {
6727  return Qtrue;
6728  }
6729  else {
6730  return Qfalse;
6731  }
6732 }
6733 #else
6734 #define p_sys_issetugid rb_f_notimplement
6735 #endif
6736 
6737 
6738 /*
6739  * call-seq:
6740  * Process.gid -> integer
6741  * Process::GID.rid -> integer
6742  * Process::Sys.getgid -> integer
6743  *
6744  * Returns the (real) group ID for this process.
6745  *
6746  * Process.gid #=> 500
6747  */
6748 
6749 static VALUE
6750 proc_getgid(VALUE obj)
6751 {
6752  rb_gid_t gid = getgid();
6753  return GIDT2NUM(gid);
6754 }
6755 
6756 
6757 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
6758 /*
6759  * call-seq:
6760  * Process.gid= integer -> integer
6761  *
6762  * Sets the group ID for this process.
6763  */
6764 
6765 static VALUE
6766 proc_setgid(VALUE obj, VALUE id)
6767 {
6768  rb_gid_t gid;
6769 
6770  check_gid_switch();
6771 
6772  gid = OBJ2GID(id);
6773 #if defined(HAVE_SETRESGID)
6774  if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
6775 #elif defined HAVE_SETREGID
6776  if (setregid(gid, -1) < 0) rb_sys_fail(0);
6777 #elif defined HAVE_SETRGID
6778  if (setrgid(gid) < 0) rb_sys_fail(0);
6779 #elif defined HAVE_SETGID
6780  {
6781  if (getegid() == gid) {
6782  if (setgid(gid) < 0) rb_sys_fail(0);
6783  }
6784  else {
6785  rb_notimplement();
6786  }
6787  }
6788 #endif
6789  return GIDT2NUM(gid);
6790 }
6791 #else
6792 #define proc_setgid rb_f_notimplement
6793 #endif
6794 
6795 
6796 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
6797 /*
6798  * Maximum supplementary groups are platform dependent.
6799  * FWIW, 65536 is enough big for our supported OSs.
6800  *
6801  * OS Name max groups
6802  * -----------------------------------------------
6803  * Linux Kernel >= 2.6.3 65536
6804  * Linux Kernel < 2.6.3 32
6805  * IBM AIX 5.2 64
6806  * IBM AIX 5.3 ... 6.1 128
6807  * IBM AIX 7.1 128 (can be configured to be up to 2048)
6808  * OpenBSD, NetBSD 16
6809  * FreeBSD < 8.0 16
6810  * FreeBSD >=8.0 1023
6811  * Darwin (Mac OS X) 16
6812  * Sun Solaris 7,8,9,10 16
6813  * Sun Solaris 11 / OpenSolaris 1024
6814  * HP-UX 20
6815  * Windows 1015
6816  */
6817 static int _maxgroups = -1;
6818 static int
6819 get_sc_ngroups_max(void)
6820 {
6821 #ifdef _SC_NGROUPS_MAX
6822  return (int)sysconf(_SC_NGROUPS_MAX);
6823 #elif defined(NGROUPS_MAX)
6824  return (int)NGROUPS_MAX;
6825 #else
6826  return -1;
6827 #endif
6828 }
6829 static int
6830 maxgroups(void)
6831 {
6832  if (_maxgroups < 0) {
6833  _maxgroups = get_sc_ngroups_max();
6834  if (_maxgroups < 0)
6835  _maxgroups = RB_MAX_GROUPS;
6836  }
6837 
6838  return _maxgroups;
6839 }
6840 #endif
6841 
6842 
6843 
6844 #ifdef HAVE_GETGROUPS
6845 /*
6846  * call-seq:
6847  * Process.groups -> array
6848  *
6849  * Get an Array of the group IDs in the
6850  * supplemental group access list for this process.
6851  *
6852  * Process.groups #=> [27, 6, 10, 11]
6853  *
6854  * Note that this method is just a wrapper of getgroups(2).
6855  * This means that the following characteristics of
6856  * the result completely depend on your system:
6857  *
6858  * - the result is sorted
6859  * - the result includes effective GIDs
6860  * - the result does not include duplicated GIDs
6861  *
6862  * You can make sure to get a sorted unique GID list of
6863  * the current process by this expression:
6864  *
6865  * Process.groups.uniq.sort
6866  *
6867  */
6868 
6869 static VALUE
6870 proc_getgroups(VALUE obj)
6871 {
6872  VALUE ary, tmp;
6873  int i, ngroups;
6874  rb_gid_t *groups;
6875 
6876  ngroups = getgroups(0, NULL);
6877  if (ngroups == -1)
6878  rb_sys_fail(0);
6879 
6880  groups = ALLOCV_N(rb_gid_t, tmp, ngroups);
6881 
6882  ngroups = getgroups(ngroups, groups);
6883  if (ngroups == -1)
6884  rb_sys_fail(0);
6885 
6886  ary = rb_ary_new();
6887  for (i = 0; i < ngroups; i++)
6888  rb_ary_push(ary, GIDT2NUM(groups[i]));
6889 
6890  ALLOCV_END(tmp);
6891 
6892  return ary;
6893 }
6894 #else
6895 #define proc_getgroups rb_f_notimplement
6896 #endif
6897 
6898 
6899 #ifdef HAVE_SETGROUPS
6900 /*
6901  * call-seq:
6902  * Process.groups= array -> array
6903  *
6904  * Set the supplemental group access list to the given
6905  * Array of group IDs.
6906  *
6907  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
6908  * Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11]
6909  * Process.groups #=> [27, 6, 10, 11]
6910  *
6911  */
6912 
6913 static VALUE
6914 proc_setgroups(VALUE obj, VALUE ary)
6915 {
6916  int ngroups, i;
6917  rb_gid_t *groups;
6918  VALUE tmp;
6919  PREPARE_GETGRNAM;
6920 
6921  Check_Type(ary, T_ARRAY);
6922 
6923  ngroups = RARRAY_LENINT(ary);
6924  if (ngroups > maxgroups())
6925  rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());
6926 
6927  groups = ALLOCV_N(rb_gid_t, tmp, ngroups);
6928 
6929  for (i = 0; i < ngroups; i++) {
6930  VALUE g = RARRAY_AREF(ary, i);
6931 
6932  groups[i] = OBJ2GID1(g);
6933  }
6934  FINISH_GETGRNAM;
6935 
6936  if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
6937  rb_sys_fail(0);
6938 
6939  ALLOCV_END(tmp);
6940 
6941  return proc_getgroups(obj);
6942 }
6943 #else
6944 #define proc_setgroups rb_f_notimplement
6945 #endif
6946 
6947 
6948 #ifdef HAVE_INITGROUPS
6949 /*
6950  * call-seq:
6951  * Process.initgroups(username, gid) -> array
6952  *
6953  * Initializes the supplemental group access list by reading the
6954  * system group database and using all groups of which the given user
6955  * is a member. The group with the specified <em>gid</em> is also
6956  * added to the list. Returns the resulting Array of the
6957  * gids of all the groups in the supplementary group access list. Not
6958  * available on all platforms.
6959  *
6960  * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
6961  * Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
6962  * Process.groups #=> [30, 6, 10, 11]
6963  *
6964  */
6965 
6966 static VALUE
6967 proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
6968 {
6969  if (initgroups(StringValueCStr(uname), OBJ2GID(base_grp)) != 0) {
6970  rb_sys_fail(0);
6971  }
6972  return proc_getgroups(obj);
6973 }
6974 #else
6975 #define proc_initgroups rb_f_notimplement
6976 #endif
6977 
6978 #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
6979 /*
6980  * call-seq:
6981  * Process.maxgroups -> integer
6982  *
6983  * Returns the maximum number of gids allowed in the supplemental
6984  * group access list.
6985  *
6986  * Process.maxgroups #=> 32
6987  */
6988 
6989 static VALUE
6990 proc_getmaxgroups(VALUE obj)
6991 {
6992  return INT2FIX(maxgroups());
6993 }
6994 #else
6995 #define proc_getmaxgroups rb_f_notimplement
6996 #endif
6997 
6998 #ifdef HAVE_SETGROUPS
6999 /*
7000  * call-seq:
7001  * Process.maxgroups= integer -> integer
7002  *
7003  * Sets the maximum number of gids allowed in the supplemental group
7004  * access list.
7005  */
7006 
7007 static VALUE
7008 proc_setmaxgroups(VALUE obj, VALUE val)
7009 {
7010  int ngroups = FIX2INT(val);
7011  int ngroups_max = get_sc_ngroups_max();
7012 
7013  if (ngroups <= 0)
7014  rb_raise(rb_eArgError, "maxgroups %d should be positive", ngroups);
7015 
7016  if (ngroups > RB_MAX_GROUPS)
7017  ngroups = RB_MAX_GROUPS;
7018 
7019  if (ngroups_max > 0 && ngroups > ngroups_max)
7020  ngroups = ngroups_max;
7021 
7022  _maxgroups = ngroups;
7023 
7024  return INT2FIX(_maxgroups);
7025 }
7026 #else
7027 #define proc_setmaxgroups rb_f_notimplement
7028 #endif
7029 
7030 #if defined(HAVE_DAEMON) || (defined(HAVE_WORKING_FORK) && defined(HAVE_SETSID))
7031 static int rb_daemon(int nochdir, int noclose);
7032 
7033 /*
7034  * call-seq:
7035  * Process.daemon() -> 0
7036  * Process.daemon(nochdir=nil,noclose=nil) -> 0
7037  *
7038  * Detach the process from controlling terminal and run in
7039  * the background as system daemon. Unless the argument
7040  * nochdir is true (i.e. non false), it changes the current
7041  * working directory to the root ("/"). Unless the argument
7042  * noclose is true, daemon() will redirect standard input,
7043  * standard output and standard error to /dev/null.
7044  * Return zero on success, or raise one of Errno::*.
7045  */
7046 
7047 static VALUE
7048 proc_daemon(int argc, VALUE *argv, VALUE _)
7049 {
7050  int n, nochdir = FALSE, noclose = FALSE;
7051 
7052  switch (rb_check_arity(argc, 0, 2)) {
7053  case 2: noclose = TO_BOOL(argv[1], "noclose");
7054  case 1: nochdir = TO_BOOL(argv[0], "nochdir");
7055  }
7056 
7057  prefork();
7058  n = rb_daemon(nochdir, noclose);
7059  if (n < 0) rb_sys_fail("daemon");
7060  return INT2FIX(n);
7061 }
7062 
7063 static int
7064 rb_daemon(int nochdir, int noclose)
7065 {
7066  int err = 0;
7067 #ifdef HAVE_DAEMON
7068  if (mjit_enabled) mjit_pause(false); // Don't leave locked mutex to child.
7069  before_fork_ruby();
7070  err = daemon(nochdir, noclose);
7071  after_fork_ruby();
7072  rb_thread_atfork(); /* calls mjit_resume() */
7073 #else
7074  int n;
7075 
7076 #define fork_daemon() \
7077  switch (rb_fork_ruby(NULL)) { \
7078  case -1: return -1; \
7079  case 0: break; \
7080  default: _exit(EXIT_SUCCESS); \
7081  }
7082 
7083  fork_daemon();
7084 
7085  if (setsid() < 0) return -1;
7086 
7087  /* must not be process-leader */
7088  fork_daemon();
7089 
7090  if (!nochdir)
7091  err = chdir("/");
7092 
7093  if (!noclose && (n = rb_cloexec_open("/dev/null", O_RDWR, 0)) != -1) {
7094  rb_update_max_fd(n);
7095  (void)dup2(n, 0);
7096  (void)dup2(n, 1);
7097  (void)dup2(n, 2);
7098  if (n > 2)
7099  (void)close (n);
7100  }
7101 #endif
7102  return err;
7103 }
7104 #else
7105 #define proc_daemon rb_f_notimplement
7106 #endif
7107 
7108 /********************************************************************
7109  *
7110  * Document-class: Process::GID
7111  *
7112  * The Process::GID module contains a collection of
7113  * module functions which can be used to portably get, set, and
7114  * switch the current process's real, effective, and saved group IDs.
7115  *
7116  */
7117 
7118 static rb_gid_t SAVED_GROUP_ID = -1;
7119 
7120 #ifdef BROKEN_SETREGID
7121 int
7122 setregid(rb_gid_t rgid, rb_gid_t egid)
7123 {
7124  if (rgid != (rb_gid_t)-1 && rgid != getgid()) {
7125  if (egid == (rb_gid_t)-1) egid = getegid();
7126  if (setgid(rgid) < 0) return -1;
7127  }
7128  if (egid != (rb_gid_t)-1 && egid != getegid()) {
7129  if (setegid(egid) < 0) return -1;
7130  }
7131  return 0;
7132 }
7133 #endif
7134 
7135 /*
7136  * call-seq:
7137  * Process::GID.change_privilege(group) -> integer
7138  *
7139  * Change the current process's real and effective group ID to that
7140  * specified by _group_. Returns the new group ID. Not
7141  * available on all platforms.
7142  *
7143  * [Process.gid, Process.egid] #=> [0, 0]
7144  * Process::GID.change_privilege(33) #=> 33
7145  * [Process.gid, Process.egid] #=> [33, 33]
7146  */
7147 
7148 static VALUE
7149 p_gid_change_privilege(VALUE obj, VALUE id)
7150 {
7151  rb_gid_t gid;
7152 
7153  check_gid_switch();
7154 
7155  gid = OBJ2GID(id);
7156 
7157  if (geteuid() == 0) { /* root-user */
7158 #if defined(HAVE_SETRESGID)
7159  if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
7160  SAVED_GROUP_ID = gid;
7161 #elif defined HAVE_SETGID
7162  if (setgid(gid) < 0) rb_sys_fail(0);
7163  SAVED_GROUP_ID = gid;
7164 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
7165  if (getgid() == gid) {
7166  if (SAVED_GROUP_ID == gid) {
7167  if (setregid(-1, gid) < 0) rb_sys_fail(0);
7168  }
7169  else {
7170  if (gid == 0) { /* (r,e,s) == (root, y, x) */
7171  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
7172  if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
7173  SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
7174  if (setregid(gid, gid) < 0) rb_sys_fail(0);
7175  SAVED_GROUP_ID = gid;
7176  }
7177  else { /* (r,e,s) == (z, y, x) */
7178  if (setregid(0, 0) < 0) rb_sys_fail(0);
7179  SAVED_GROUP_ID = 0;
7180  if (setregid(gid, gid) < 0) rb_sys_fail(0);
7181  SAVED_GROUP_ID = gid;
7182  }
7183  }
7184  }
7185  else {
7186  if (setregid(gid, gid) < 0) rb_sys_fail(0);
7187  SAVED_GROUP_ID = gid;
7188  }
7189 #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
7190  if (getgid() == gid) {
7191  if (SAVED_GROUP_ID == gid) {
7192  if (setegid(gid) < 0) rb_sys_fail(0);
7193  }
7194  else {
7195  if (gid == 0) {
7196  if (setegid(gid) < 0) rb_sys_fail(0);
7197  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
7198  SAVED_GROUP_ID = 0;
7199  if (setrgid(0) < 0) rb_sys_fail(0);
7200  }
7201  else {
7202  if (setrgid(0) < 0) rb_sys_fail(0);
7203  SAVED_GROUP_ID = 0;
7204  if (setegid(gid) < 0) rb_sys_fail(0);
7205  if (setrgid(gid) < 0) rb_sys_fail(0);
7206  SAVED_GROUP_ID = gid;
7207  }
7208  }
7209  }
7210  else {
7211  if (setegid(gid) < 0) rb_sys_fail(0);
7212  if (setrgid(gid) < 0) rb_sys_fail(0);
7213  SAVED_GROUP_ID = gid;
7214  }
7215 #else
7216  rb_notimplement();
7217 #endif
7218  }
7219  else { /* unprivileged user */
7220 #if defined(HAVE_SETRESGID)
7221  if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
7222  (getegid() == gid)? (rb_gid_t)-1: gid,
7223  (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
7224  SAVED_GROUP_ID = gid;
7225 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
7226  if (SAVED_GROUP_ID == gid) {
7227  if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
7228  (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
7229  rb_sys_fail(0);
7230  }
7231  else if (getgid() != gid) {
7232  if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
7233  rb_sys_fail(0);
7234  SAVED_GROUP_ID = gid;
7235  }
7236  else if (/* getgid() == gid && */ getegid() != gid) {
7237  if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
7238  SAVED_GROUP_ID = gid;
7239  if (setregid(gid, -1) < 0) rb_sys_fail(0);
7240  }
7241  else { /* getgid() == gid && getegid() == gid */
7242  if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
7243  if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
7244  SAVED_GROUP_ID = gid;
7245  if (setregid(gid, -1) < 0) rb_sys_fail(0);
7246  }
7247 #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
7248  if (SAVED_GROUP_ID == gid) {
7249  if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
7250  if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
7251  }
7252  else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
7253  if (getgid() != gid) {
7254  if (setrgid(gid) < 0) rb_sys_fail(0);
7255  SAVED_GROUP_ID = gid;
7256  }
7257  else {
7258  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
7259  SAVED_GROUP_ID = gid;
7260  if (setrgid(gid) < 0) rb_sys_fail(0);
7261  }
7262  }
7263  else if (/* getegid() != gid && */ getgid() == gid) {
7264  if (setegid(gid) < 0) rb_sys_fail(0);
7265  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
7266  SAVED_GROUP_ID = gid;
7267  if (setrgid(gid) < 0) rb_sys_fail(0);
7268  }
7269  else {
7270  rb_syserr_fail(EPERM, 0);
7271  }
7272 #elif defined HAVE_44BSD_SETGID
7273  if (getgid() == gid) {
7274  /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
7275  if (setgid(gid) < 0) rb_sys_fail(0);
7276  SAVED_GROUP_ID = gid;
7277  }
7278  else {
7279  rb_syserr_fail(EPERM, 0);
7280  }
7281 #elif defined HAVE_SETEGID
7282  if (getgid() == gid && SAVED_GROUP_ID == gid) {
7283  if (setegid(gid) < 0) rb_sys_fail(0);
7284  }
7285  else {
7286  rb_syserr_fail(EPERM, 0);
7287  }
7288 #elif defined HAVE_SETGID
7289  if (getgid() == gid && SAVED_GROUP_ID == gid) {
7290  if (setgid(gid) < 0) rb_sys_fail(0);
7291  }
7292  else {
7293  rb_syserr_fail(EPERM, 0);
7294  }
7295 #else
7296  (void)gid;
7297  rb_notimplement();
7298 #endif
7299  }
7300  return id;
7301 }
7302 
7303 
7304 /*
7305  * call-seq:
7306  * Process.euid -> integer
7307  * Process::UID.eid -> integer
7308  * Process::Sys.geteuid -> integer
7309  *
7310  * Returns the effective user ID for this process.
7311  *
7312  * Process.euid #=> 501
7313  */
7314 
7315 static VALUE
7316 proc_geteuid(VALUE obj)
7317 {
7318  rb_uid_t euid = geteuid();
7319  return UIDT2NUM(euid);
7320 }
7321 
7322 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
7323 static void
7324 proc_seteuid(rb_uid_t uid)
7325 {
7326 #if defined(HAVE_SETRESUID)
7327  if (setresuid(-1, uid, -1) < 0) rb_sys_fail(0);
7328 #elif defined HAVE_SETREUID
7329  if (setreuid(-1, uid) < 0) rb_sys_fail(0);
7330 #elif defined HAVE_SETEUID
7331  if (seteuid(uid) < 0) rb_sys_fail(0);
7332 #elif defined HAVE_SETUID
7333  if (uid == getuid()) {
7334  if (setuid(uid) < 0) rb_sys_fail(0);
7335  }
7336  else {
7337  rb_notimplement();
7338  }
7339 #else
7340  rb_notimplement();
7341 #endif
7342 }
7343 #endif
7344 
7345 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
7346 /*
7347  * call-seq:
7348  * Process.euid= user
7349  *
7350  * Sets the effective user ID for this process. Not available on all
7351  * platforms.
7352  */
7353 
7354 static VALUE
7355 proc_seteuid_m(VALUE mod, VALUE euid)
7356 {
7357  check_uid_switch();
7358  proc_seteuid(OBJ2UID(euid));
7359  return euid;
7360 }
7361 #else
7362 #define proc_seteuid_m rb_f_notimplement
7363 #endif
7364 
7365 static rb_uid_t
7366 rb_seteuid_core(rb_uid_t euid)
7367 {
7368 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
7369  rb_uid_t uid;
7370 #endif
7371 
7372  check_uid_switch();
7373 
7374 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
7375  uid = getuid();
7376 #endif
7377 
7378 #if defined(HAVE_SETRESUID)
7379  if (uid != euid) {
7380  if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
7381  SAVED_USER_ID = euid;
7382  }
7383  else {
7384  if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
7385  }
7386 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
7387  if (setreuid(-1, euid) < 0) rb_sys_fail(0);
7388  if (uid != euid) {
7389  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
7390  if (setreuid(uid,euid) < 0) rb_sys_fail(0);
7391  SAVED_USER_ID = euid;
7392  }
7393 #elif defined HAVE_SETEUID
7394  if (seteuid(euid) < 0) rb_sys_fail(0);
7395 #elif defined HAVE_SETUID
7396  if (geteuid() == 0) rb_sys_fail(0);
7397  if (setuid(euid) < 0) rb_sys_fail(0);
7398 #else
7399  rb_notimplement();
7400 #endif
7401  return euid;
7402 }
7403 
7404 
7405 /*
7406  * call-seq:
7407  * Process::UID.grant_privilege(user) -> integer
7408  * Process::UID.eid= user -> integer
7409  *
7410  * Set the effective user ID, and if possible, the saved user ID of
7411  * the process to the given _user_. Returns the new
7412  * effective user ID. Not available on all platforms.
7413  *
7414  * [Process.uid, Process.euid] #=> [0, 0]
7415  * Process::UID.grant_privilege(31) #=> 31
7416  * [Process.uid, Process.euid] #=> [0, 31]
7417  */
7418 
7419 static VALUE
7420 p_uid_grant_privilege(VALUE obj, VALUE id)
7421 {
7422  rb_seteuid_core(OBJ2UID(id));
7423  return id;
7424 }
7425 
7426 
7427 /*
7428  * call-seq:
7429  * Process.egid -> integer
7430  * Process::GID.eid -> integer
7431  * Process::Sys.geteid -> integer
7432  *
7433  * Returns the effective group ID for this process. Not available on
7434  * all platforms.
7435  *
7436  * Process.egid #=> 500
7437  */
7438 
7439 static VALUE
7440 proc_getegid(VALUE obj)
7441 {
7442  rb_gid_t egid = getegid();
7443 
7444  return GIDT2NUM(egid);
7445 }
7446 
7447 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
7448 /*
7449  * call-seq:
7450  * Process.egid = integer -> integer
7451  *
7452  * Sets the effective group ID for this process. Not available on all
7453  * platforms.
7454  */
7455 
7456 static VALUE
7457 proc_setegid(VALUE obj, VALUE egid)
7458 {
7459 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
7460  rb_gid_t gid;
7461 #endif
7462 
7463  check_gid_switch();
7464 
7465 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
7466  gid = OBJ2GID(egid);
7467 #endif
7468 
7469 #if defined(HAVE_SETRESGID)
7470  if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
7471 #elif defined HAVE_SETREGID
7472  if (setregid(-1, gid) < 0) rb_sys_fail(0);
7473 #elif defined HAVE_SETEGID
7474  if (setegid(gid) < 0) rb_sys_fail(0);
7475 #elif defined HAVE_SETGID
7476  if (gid == getgid()) {
7477  if (setgid(gid) < 0) rb_sys_fail(0);
7478  }
7479  else {
7480  rb_notimplement();
7481  }
7482 #else
7483  rb_notimplement();
7484 #endif
7485  return egid;
7486 }
7487 #endif
7488 
7489 #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
7490 #define proc_setegid_m proc_setegid
7491 #else
7492 #define proc_setegid_m rb_f_notimplement
7493 #endif
7494 
7495 static rb_gid_t
7496 rb_setegid_core(rb_gid_t egid)
7497 {
7498 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
7499  rb_gid_t gid;
7500 #endif
7501 
7502  check_gid_switch();
7503 
7504 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
7505  gid = getgid();
7506 #endif
7507 
7508 #if defined(HAVE_SETRESGID)
7509  if (gid != egid) {
7510  if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
7511  SAVED_GROUP_ID = egid;
7512  }
7513  else {
7514  if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
7515  }
7516 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
7517  if (setregid(-1, egid) < 0) rb_sys_fail(0);
7518  if (gid != egid) {
7519  if (setregid(egid,gid) < 0) rb_sys_fail(0);
7520  if (setregid(gid,egid) < 0) rb_sys_fail(0);
7521  SAVED_GROUP_ID = egid;
7522  }
7523 #elif defined HAVE_SETEGID
7524  if (setegid(egid) < 0) rb_sys_fail(0);
7525 #elif defined HAVE_SETGID
7526  if (geteuid() == 0 /* root user */) rb_sys_fail(0);
7527  if (setgid(egid) < 0) rb_sys_fail(0);
7528 #else
7529  rb_notimplement();
7530 #endif
7531  return egid;
7532 }
7533 
7534 
7535 /*
7536  * call-seq:
7537  * Process::GID.grant_privilege(group) -> integer
7538  * Process::GID.eid = group -> integer
7539  *
7540  * Set the effective group ID, and if possible, the saved group ID of
7541  * the process to the given _group_. Returns the new
7542  * effective group ID. Not available on all platforms.
7543  *
7544  * [Process.gid, Process.egid] #=> [0, 0]
7545  * Process::GID.grant_privilege(31) #=> 33
7546  * [Process.gid, Process.egid] #=> [0, 33]
7547  */
7548 
7549 static VALUE
7550 p_gid_grant_privilege(VALUE obj, VALUE id)
7551 {
7552  rb_setegid_core(OBJ2GID(id));
7553  return id;
7554 }
7555 
7556 
7557 /*
7558  * call-seq:
7559  * Process::UID.re_exchangeable? -> true or false
7560  *
7561  * Returns +true+ if the real and effective user IDs of a
7562  * process may be exchanged on the current platform.
7563  *
7564  */
7565 
7566 static VALUE
7567 p_uid_exchangeable(VALUE _)
7568 {
7569 #if defined(HAVE_SETRESUID)
7570  return Qtrue;
7571 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
7572  return Qtrue;
7573 #else
7574  return Qfalse;
7575 #endif
7576 }
7577 
7578 
7579 /*
7580  * call-seq:
7581  * Process::UID.re_exchange -> integer
7582  *
7583  * Exchange real and effective user IDs and return the new effective
7584  * user ID. Not available on all platforms.
7585  *
7586  * [Process.uid, Process.euid] #=> [0, 31]
7587  * Process::UID.re_exchange #=> 0
7588  * [Process.uid, Process.euid] #=> [31, 0]
7589  */
7590 
7591 static VALUE
7592 p_uid_exchange(VALUE obj)
7593 {
7594  rb_uid_t uid;
7595 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
7596  rb_uid_t euid;
7597 #endif
7598 
7599  check_uid_switch();
7600 
7601  uid = getuid();
7602 #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
7603  euid = geteuid();
7604 #endif
7605 
7606 #if defined(HAVE_SETRESUID)
7607  if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
7608  SAVED_USER_ID = uid;
7609 #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
7610  if (setreuid(euid,uid) < 0) rb_sys_fail(0);
7611  SAVED_USER_ID = uid;
7612 #else
7613  rb_notimplement();
7614 #endif
7615  return UIDT2NUM(uid);
7616 }
7617 
7618 
7619 /*
7620  * call-seq:
7621  * Process::GID.re_exchangeable? -> true or false
7622  *
7623  * Returns +true+ if the real and effective group IDs of a
7624  * process may be exchanged on the current platform.
7625  *
7626  */
7627 
7628 static VALUE
7629 p_gid_exchangeable(VALUE _)
7630 {
7631 #if defined(HAVE_SETRESGID)
7632  return Qtrue;
7633 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
7634  return Qtrue;
7635 #else
7636  return Qfalse;
7637 #endif
7638 }
7639 
7640 
7641 /*
7642  * call-seq:
7643  * Process::GID.re_exchange -> integer
7644  *
7645  * Exchange real and effective group IDs and return the new effective
7646  * group ID. Not available on all platforms.
7647  *
7648  * [Process.gid, Process.egid] #=> [0, 33]
7649  * Process::GID.re_exchange #=> 0
7650  * [Process.gid, Process.egid] #=> [33, 0]
7651  */
7652 
7653 static VALUE
7654 p_gid_exchange(VALUE obj)
7655 {
7656  rb_gid_t gid;
7657 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
7658  rb_gid_t egid;
7659 #endif
7660 
7661  check_gid_switch();
7662 
7663  gid = getgid();
7664 #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
7665  egid = getegid();
7666 #endif
7667 
7668 #if defined(HAVE_SETRESGID)
7669  if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
7670  SAVED_GROUP_ID = gid;
7671 #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
7672  if (setregid(egid,gid) < 0) rb_sys_fail(0);
7673  SAVED_GROUP_ID = gid;
7674 #else
7675  rb_notimplement();
7676 #endif
7677  return GIDT2NUM(gid);
7678 }
7679 
7680 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
7681 
7682 /*
7683  * call-seq:
7684  * Process::UID.sid_available? -> true or false
7685  *
7686  * Returns +true+ if the current platform has saved user
7687  * ID functionality.
7688  *
7689  */
7690 
7691 static VALUE
7692 p_uid_have_saved_id(VALUE _)
7693 {
7694 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
7695  return Qtrue;
7696 #else
7697  return Qfalse;
7698 #endif
7699 }
7700 
7701 
7702 #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
7703 static VALUE
7704 p_uid_sw_ensure(VALUE i)
7705 {
7706  rb_uid_t id = (rb_uid_t/* narrowing */)i;
7707  under_uid_switch = 0;
7708  id = rb_seteuid_core(id);
7709  return UIDT2NUM(id);
7710 }
7711 
7712 
7713 /*
7714  * call-seq:
7715  * Process::UID.switch -> integer
7716  * Process::UID.switch {|| block} -> object
7717  *
7718  * Switch the effective and real user IDs of the current process. If
7719  * a <em>block</em> is given, the user IDs will be switched back
7720  * after the block is executed. Returns the new effective user ID if
7721  * called without a block, and the return value of the block if one
7722  * is given.
7723  *
7724  */
7725 
7726 static VALUE
7727 p_uid_switch(VALUE obj)
7728 {
7729  rb_uid_t uid, euid;
7730 
7731  check_uid_switch();
7732 
7733  uid = getuid();
7734  euid = geteuid();
7735 
7736  if (uid != euid) {
7737  proc_seteuid(uid);
7738  if (rb_block_given_p()) {
7739  under_uid_switch = 1;
7740  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
7741  }
7742  else {
7743  return UIDT2NUM(euid);
7744  }
7745  }
7746  else if (euid != SAVED_USER_ID) {
7747  proc_seteuid(SAVED_USER_ID);
7748  if (rb_block_given_p()) {
7749  under_uid_switch = 1;
7750  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
7751  }
7752  else {
7753  return UIDT2NUM(uid);
7754  }
7755  }
7756  else {
7757  rb_syserr_fail(EPERM, 0);
7758  }
7759 
7761 }
7762 #else
7763 static VALUE
7764 p_uid_sw_ensure(VALUE obj)
7765 {
7766  under_uid_switch = 0;
7767  return p_uid_exchange(obj);
7768 }
7769 
7770 static VALUE
7771 p_uid_switch(VALUE obj)
7772 {
7773  rb_uid_t uid, euid;
7774 
7775  check_uid_switch();
7776 
7777  uid = getuid();
7778  euid = geteuid();
7779 
7780  if (uid == euid) {
7781  rb_syserr_fail(EPERM, 0);
7782  }
7783  p_uid_exchange(obj);
7784  if (rb_block_given_p()) {
7785  under_uid_switch = 1;
7786  return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
7787  }
7788  else {
7789  return UIDT2NUM(euid);
7790  }
7791 }
7792 #endif
7793 
7794 
7795 /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
7796 
7797 /*
7798  * call-seq:
7799  * Process::GID.sid_available? -> true or false
7800  *
7801  * Returns +true+ if the current platform has saved group
7802  * ID functionality.
7803  *
7804  */
7805 
7806 static VALUE
7807 p_gid_have_saved_id(VALUE _)
7808 {
7809 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
7810  return Qtrue;
7811 #else
7812  return Qfalse;
7813 #endif
7814 }
7815 
7816 #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
7817 static VALUE
7818 p_gid_sw_ensure(VALUE i)
7819 {
7820  rb_gid_t id = (rb_gid_t/* narrowing */)i;
7821  under_gid_switch = 0;
7822  id = rb_setegid_core(id);
7823  return GIDT2NUM(id);
7824 }
7825 
7826 
7827 /*
7828  * call-seq:
7829  * Process::GID.switch -> integer
7830  * Process::GID.switch {|| block} -> object
7831  *
7832  * Switch the effective and real group IDs of the current process. If
7833  * a <em>block</em> is given, the group IDs will be switched back
7834  * after the block is executed. Returns the new effective group ID if
7835  * called without a block, and the return value of the block if one
7836  * is given.
7837  *
7838  */
7839 
7840 static VALUE
7841 p_gid_switch(VALUE obj)
7842 {
7843  rb_gid_t gid, egid;
7844 
7845  check_gid_switch();
7846 
7847  gid = getgid();
7848  egid = getegid();
7849 
7850  if (gid != egid) {
7851  proc_setegid(obj, GIDT2NUM(gid));
7852  if (rb_block_given_p()) {
7853  under_gid_switch = 1;
7854  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
7855  }
7856  else {
7857  return GIDT2NUM(egid);
7858  }
7859  }
7860  else if (egid != SAVED_GROUP_ID) {
7861  proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
7862  if (rb_block_given_p()) {
7863  under_gid_switch = 1;
7864  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
7865  }
7866  else {
7867  return GIDT2NUM(gid);
7868  }
7869  }
7870  else {
7871  rb_syserr_fail(EPERM, 0);
7872  }
7873 
7875 }
7876 #else
7877 static VALUE
7878 p_gid_sw_ensure(VALUE obj)
7879 {
7880  under_gid_switch = 0;
7881  return p_gid_exchange(obj);
7882 }
7883 
7884 static VALUE
7885 p_gid_switch(VALUE obj)
7886 {
7887  rb_gid_t gid, egid;
7888 
7889  check_gid_switch();
7890 
7891  gid = getgid();
7892  egid = getegid();
7893 
7894  if (gid == egid) {
7895  rb_syserr_fail(EPERM, 0);
7896  }
7897  p_gid_exchange(obj);
7898  if (rb_block_given_p()) {
7899  under_gid_switch = 1;
7900  return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
7901  }
7902  else {
7903  return GIDT2NUM(egid);
7904  }
7905 }
7906 #endif
7907 
7908 
7909 #if defined(HAVE_TIMES)
7910 static long
7911 get_clk_tck(void)
7912 {
7913 #ifdef HAVE__SC_CLK_TCK
7914  return sysconf(_SC_CLK_TCK);
7915 #elif defined CLK_TCK
7916  return CLK_TCK;
7917 #elif defined HZ
7918  return HZ;
7919 #else
7920  return 60;
7921 #endif
7922 }
7923 
7924 /*
7925  * call-seq:
7926  * Process.times -> aProcessTms
7927  *
7928  * Returns a <code>Tms</code> structure (see Process::Tms)
7929  * that contains user and system CPU times for this process,
7930  * and also for children processes.
7931  *
7932  * t = Process.times
7933  * [ t.utime, t.stime, t.cutime, t.cstime ] #=> [0.0, 0.02, 0.00, 0.00]
7934  */
7935 
7936 VALUE
7937 rb_proc_times(VALUE obj)
7938 {
7939  VALUE utime, stime, cutime, cstime, ret;
7940 #if defined(RUSAGE_SELF) && defined(RUSAGE_CHILDREN)
7941  struct rusage usage_s, usage_c;
7942 
7943  if (getrusage(RUSAGE_SELF, &usage_s) != 0 || getrusage(RUSAGE_CHILDREN, &usage_c) != 0)
7944  rb_sys_fail("getrusage");
7945  utime = DBL2NUM((double)usage_s.ru_utime.tv_sec + (double)usage_s.ru_utime.tv_usec/1e6);
7946  stime = DBL2NUM((double)usage_s.ru_stime.tv_sec + (double)usage_s.ru_stime.tv_usec/1e6);
7947  cutime = DBL2NUM((double)usage_c.ru_utime.tv_sec + (double)usage_c.ru_utime.tv_usec/1e6);
7948  cstime = DBL2NUM((double)usage_c.ru_stime.tv_sec + (double)usage_c.ru_stime.tv_usec/1e6);
7949 #else
7950  const double hertz = (double)get_clk_tck();
7951  struct tms buf;
7952 
7953  times(&buf);
7954  utime = DBL2NUM(buf.tms_utime / hertz);
7955  stime = DBL2NUM(buf.tms_stime / hertz);
7956  cutime = DBL2NUM(buf.tms_cutime / hertz);
7957  cstime = DBL2NUM(buf.tms_cstime / hertz);
7958 #endif
7959  ret = rb_struct_new(rb_cProcessTms, utime, stime, cutime, cstime);
7960  RB_GC_GUARD(utime);
7961  RB_GC_GUARD(stime);
7962  RB_GC_GUARD(cutime);
7963  RB_GC_GUARD(cstime);
7964  return ret;
7965 }
7966 #else
7967 #define rb_proc_times rb_f_notimplement
7968 #endif
7969 
7970 #ifdef HAVE_LONG_LONG
7971 typedef LONG_LONG timetick_int_t;
7972 #define TIMETICK_INT_MIN LLONG_MIN
7973 #define TIMETICK_INT_MAX LLONG_MAX
7974 #define TIMETICK_INT2NUM(v) LL2NUM(v)
7975 #define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_LONG_P(a, b)
7976 #else
7977 typedef long timetick_int_t;
7978 #define TIMETICK_INT_MIN LONG_MIN
7979 #define TIMETICK_INT_MAX LONG_MAX
7980 #define TIMETICK_INT2NUM(v) LONG2NUM(v)
7981 #define MUL_OVERFLOW_TIMETICK_P(a, b) MUL_OVERFLOW_LONG_P(a, b)
7982 #endif
7983 
7984 CONSTFUNC(static timetick_int_t gcd_timetick_int(timetick_int_t, timetick_int_t));
7985 static timetick_int_t
7986 gcd_timetick_int(timetick_int_t a, timetick_int_t b)
7987 {
7988  timetick_int_t t;
7989 
7990  if (a < b) {
7991  t = a;
7992  a = b;
7993  b = t;
7994  }
7995 
7996  while (1) {
7997  t = a % b;
7998  if (t == 0)
7999  return b;
8000  a = b;
8001  b = t;
8002  }
8003 }
8004 
8005 static void
8006 reduce_fraction(timetick_int_t *np, timetick_int_t *dp)
8007 {
8008  timetick_int_t gcd = gcd_timetick_int(*np, *dp);
8009  if (gcd != 1) {
8010  *np /= gcd;
8011  *dp /= gcd;
8012  }
8013 }
8014 
8015 static void
8016 reduce_factors(timetick_int_t *numerators, int num_numerators,
8017  timetick_int_t *denominators, int num_denominators)
8018 {
8019  int i, j;
8020  for (i = 0; i < num_numerators; i++) {
8021  if (numerators[i] == 1)
8022  continue;
8023  for (j = 0; j < num_denominators; j++) {
8024  if (denominators[j] == 1)
8025  continue;
8026  reduce_fraction(&numerators[i], &denominators[j]);
8027  }
8028  }
8029 }
8030 
8031 struct timetick {
8032  timetick_int_t giga_count;
8033  int32_t count; /* 0 .. 999999999 */
8034 };
8035 
8036 static VALUE
8037 timetick2dblnum(struct timetick *ttp,
8038  timetick_int_t *numerators, int num_numerators,
8039  timetick_int_t *denominators, int num_denominators)
8040 {
8041  double d;
8042  int i;
8043 
8044  reduce_factors(numerators, num_numerators,
8045  denominators, num_denominators);
8046 
8047  d = ttp->giga_count * 1e9 + ttp->count;
8048 
8049  for (i = 0; i < num_numerators; i++)
8050  d *= numerators[i];
8051  for (i = 0; i < num_denominators; i++)
8052  d /= denominators[i];
8053 
8054  return DBL2NUM(d);
8055 }
8056 
8057 static VALUE
8058 timetick2dblnum_reciprocal(struct timetick *ttp,
8059  timetick_int_t *numerators, int num_numerators,
8060  timetick_int_t *denominators, int num_denominators)
8061 {
8062  double d;
8063  int i;
8064 
8065  reduce_factors(numerators, num_numerators,
8066  denominators, num_denominators);
8067 
8068  d = 1.0;
8069  for (i = 0; i < num_denominators; i++)
8070  d *= denominators[i];
8071  for (i = 0; i < num_numerators; i++)
8072  d /= numerators[i];
8073  d /= ttp->giga_count * 1e9 + ttp->count;
8074 
8075  return DBL2NUM(d);
8076 }
8077 
8078 #define NDIV(x,y) (-(-((x)+1)/(y))-1)
8079 #define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
8080 
8081 static VALUE
8082 timetick2integer(struct timetick *ttp,
8083  timetick_int_t *numerators, int num_numerators,
8084  timetick_int_t *denominators, int num_denominators)
8085 {
8086  VALUE v;
8087  int i;
8088 
8089  reduce_factors(numerators, num_numerators,
8090  denominators, num_denominators);
8091 
8092  if (!MUL_OVERFLOW_SIGNED_INTEGER_P(1000000000, ttp->giga_count,
8093  TIMETICK_INT_MIN, TIMETICK_INT_MAX-ttp->count)) {
8094  timetick_int_t t = ttp->giga_count * 1000000000 + ttp->count;
8095  for (i = 0; i < num_numerators; i++) {
8096  timetick_int_t factor = numerators[i];
8097  if (MUL_OVERFLOW_TIMETICK_P(factor, t))
8098  goto generic;
8099  t *= factor;
8100  }
8101  for (i = 0; i < num_denominators; i++) {
8102  t = DIV(t, denominators[i]);
8103  }
8104  return TIMETICK_INT2NUM(t);
8105  }
8106 
8107  generic:
8108  v = TIMETICK_INT2NUM(ttp->giga_count);
8109  v = rb_funcall(v, '*', 1, LONG2FIX(1000000000));
8110  v = rb_funcall(v, '+', 1, LONG2FIX(ttp->count));
8111  for (i = 0; i < num_numerators; i++) {
8112  timetick_int_t factor = numerators[i];
8113  if (factor == 1)
8114  continue;
8115  v = rb_funcall(v, '*', 1, TIMETICK_INT2NUM(factor));
8116  }
8117  for (i = 0; i < num_denominators; i++) {
8118  v = rb_funcall(v, '/', 1, TIMETICK_INT2NUM(denominators[i])); /* Ruby's '/' is div. */
8119  }
8120  return v;
8121 }
8122 
8123 static VALUE
8124 make_clock_result(struct timetick *ttp,
8125  timetick_int_t *numerators, int num_numerators,
8126  timetick_int_t *denominators, int num_denominators,
8127  VALUE unit)
8128 {
8129  if (unit == ID2SYM(id_nanosecond)) {
8130  numerators[num_numerators++] = 1000000000;
8131  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
8132  }
8133  else if (unit == ID2SYM(id_microsecond)) {
8134  numerators[num_numerators++] = 1000000;
8135  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
8136  }
8137  else if (unit == ID2SYM(id_millisecond)) {
8138  numerators[num_numerators++] = 1000;
8139  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
8140  }
8141  else if (unit == ID2SYM(id_second)) {
8142  return timetick2integer(ttp, numerators, num_numerators, denominators, num_denominators);
8143  }
8144  else if (unit == ID2SYM(id_float_microsecond)) {
8145  numerators[num_numerators++] = 1000000;
8146  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
8147  }
8148  else if (unit == ID2SYM(id_float_millisecond)) {
8149  numerators[num_numerators++] = 1000;
8150  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
8151  }
8152  else if (NIL_P(unit) || unit == ID2SYM(id_float_second)) {
8153  return timetick2dblnum(ttp, numerators, num_numerators, denominators, num_denominators);
8154  }
8155  else
8156  rb_raise(rb_eArgError, "unexpected unit: %"PRIsVALUE, unit);
8157 }
8158 
8159 #ifdef __APPLE__
8160 static const mach_timebase_info_data_t *
8161 get_mach_timebase_info(void)
8162 {
8163  static mach_timebase_info_data_t sTimebaseInfo;
8164 
8165  if ( sTimebaseInfo.denom == 0 ) {
8166  (void) mach_timebase_info(&sTimebaseInfo);
8167  }
8168 
8169  return &sTimebaseInfo;
8170 }
8171 
8172 double
8173 ruby_real_ms_time(void)
8174 {
8175  const mach_timebase_info_data_t *info = get_mach_timebase_info();
8176  uint64_t t = mach_absolute_time();
8177  return (double)t * info->numer / info->denom / 1e6;
8178 }
8179 #endif
8180 
8181 /*
8182  * call-seq:
8183  * Process.clock_gettime(clock_id [, unit]) -> number
8184  *
8185  * Returns a time returned by POSIX clock_gettime() function.
8186  *
8187  * p Process.clock_gettime(Process::CLOCK_MONOTONIC)
8188  * #=> 896053.968060096
8189  *
8190  * +clock_id+ specifies a kind of clock.
8191  * It is specified as a constant which begins with <code>Process::CLOCK_</code>
8192  * such as Process::CLOCK_REALTIME and Process::CLOCK_MONOTONIC.
8193  *
8194  * The supported constants depends on OS and version.
8195  * Ruby provides following types of +clock_id+ if available.
8196  *
8197  * [CLOCK_REALTIME] SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12, Windows-8/Server-2012
8198  * [CLOCK_MONOTONIC] SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12, Windows-2000
8199  * [CLOCK_PROCESS_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, FreeBSD 9.3, OpenBSD 5.4, macOS 10.12
8200  * [CLOCK_THREAD_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD 5.4, macOS 10.12
8201  * [CLOCK_VIRTUAL] FreeBSD 3.0, OpenBSD 2.1
8202  * [CLOCK_PROF] FreeBSD 3.0, OpenBSD 2.1
8203  * [CLOCK_REALTIME_FAST] FreeBSD 8.1
8204  * [CLOCK_REALTIME_PRECISE] FreeBSD 8.1
8205  * [CLOCK_REALTIME_COARSE] Linux 2.6.32
8206  * [CLOCK_REALTIME_ALARM] Linux 3.0
8207  * [CLOCK_MONOTONIC_FAST] FreeBSD 8.1
8208  * [CLOCK_MONOTONIC_PRECISE] FreeBSD 8.1
8209  * [CLOCK_MONOTONIC_COARSE] Linux 2.6.32
8210  * [CLOCK_MONOTONIC_RAW] Linux 2.6.28, macOS 10.12
8211  * [CLOCK_MONOTONIC_RAW_APPROX] macOS 10.12
8212  * [CLOCK_BOOTTIME] Linux 2.6.39
8213  * [CLOCK_BOOTTIME_ALARM] Linux 3.0
8214  * [CLOCK_UPTIME] FreeBSD 7.0, OpenBSD 5.5
8215  * [CLOCK_UPTIME_FAST] FreeBSD 8.1
8216  * [CLOCK_UPTIME_RAW] macOS 10.12
8217  * [CLOCK_UPTIME_RAW_APPROX] macOS 10.12
8218  * [CLOCK_UPTIME_PRECISE] FreeBSD 8.1
8219  * [CLOCK_SECOND] FreeBSD 8.1
8220  * [CLOCK_TAI] Linux 3.10
8221  *
8222  * Note that SUS stands for Single Unix Specification.
8223  * SUS contains POSIX and clock_gettime is defined in the POSIX part.
8224  * SUS defines CLOCK_REALTIME mandatory but
8225  * CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID are optional.
8226  *
8227  * Also, several symbols are accepted as +clock_id+.
8228  * There are emulations for clock_gettime().
8229  *
8230  * For example, Process::CLOCK_REALTIME is defined as
8231  * +:GETTIMEOFDAY_BASED_CLOCK_REALTIME+ when clock_gettime() is not available.
8232  *
8233  * Emulations for +CLOCK_REALTIME+:
8234  * [:GETTIMEOFDAY_BASED_CLOCK_REALTIME]
8235  * Use gettimeofday() defined by SUS.
8236  * (SUSv4 obsoleted it, though.)
8237  * The resolution is 1 microsecond.
8238  * [:TIME_BASED_CLOCK_REALTIME]
8239  * Use time() defined by ISO C.
8240  * The resolution is 1 second.
8241  *
8242  * Emulations for +CLOCK_MONOTONIC+:
8243  * [:MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC]
8244  * Use mach_absolute_time(), available on Darwin.
8245  * The resolution is CPU dependent.
8246  * [:TIMES_BASED_CLOCK_MONOTONIC]
8247  * Use the result value of times() defined by POSIX.
8248  * POSIX defines it as "times() shall return the elapsed real time, in clock ticks, since an arbitrary point in the past (for example, system start-up time)".
8249  * For example, GNU/Linux returns a value based on jiffies and it is monotonic.
8250  * However, 4.4BSD uses gettimeofday() and it is not monotonic.
8251  * (FreeBSD uses clock_gettime(CLOCK_MONOTONIC) instead, though.)
8252  * The resolution is the clock tick.
8253  * "getconf CLK_TCK" command shows the clock ticks per second.
8254  * (The clock ticks per second is defined by HZ macro in older systems.)
8255  * If it is 100 and clock_t is 32 bits integer type, the resolution is 10 millisecond and
8256  * cannot represent over 497 days.
8257  *
8258  * Emulations for +CLOCK_PROCESS_CPUTIME_ID+:
8259  * [:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID]
8260  * Use getrusage() defined by SUS.
8261  * getrusage() is used with RUSAGE_SELF to obtain the time only for
8262  * the calling process (excluding the time for child processes).
8263  * The result is addition of user time (ru_utime) and system time (ru_stime).
8264  * The resolution is 1 microsecond.
8265  * [:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID]
8266  * Use times() defined by POSIX.
8267  * The result is addition of user time (tms_utime) and system time (tms_stime).
8268  * tms_cutime and tms_cstime are ignored to exclude the time for child processes.
8269  * The resolution is the clock tick.
8270  * "getconf CLK_TCK" command shows the clock ticks per second.
8271  * (The clock ticks per second is defined by HZ macro in older systems.)
8272  * If it is 100, the resolution is 10 millisecond.
8273  * [:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID]
8274  * Use clock() defined by ISO C.
8275  * The resolution is 1/CLOCKS_PER_SEC.
8276  * CLOCKS_PER_SEC is the C-level macro defined by time.h.
8277  * SUS defines CLOCKS_PER_SEC is 1000000.
8278  * Non-Unix systems may define it a different value, though.
8279  * If CLOCKS_PER_SEC is 1000000 as SUS, the resolution is 1 microsecond.
8280  * If CLOCKS_PER_SEC is 1000000 and clock_t is 32 bits integer type, it cannot represent over 72 minutes.
8281  *
8282  * If the given +clock_id+ is not supported, Errno::EINVAL is raised.
8283  *
8284  * +unit+ specifies a type of the return value.
8285  *
8286  * [:float_second] number of seconds as a float (default)
8287  * [:float_millisecond] number of milliseconds as a float
8288  * [:float_microsecond] number of microseconds as a float
8289  * [:second] number of seconds as an integer
8290  * [:millisecond] number of milliseconds as an integer
8291  * [:microsecond] number of microseconds as an integer
8292  * [:nanosecond] number of nanoseconds as an integer
8293  *
8294  * The underlying function, clock_gettime(), returns a number of nanoseconds.
8295  * Float object (IEEE 754 double) is not enough to represent
8296  * the return value for CLOCK_REALTIME.
8297  * If the exact nanoseconds value is required, use +:nanoseconds+ as the +unit+.
8298  *
8299  * The origin (zero) of the returned value varies.
8300  * For example, system start up time, process start up time, the Epoch, etc.
8301  *
8302  * The origin in CLOCK_REALTIME is defined as the Epoch
8303  * (1970-01-01 00:00:00 UTC).
8304  * But some systems count leap seconds and others doesn't.
8305  * So the result can be interpreted differently across systems.
8306  * Time.now is recommended over CLOCK_REALTIME.
8307  */
8308 static VALUE
8309 rb_clock_gettime(int argc, VALUE *argv, VALUE _)
8310 {
8311  int ret;
8312 
8313  struct timetick tt;
8314  timetick_int_t numerators[2];
8315  timetick_int_t denominators[2];
8316  int num_numerators = 0;
8317  int num_denominators = 0;
8318 
8319  VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
8320  VALUE clk_id = argv[0];
8321 
8322  if (SYMBOL_P(clk_id)) {
8323  /*
8324  * Non-clock_gettime clocks are provided by symbol clk_id.
8325  */
8326 #ifdef HAVE_GETTIMEOFDAY
8327  /*
8328  * GETTIMEOFDAY_BASED_CLOCK_REALTIME is used for
8329  * CLOCK_REALTIME if clock_gettime is not available.
8330  */
8331 #define RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME ID2SYM(id_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
8332  if (clk_id == RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME) {
8333  struct timeval tv;
8334  ret = gettimeofday(&tv, 0);
8335  if (ret != 0)
8336  rb_sys_fail("gettimeofday");
8337  tt.giga_count = tv.tv_sec;
8338  tt.count = (int32_t)tv.tv_usec * 1000;
8339  denominators[num_denominators++] = 1000000000;
8340  goto success;
8341  }
8342 #endif
8343 
8344 #define RUBY_TIME_BASED_CLOCK_REALTIME ID2SYM(id_TIME_BASED_CLOCK_REALTIME)
8345  if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
8346  time_t t;
8347  t = time(NULL);
8348  if (t == (time_t)-1)
8349  rb_sys_fail("time");
8350  tt.giga_count = t;
8351  tt.count = 0;
8352  denominators[num_denominators++] = 1000000000;
8353  goto success;
8354  }
8355 
8356 #ifdef HAVE_TIMES
8357 #define RUBY_TIMES_BASED_CLOCK_MONOTONIC \
8358  ID2SYM(id_TIMES_BASED_CLOCK_MONOTONIC)
8359  if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
8360  struct tms buf;
8361  clock_t c;
8362  unsigned_clock_t uc;
8363  c = times(&buf);
8364  if (c == (clock_t)-1)
8365  rb_sys_fail("times");
8366  uc = (unsigned_clock_t)c;
8367  tt.count = (int32_t)(uc % 1000000000);
8368  tt.giga_count = (uc / 1000000000);
8369  denominators[num_denominators++] = get_clk_tck();
8370  goto success;
8371  }
8372 #endif
8373 
8374 #ifdef RUSAGE_SELF
8375 #define RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID \
8376  ID2SYM(id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
8377  if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
8378  struct rusage usage;
8379  int32_t usec;
8380  ret = getrusage(RUSAGE_SELF, &usage);
8381  if (ret != 0)
8382  rb_sys_fail("getrusage");
8383  tt.giga_count = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
8384  usec = (int32_t)(usage.ru_utime.tv_usec + usage.ru_stime.tv_usec);
8385  if (1000000 <= usec) {
8386  tt.giga_count++;
8387  usec -= 1000000;
8388  }
8389  tt.count = usec * 1000;
8390  denominators[num_denominators++] = 1000000000;
8391  goto success;
8392  }
8393 #endif
8394 
8395 #ifdef HAVE_TIMES
8396 #define RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID \
8397  ID2SYM(id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID)
8398  if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
8399  struct tms buf;
8400  unsigned_clock_t utime, stime;
8401  if (times(&buf) == (clock_t)-1)
8402  rb_sys_fail("times");
8403  utime = (unsigned_clock_t)buf.tms_utime;
8404  stime = (unsigned_clock_t)buf.tms_stime;
8405  tt.count = (int32_t)((utime % 1000000000) + (stime % 1000000000));
8406  tt.giga_count = (utime / 1000000000) + (stime / 1000000000);
8407  if (1000000000 <= tt.count) {
8408  tt.count -= 1000000000;
8409  tt.giga_count++;
8410  }
8411  denominators[num_denominators++] = get_clk_tck();
8412  goto success;
8413  }
8414 #endif
8415 
8416 #define RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID \
8417  ID2SYM(id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID)
8418  if (clk_id == RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID) {
8419  clock_t c;
8420  unsigned_clock_t uc;
8421  errno = 0;
8422  c = clock();
8423  if (c == (clock_t)-1)
8424  rb_sys_fail("clock");
8425  uc = (unsigned_clock_t)c;
8426  tt.count = (int32_t)(uc % 1000000000);
8427  tt.giga_count = uc / 1000000000;
8428  denominators[num_denominators++] = CLOCKS_PER_SEC;
8429  goto success;
8430  }
8431 
8432 #ifdef __APPLE__
8433 #define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
8434  if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
8435  const mach_timebase_info_data_t *info = get_mach_timebase_info();
8436  uint64_t t = mach_absolute_time();
8437  tt.count = (int32_t)(t % 1000000000);
8438  tt.giga_count = t / 1000000000;
8439  numerators[num_numerators++] = info->numer;
8440  denominators[num_denominators++] = info->denom;
8441  denominators[num_denominators++] = 1000000000;
8442  goto success;
8443  }
8444 #endif
8445  }
8446  else {
8447 #if defined(HAVE_CLOCK_GETTIME)
8448  struct timespec ts;
8449  clockid_t c;
8450  c = NUM2CLOCKID(clk_id);
8451  ret = clock_gettime(c, &ts);
8452  if (ret == -1)
8453  rb_sys_fail("clock_gettime");
8454  tt.count = (int32_t)ts.tv_nsec;
8455  tt.giga_count = ts.tv_sec;
8456  denominators[num_denominators++] = 1000000000;
8457  goto success;
8458 #endif
8459  }
8460  /* EINVAL emulates clock_gettime behavior when clock_id is invalid. */
8461  rb_syserr_fail(EINVAL, 0);
8462 
8463  success:
8464  return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
8465 }
8466 
8467 /*
8468  * call-seq:
8469  * Process.clock_getres(clock_id [, unit]) -> number
8470  *
8471  * Returns an estimate of the resolution of a +clock_id+ using the POSIX
8472  * <code>clock_getres()</code> function.
8473  *
8474  * Note the reported resolution is often inaccurate on most platforms due to
8475  * underlying bugs for this function and therefore the reported resolution
8476  * often differs from the actual resolution of the clock in practice.
8477  * Inaccurate reported resolutions have been observed for various clocks including
8478  * CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW when using Linux, macOS, BSD or AIX
8479  * platforms, when using ARM processors, or when using virtualization.
8480  *
8481  * +clock_id+ specifies a kind of clock.
8482  * See the document of +Process.clock_gettime+ for details.
8483  * +clock_id+ can be a symbol as for +Process.clock_gettime+.
8484  *
8485  * If the given +clock_id+ is not supported, Errno::EINVAL is raised.
8486  *
8487  * +unit+ specifies the type of the return value.
8488  * +Process.clock_getres+ accepts +unit+ as +Process.clock_gettime+.
8489  * The default value, +:float_second+, is also the same as
8490  * +Process.clock_gettime+.
8491  *
8492  * +Process.clock_getres+ also accepts +:hertz+ as +unit+.
8493  * +:hertz+ means the reciprocal of +:float_second+.
8494  *
8495  * +:hertz+ can be used to obtain the exact value of
8496  * the clock ticks per second for the times() function and
8497  * CLOCKS_PER_SEC for the clock() function.
8498  *
8499  * <code>Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)</code>
8500  * returns the clock ticks per second.
8501  *
8502  * <code>Process.clock_getres(:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)</code>
8503  * returns CLOCKS_PER_SEC.
8504  *
8505  * p Process.clock_getres(Process::CLOCK_MONOTONIC)
8506  * #=> 1.0e-09
8507  *
8508  */
8509 static VALUE
8510 rb_clock_getres(int argc, VALUE *argv, VALUE _)
8511 {
8512  struct timetick tt;
8513  timetick_int_t numerators[2];
8514  timetick_int_t denominators[2];
8515  int num_numerators = 0;
8516  int num_denominators = 0;
8517 
8518  VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
8519  VALUE clk_id = argv[0];
8520 
8521  if (SYMBOL_P(clk_id)) {
8522 #ifdef RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
8523  if (clk_id == RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME) {
8524  tt.giga_count = 0;
8525  tt.count = 1000;
8526  denominators[num_denominators++] = 1000000000;
8527  goto success;
8528  }
8529 #endif
8530 
8531 #ifdef RUBY_TIME_BASED_CLOCK_REALTIME
8532  if (clk_id == RUBY_TIME_BASED_CLOCK_REALTIME) {
8533  tt.giga_count = 1;
8534  tt.count = 0;
8535  denominators[num_denominators++] = 1000000000;
8536  goto success;
8537  }
8538 #endif
8539 
8540 #ifdef RUBY_TIMES_BASED_CLOCK_MONOTONIC
8541  if (clk_id == RUBY_TIMES_BASED_CLOCK_MONOTONIC) {
8542  tt.count = 1;
8543  tt.giga_count = 0;
8544  denominators[num_denominators++] = get_clk_tck();
8545  goto success;
8546  }
8547 #endif
8548 
8549 #ifdef RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
8550  if (clk_id == RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) {
8551  tt.giga_count = 0;
8552  tt.count = 1000;
8553  denominators[num_denominators++] = 1000000000;
8554  goto success;
8555  }
8556 #endif
8557 
8558 #ifdef RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID
8559  if (clk_id == RUBY_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID) {
8560  tt.count = 1;
8561  tt.giga_count = 0;
8562  denominators[num_denominators++] = get_clk_tck();
8563  goto success;
8564  }
8565 #endif
8566 
8567 #ifdef RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID
8568  if (clk_id == RUBY_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID) {
8569  tt.count = 1;
8570  tt.giga_count = 0;
8571  denominators[num_denominators++] = CLOCKS_PER_SEC;
8572  goto success;
8573  }
8574 #endif
8575 
8576 #ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
8577  if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
8578  const mach_timebase_info_data_t *info = get_mach_timebase_info();
8579  tt.count = 1;
8580  tt.giga_count = 0;
8581  numerators[num_numerators++] = info->numer;
8582  denominators[num_denominators++] = info->denom;
8583  denominators[num_denominators++] = 1000000000;
8584  goto success;
8585  }
8586 #endif
8587  }
8588  else {
8589 #if defined(HAVE_CLOCK_GETRES)
8590  struct timespec ts;
8591  clockid_t c = NUM2CLOCKID(clk_id);
8592  int ret = clock_getres(c, &ts);
8593  if (ret == -1)
8594  rb_sys_fail("clock_getres");
8595  tt.count = (int32_t)ts.tv_nsec;
8596  tt.giga_count = ts.tv_sec;
8597  denominators[num_denominators++] = 1000000000;
8598  goto success;
8599 #endif
8600  }
8601  /* EINVAL emulates clock_getres behavior when clock_id is invalid. */
8602  rb_syserr_fail(EINVAL, 0);
8603 
8604  success:
8605  if (unit == ID2SYM(id_hertz)) {
8606  return timetick2dblnum_reciprocal(&tt, numerators, num_numerators, denominators, num_denominators);
8607  }
8608  else {
8609  return make_clock_result(&tt, numerators, num_numerators, denominators, num_denominators, unit);
8610  }
8611 }
8612 
8613 static VALUE
8614 get_CHILD_STATUS(ID _x, VALUE *_y)
8615 {
8616  return rb_last_status_get();
8617 }
8618 
8619 static VALUE
8620 get_PROCESS_ID(ID _x, VALUE *_y)
8621 {
8622  return get_pid();
8623 }
8624 
8625 /*
8626  * call-seq:
8627  * Process.kill(signal, pid, ...) -> integer
8628  *
8629  * Sends the given signal to the specified process id(s) if _pid_ is positive.
8630  * If _pid_ is zero, _signal_ is sent to all processes whose group ID is equal
8631  * to the group ID of the process. If _pid_ is negative, results are dependent
8632  * on the operating system. _signal_ may be an integer signal number or
8633  * a POSIX signal name (either with or without a +SIG+ prefix). If _signal_ is
8634  * negative (or starts with a minus sign), kills process groups instead of
8635  * processes. Not all signals are available on all platforms.
8636  * The keys and values of Signal.list are known signal names and numbers,
8637  * respectively.
8638  *
8639  * pid = fork do
8640  * Signal.trap("HUP") { puts "Ouch!"; exit }
8641  * # ... do some work ...
8642  * end
8643  * # ...
8644  * Process.kill("HUP", pid)
8645  * Process.wait
8646  *
8647  * <em>produces:</em>
8648  *
8649  * Ouch!
8650  *
8651  * If _signal_ is an integer but wrong for signal, Errno::EINVAL or
8652  * RangeError will be raised. Otherwise unless _signal_ is a String
8653  * or a Symbol, and a known signal name, ArgumentError will be
8654  * raised.
8655  *
8656  * Also, Errno::ESRCH or RangeError for invalid _pid_, Errno::EPERM
8657  * when failed because of no privilege, will be raised. In these
8658  * cases, signals may have been sent to preceding processes.
8659  */
8660 
8661 static VALUE
8662 proc_rb_f_kill(int c, const VALUE *v, VALUE _)
8663 {
8664  return rb_f_kill(c, v);
8665 }
8666 
8668 static VALUE rb_mProcUID;
8669 static VALUE rb_mProcGID;
8670 static VALUE rb_mProcID_Syscall;
8671 
8672 
8673 /*
8674  * The Process module is a collection of methods used to
8675  * manipulate processes.
8676  */
8677 
8678 void
8679 InitVM_process(void)
8680 {
8681  rb_define_virtual_variable("$?", get_CHILD_STATUS, 0);
8682  rb_define_virtual_variable("$$", get_PROCESS_ID, 0);
8683 
8684  rb_gvar_ractor_local("$$");
8685  rb_gvar_ractor_local("$?");
8686 
8687  rb_define_global_function("exec", f_exec, -1);
8688  rb_define_global_function("fork", rb_f_fork, 0);
8689  rb_define_global_function("exit!", rb_f_exit_bang, -1);
8690  rb_define_global_function("system", rb_f_system, -1);
8691  rb_define_global_function("spawn", rb_f_spawn, -1);
8692  rb_define_global_function("sleep", rb_f_sleep, -1);
8693  rb_define_global_function("exit", f_exit, -1);
8694  rb_define_global_function("abort", f_abort, -1);
8695 
8696  rb_mProcess = rb_define_module("Process");
8697 
8698 #ifdef WNOHANG
8699  /* see Process.wait */
8700  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
8701 #else
8702  /* see Process.wait */
8703  rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
8704 #endif
8705 #ifdef WUNTRACED
8706  /* see Process.wait */
8707  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
8708 #else
8709  /* see Process.wait */
8710  rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
8711 #endif
8712 
8713  rb_define_singleton_method(rb_mProcess, "exec", f_exec, -1);
8714  rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
8715  rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
8716  rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
8717  rb_define_singleton_method(rb_mProcess, "exit", f_exit, -1);
8718  rb_define_singleton_method(rb_mProcess, "abort", f_abort, -1);
8719  rb_define_singleton_method(rb_mProcess, "last_status", proc_s_last_status, 0);
8720  rb_define_singleton_method(rb_mProcess, "_fork", rb_proc__fork, 0);
8721 
8722  rb_define_module_function(rb_mProcess, "kill", proc_rb_f_kill, -1);
8723  rb_define_module_function(rb_mProcess, "wait", proc_m_wait, -1);
8724  rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
8725  rb_define_module_function(rb_mProcess, "waitpid", proc_m_wait, -1);
8726  rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
8727  rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
8728  rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
8729 
8730  /* :nodoc: */
8731  rb_cWaiter = rb_define_class_under(rb_mProcess, "Waiter", rb_cThread);
8732  rb_undef_alloc_func(rb_cWaiter);
8733  rb_undef_method(CLASS_OF(rb_cWaiter), "new");
8734  rb_define_method(rb_cWaiter, "pid", detach_process_pid, 0);
8735 
8736  rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
8737  rb_define_alloc_func(rb_cProcessStatus, rb_process_status_allocate);
8738  rb_undef_method(CLASS_OF(rb_cProcessStatus), "new");
8739  rb_marshal_define_compat(rb_cProcessStatus, rb_cObject,
8740  process_status_dump, process_status_load);
8741 
8742  rb_define_singleton_method(rb_cProcessStatus, "wait", rb_process_status_waitv, -1);
8743 
8744  rb_define_method(rb_cProcessStatus, "==", pst_equal, 1);
8745  rb_define_method(rb_cProcessStatus, "&", pst_bitand, 1);
8746  rb_define_method(rb_cProcessStatus, ">>", pst_rshift, 1);
8747  rb_define_method(rb_cProcessStatus, "to_i", pst_to_i, 0);
8748  rb_define_method(rb_cProcessStatus, "to_s", pst_to_s, 0);
8749  rb_define_method(rb_cProcessStatus, "inspect", pst_inspect, 0);
8750 
8751  rb_define_method(rb_cProcessStatus, "pid", pst_pid_m, 0);
8752 
8753  rb_define_method(rb_cProcessStatus, "stopped?", pst_wifstopped, 0);
8754  rb_define_method(rb_cProcessStatus, "stopsig", pst_wstopsig, 0);
8755  rb_define_method(rb_cProcessStatus, "signaled?", pst_wifsignaled, 0);
8756  rb_define_method(rb_cProcessStatus, "termsig", pst_wtermsig, 0);
8757  rb_define_method(rb_cProcessStatus, "exited?", pst_wifexited, 0);
8758  rb_define_method(rb_cProcessStatus, "exitstatus", pst_wexitstatus, 0);
8759  rb_define_method(rb_cProcessStatus, "success?", pst_success_p, 0);
8760  rb_define_method(rb_cProcessStatus, "coredump?", pst_wcoredump, 0);
8761 
8762  rb_define_module_function(rb_mProcess, "pid", proc_get_pid, 0);
8763  rb_define_module_function(rb_mProcess, "ppid", proc_get_ppid, 0);
8764 
8765  rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, 0);
8766  rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, 0);
8767  rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
8768  rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
8769 
8770  rb_define_module_function(rb_mProcess, "getsid", proc_getsid, -1);
8771  rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
8772 
8773  rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
8774  rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
8775 
8776 #ifdef HAVE_GETPRIORITY
8777  /* see Process.setpriority */
8778  rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
8779  /* see Process.setpriority */
8780  rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
8781  /* see Process.setpriority */
8782  rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
8783 #endif
8784 
8785  rb_define_module_function(rb_mProcess, "getrlimit", proc_getrlimit, 1);
8786  rb_define_module_function(rb_mProcess, "setrlimit", proc_setrlimit, -1);
8787 #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
8788  {
8789  VALUE inf = RLIM2NUM(RLIM_INFINITY);
8790 #ifdef RLIM_SAVED_MAX
8791  {
8792  VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
8793  /* see Process.setrlimit */
8794  rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
8795  }
8796 #endif
8797  /* see Process.setrlimit */
8798  rb_define_const(rb_mProcess, "RLIM_INFINITY", inf);
8799 #ifdef RLIM_SAVED_CUR
8800  {
8801  VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
8802  /* see Process.setrlimit */
8803  rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
8804  }
8805 #endif
8806  }
8807 #ifdef RLIMIT_AS
8808  /* Maximum size of the process's virtual memory (address space) in bytes.
8809  *
8810  * see the system getrlimit(2) manual for details.
8811  */
8812  rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
8813 #endif
8814 #ifdef RLIMIT_CORE
8815  /* Maximum size of the core file.
8816  *
8817  * see the system getrlimit(2) manual for details.
8818  */
8819  rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
8820 #endif
8821 #ifdef RLIMIT_CPU
8822  /* CPU time limit in seconds.
8823  *
8824  * see the system getrlimit(2) manual for details.
8825  */
8826  rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
8827 #endif
8828 #ifdef RLIMIT_DATA
8829  /* Maximum size of the process's data segment.
8830  *
8831  * see the system getrlimit(2) manual for details.
8832  */
8833  rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
8834 #endif
8835 #ifdef RLIMIT_FSIZE
8836  /* Maximum size of files that the process may create.
8837  *
8838  * see the system getrlimit(2) manual for details.
8839  */
8840  rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
8841 #endif
8842 #ifdef RLIMIT_MEMLOCK
8843  /* Maximum number of bytes of memory that may be locked into RAM.
8844  *
8845  * see the system getrlimit(2) manual for details.
8846  */
8847  rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
8848 #endif
8849 #ifdef RLIMIT_MSGQUEUE
8850  /* Specifies the limit on the number of bytes that can be allocated
8851  * for POSIX message queues for the real user ID of the calling process.
8852  *
8853  * see the system getrlimit(2) manual for details.
8854  */
8855  rb_define_const(rb_mProcess, "RLIMIT_MSGQUEUE", INT2FIX(RLIMIT_MSGQUEUE));
8856 #endif
8857 #ifdef RLIMIT_NICE
8858  /* Specifies a ceiling to which the process's nice value can be raised.
8859  *
8860  * see the system getrlimit(2) manual for details.
8861  */
8862  rb_define_const(rb_mProcess, "RLIMIT_NICE", INT2FIX(RLIMIT_NICE));
8863 #endif
8864 #ifdef RLIMIT_NOFILE
8865  /* Specifies a value one greater than the maximum file descriptor
8866  * number that can be opened by this process.
8867  *
8868  * see the system getrlimit(2) manual for details.
8869  */
8870  rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
8871 #endif
8872 #ifdef RLIMIT_NPROC
8873  /* The maximum number of processes that can be created for the
8874  * real user ID of the calling process.
8875  *
8876  * see the system getrlimit(2) manual for details.
8877  */
8878  rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
8879 #endif
8880 #ifdef RLIMIT_RSS
8881  /* Specifies the limit (in pages) of the process's resident set.
8882  *
8883  * see the system getrlimit(2) manual for details.
8884  */
8885  rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
8886 #endif
8887 #ifdef RLIMIT_RTPRIO
8888  /* Specifies a ceiling on the real-time priority that may be set for this process.
8889  *
8890  * see the system getrlimit(2) manual for details.
8891  */
8892  rb_define_const(rb_mProcess, "RLIMIT_RTPRIO", INT2FIX(RLIMIT_RTPRIO));
8893 #endif
8894 #ifdef RLIMIT_RTTIME
8895  /* Specifies limit on CPU time this process scheduled under a real-time
8896  * scheduling policy can consume.
8897  *
8898  * see the system getrlimit(2) manual for details.
8899  */
8900  rb_define_const(rb_mProcess, "RLIMIT_RTTIME", INT2FIX(RLIMIT_RTTIME));
8901 #endif
8902 #ifdef RLIMIT_SBSIZE
8903  /* Maximum size of the socket buffer.
8904  */
8905  rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
8906 #endif
8907 #ifdef RLIMIT_SIGPENDING
8908  /* Specifies a limit on the number of signals that may be queued for
8909  * the real user ID of the calling process.
8910  *
8911  * see the system getrlimit(2) manual for details.
8912  */
8913  rb_define_const(rb_mProcess, "RLIMIT_SIGPENDING", INT2FIX(RLIMIT_SIGPENDING));
8914 #endif
8915 #ifdef RLIMIT_STACK
8916  /* Maximum size of the stack, in bytes.
8917  *
8918  * see the system getrlimit(2) manual for details.
8919  */
8920  rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
8921 #endif
8922 #endif
8923 
8924  rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
8925  rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
8926  rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
8927  rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
8928  rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
8929  rb_define_module_function(rb_mProcess, "euid=", proc_seteuid_m, 1);
8930  rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
8931  rb_define_module_function(rb_mProcess, "egid=", proc_setegid_m, 1);
8932  rb_define_module_function(rb_mProcess, "initgroups", proc_initgroups, 2);
8933  rb_define_module_function(rb_mProcess, "groups", proc_getgroups, 0);
8934  rb_define_module_function(rb_mProcess, "groups=", proc_setgroups, 1);
8935  rb_define_module_function(rb_mProcess, "maxgroups", proc_getmaxgroups, 0);
8936  rb_define_module_function(rb_mProcess, "maxgroups=", proc_setmaxgroups, 1);
8937 
8938  rb_define_module_function(rb_mProcess, "daemon", proc_daemon, -1);
8939 
8941 
8942 #ifdef CLOCK_REALTIME
8943  /* see Process.clock_gettime */
8944  rb_define_const(rb_mProcess, "CLOCK_REALTIME", CLOCKID2NUM(CLOCK_REALTIME));
8945 #elif defined(RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
8946  /* see Process.clock_gettime */
8947  rb_define_const(rb_mProcess, "CLOCK_REALTIME", RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME);
8948 #endif
8949 #ifdef CLOCK_MONOTONIC
8950  /* see Process.clock_gettime */
8951  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", CLOCKID2NUM(CLOCK_MONOTONIC));
8952 #elif defined(RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
8953  /* see Process.clock_gettime */
8954  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC);
8955 #endif
8956 #ifdef CLOCK_PROCESS_CPUTIME_ID
8957  /* see Process.clock_gettime */
8958  rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", CLOCKID2NUM(CLOCK_PROCESS_CPUTIME_ID));
8959 #elif defined(RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
8960  /* see Process.clock_gettime */
8961  rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID);
8962 #endif
8963 #ifdef CLOCK_THREAD_CPUTIME_ID
8964  /* see Process.clock_gettime */
8965  rb_define_const(rb_mProcess, "CLOCK_THREAD_CPUTIME_ID", CLOCKID2NUM(CLOCK_THREAD_CPUTIME_ID));
8966 #endif
8967 #ifdef CLOCK_VIRTUAL
8968  /* see Process.clock_gettime */
8969  rb_define_const(rb_mProcess, "CLOCK_VIRTUAL", CLOCKID2NUM(CLOCK_VIRTUAL));
8970 #endif
8971 #ifdef CLOCK_PROF
8972  /* see Process.clock_gettime */
8973  rb_define_const(rb_mProcess, "CLOCK_PROF", CLOCKID2NUM(CLOCK_PROF));
8974 #endif
8975 #ifdef CLOCK_REALTIME_FAST
8976  /* see Process.clock_gettime */
8977  rb_define_const(rb_mProcess, "CLOCK_REALTIME_FAST", CLOCKID2NUM(CLOCK_REALTIME_FAST));
8978 #endif
8979 #ifdef CLOCK_REALTIME_PRECISE
8980  /* see Process.clock_gettime */
8981  rb_define_const(rb_mProcess, "CLOCK_REALTIME_PRECISE", CLOCKID2NUM(CLOCK_REALTIME_PRECISE));
8982 #endif
8983 #ifdef CLOCK_REALTIME_COARSE
8984  /* see Process.clock_gettime */
8985  rb_define_const(rb_mProcess, "CLOCK_REALTIME_COARSE", CLOCKID2NUM(CLOCK_REALTIME_COARSE));
8986 #endif
8987 #ifdef CLOCK_REALTIME_ALARM
8988  /* see Process.clock_gettime */
8989  rb_define_const(rb_mProcess, "CLOCK_REALTIME_ALARM", CLOCKID2NUM(CLOCK_REALTIME_ALARM));
8990 #endif
8991 #ifdef CLOCK_MONOTONIC_FAST
8992  /* see Process.clock_gettime */
8993  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_FAST", CLOCKID2NUM(CLOCK_MONOTONIC_FAST));
8994 #endif
8995 #ifdef CLOCK_MONOTONIC_PRECISE
8996  /* see Process.clock_gettime */
8997  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_PRECISE", CLOCKID2NUM(CLOCK_MONOTONIC_PRECISE));
8998 #endif
8999 #ifdef CLOCK_MONOTONIC_RAW
9000  /* see Process.clock_gettime */
9001  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_RAW", CLOCKID2NUM(CLOCK_MONOTONIC_RAW));
9002 #endif
9003 #ifdef CLOCK_MONOTONIC_RAW_APPROX
9004  /* see Process.clock_gettime */
9005  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_RAW_APPROX", CLOCKID2NUM(CLOCK_MONOTONIC_RAW_APPROX));
9006 #endif
9007 #ifdef CLOCK_MONOTONIC_COARSE
9008  /* see Process.clock_gettime */
9009  rb_define_const(rb_mProcess, "CLOCK_MONOTONIC_COARSE", CLOCKID2NUM(CLOCK_MONOTONIC_COARSE));
9010 #endif
9011 #ifdef CLOCK_BOOTTIME
9012  /* see Process.clock_gettime */
9013  rb_define_const(rb_mProcess, "CLOCK_BOOTTIME", CLOCKID2NUM(CLOCK_BOOTTIME));
9014 #endif
9015 #ifdef CLOCK_BOOTTIME_ALARM
9016  /* see Process.clock_gettime */
9017  rb_define_const(rb_mProcess, "CLOCK_BOOTTIME_ALARM", CLOCKID2NUM(CLOCK_BOOTTIME_ALARM));
9018 #endif
9019 #ifdef CLOCK_UPTIME
9020  /* see Process.clock_gettime */
9021  rb_define_const(rb_mProcess, "CLOCK_UPTIME", CLOCKID2NUM(CLOCK_UPTIME));
9022 #endif
9023 #ifdef CLOCK_UPTIME_FAST
9024  /* see Process.clock_gettime */
9025  rb_define_const(rb_mProcess, "CLOCK_UPTIME_FAST", CLOCKID2NUM(CLOCK_UPTIME_FAST));
9026 #endif
9027 #ifdef CLOCK_UPTIME_PRECISE
9028  /* see Process.clock_gettime */
9029  rb_define_const(rb_mProcess, "CLOCK_UPTIME_PRECISE", CLOCKID2NUM(CLOCK_UPTIME_PRECISE));
9030 #endif
9031 #ifdef CLOCK_UPTIME_RAW
9032  /* see Process.clock_gettime */
9033  rb_define_const(rb_mProcess, "CLOCK_UPTIME_RAW", CLOCKID2NUM(CLOCK_UPTIME_RAW));
9034 #endif
9035 #ifdef CLOCK_UPTIME_RAW_APPROX
9036  /* see Process.clock_gettime */
9037  rb_define_const(rb_mProcess, "CLOCK_UPTIME_RAW_APPROX", CLOCKID2NUM(CLOCK_UPTIME_RAW_APPROX));
9038 #endif
9039 #ifdef CLOCK_SECOND
9040  /* see Process.clock_gettime */
9041  rb_define_const(rb_mProcess, "CLOCK_SECOND", CLOCKID2NUM(CLOCK_SECOND));
9042 #endif
9043 #ifdef CLOCK_TAI
9044  /* see Process.clock_gettime */
9045  rb_define_const(rb_mProcess, "CLOCK_TAI", CLOCKID2NUM(CLOCK_TAI));
9046 #endif
9047  rb_define_module_function(rb_mProcess, "clock_gettime", rb_clock_gettime, -1);
9048  rb_define_module_function(rb_mProcess, "clock_getres", rb_clock_getres, -1);
9049 
9050 #if defined(HAVE_TIMES) || defined(_WIN32)
9051  /* Placeholder for rusage */
9052  rb_cProcessTms = rb_struct_define_under(rb_mProcess, "Tms", "utime", "stime", "cutime", "cstime", NULL);
9053 #endif
9054 
9055  SAVED_USER_ID = geteuid();
9056  SAVED_GROUP_ID = getegid();
9057 
9058  rb_mProcUID = rb_define_module_under(rb_mProcess, "UID");
9059  rb_mProcGID = rb_define_module_under(rb_mProcess, "GID");
9060 
9061  rb_define_module_function(rb_mProcUID, "rid", proc_getuid, 0);
9062  rb_define_module_function(rb_mProcGID, "rid", proc_getgid, 0);
9063  rb_define_module_function(rb_mProcUID, "eid", proc_geteuid, 0);
9064  rb_define_module_function(rb_mProcGID, "eid", proc_getegid, 0);
9065  rb_define_module_function(rb_mProcUID, "change_privilege", p_uid_change_privilege, 1);
9066  rb_define_module_function(rb_mProcGID, "change_privilege", p_gid_change_privilege, 1);
9067  rb_define_module_function(rb_mProcUID, "grant_privilege", p_uid_grant_privilege, 1);
9068  rb_define_module_function(rb_mProcGID, "grant_privilege", p_gid_grant_privilege, 1);
9069  rb_define_alias(rb_singleton_class(rb_mProcUID), "eid=", "grant_privilege");
9070  rb_define_alias(rb_singleton_class(rb_mProcGID), "eid=", "grant_privilege");
9071  rb_define_module_function(rb_mProcUID, "re_exchange", p_uid_exchange, 0);
9072  rb_define_module_function(rb_mProcGID, "re_exchange", p_gid_exchange, 0);
9073  rb_define_module_function(rb_mProcUID, "re_exchangeable?", p_uid_exchangeable, 0);
9074  rb_define_module_function(rb_mProcGID, "re_exchangeable?", p_gid_exchangeable, 0);
9075  rb_define_module_function(rb_mProcUID, "sid_available?", p_uid_have_saved_id, 0);
9076  rb_define_module_function(rb_mProcGID, "sid_available?", p_gid_have_saved_id, 0);
9077  rb_define_module_function(rb_mProcUID, "switch", p_uid_switch, 0);
9078  rb_define_module_function(rb_mProcGID, "switch", p_gid_switch, 0);
9079 #ifdef p_uid_from_name
9080  rb_define_module_function(rb_mProcUID, "from_name", p_uid_from_name, 1);
9081 #endif
9082 #ifdef p_gid_from_name
9083  rb_define_module_function(rb_mProcGID, "from_name", p_gid_from_name, 1);
9084 #endif
9085 
9086  rb_mProcID_Syscall = rb_define_module_under(rb_mProcess, "Sys");
9087 
9088  rb_define_module_function(rb_mProcID_Syscall, "getuid", proc_getuid, 0);
9089  rb_define_module_function(rb_mProcID_Syscall, "geteuid", proc_geteuid, 0);
9090  rb_define_module_function(rb_mProcID_Syscall, "getgid", proc_getgid, 0);
9091  rb_define_module_function(rb_mProcID_Syscall, "getegid", proc_getegid, 0);
9092 
9093  rb_define_module_function(rb_mProcID_Syscall, "setuid", p_sys_setuid, 1);
9094  rb_define_module_function(rb_mProcID_Syscall, "setgid", p_sys_setgid, 1);
9095 
9096  rb_define_module_function(rb_mProcID_Syscall, "setruid", p_sys_setruid, 1);
9097  rb_define_module_function(rb_mProcID_Syscall, "setrgid", p_sys_setrgid, 1);
9098 
9099  rb_define_module_function(rb_mProcID_Syscall, "seteuid", p_sys_seteuid, 1);
9100  rb_define_module_function(rb_mProcID_Syscall, "setegid", p_sys_setegid, 1);
9101 
9102  rb_define_module_function(rb_mProcID_Syscall, "setreuid", p_sys_setreuid, 2);
9103  rb_define_module_function(rb_mProcID_Syscall, "setregid", p_sys_setregid, 2);
9104 
9105  rb_define_module_function(rb_mProcID_Syscall, "setresuid", p_sys_setresuid, 3);
9106  rb_define_module_function(rb_mProcID_Syscall, "setresgid", p_sys_setresgid, 3);
9107  rb_define_module_function(rb_mProcID_Syscall, "issetugid", p_sys_issetugid, 0);
9108 }
9109 
9110 void
9111 Init_process(void)
9112 {
9113  id_in = rb_intern_const("in");
9114  id_out = rb_intern_const("out");
9115  id_err = rb_intern_const("err");
9116  id_pid = rb_intern_const("pid");
9117  id_uid = rb_intern_const("uid");
9118  id_gid = rb_intern_const("gid");
9119  id_close = rb_intern_const("close");
9120  id_child = rb_intern_const("child");
9121 #ifdef HAVE_SETPGID
9122  id_pgroup = rb_intern_const("pgroup");
9123 #endif
9124 #ifdef _WIN32
9125  id_new_pgroup = rb_intern_const("new_pgroup");
9126 #endif
9127  id_unsetenv_others = rb_intern_const("unsetenv_others");
9128  id_chdir = rb_intern_const("chdir");
9129  id_umask = rb_intern_const("umask");
9130  id_close_others = rb_intern_const("close_others");
9131  id_nanosecond = rb_intern_const("nanosecond");
9132  id_microsecond = rb_intern_const("microsecond");
9133  id_millisecond = rb_intern_const("millisecond");
9134  id_second = rb_intern_const("second");
9135  id_float_microsecond = rb_intern_const("float_microsecond");
9136  id_float_millisecond = rb_intern_const("float_millisecond");
9137  id_float_second = rb_intern_const("float_second");
9138  id_GETTIMEOFDAY_BASED_CLOCK_REALTIME = rb_intern_const("GETTIMEOFDAY_BASED_CLOCK_REALTIME");
9139  id_TIME_BASED_CLOCK_REALTIME = rb_intern_const("TIME_BASED_CLOCK_REALTIME");
9140 #ifdef HAVE_TIMES
9141  id_TIMES_BASED_CLOCK_MONOTONIC = rb_intern_const("TIMES_BASED_CLOCK_MONOTONIC");
9142  id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID");
9143 #endif
9144 #ifdef RUSAGE_SELF
9145  id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID");
9146 #endif
9147  id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID");
9148 #ifdef __APPLE__
9149  id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC = rb_intern_const("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC");
9150 #endif
9151  id_hertz = rb_intern_const("hertz");
9152 
9153  InitVM(process);
9154 }
#define LONG_LONG
Definition: long_long.h:38
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition: cxxanyargs.hpp:685
#define PATH_ENV
Definition: dosish.h:63
#define GIDT2NUM
Converts a C's gid_t into an instance of rb_cInteger.
Definition: gid_t.h:28
#define NUM2GIDT
Converts an instance of rb_cNumeric into C's gid_t.
Definition: gid_t.h:33
VALUE rb_singleton_class(VALUE obj)
Finds or creates the singleton class of the passed object.
Definition: class.c:2068
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:869
VALUE rb_define_module(const char *name)
Defines a top-level module.
Definition: class.c:948
VALUE rb_define_module_under(VALUE outer, const char *name)
Defines a module under the namespace of outer.
Definition: class.c:972
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:2116
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for a module.
Definition: class.c:2100
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
Definition: class.c:1938
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
Definition: class.c:1914
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:854
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:2110
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition: string.h:1738
#define TYPE(_)
Old name of rb_type.
Definition: value_type.h:107
#define T_FILE
Old name of RUBY_T_FILE.
Definition: value_type.h:62
#define T_STRING
Old name of RUBY_T_STRING.
Definition: value_type.h:78
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition: long.h:48
#define ISUPPER
Old name of rb_isupper.
Definition: ctype.h:89
#define ID2SYM
Old name of RB_ID2SYM.
Definition: symbol.h:44
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition: value_type.h:57
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition: value_type.h:63
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition: assume.h:31
#define CLASS_OF
Old name of rb_class_of.
Definition: globals.h:203
#define LONG2FIX
Old name of RB_INT2FIX.
Definition: long.h:49
#define FIX2INT
Old name of RB_FIX2INT.
Definition: int.h:41
#define TOUPPER
Old name of rb_toupper.
Definition: ctype.h:100
#define NUM2UINT
Old name of RB_NUM2UINT.
Definition: int.h:45
#define ISLOWER
Old name of rb_islower.
Definition: ctype.h:90
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition: array.h:652
#define Qtrue
Old name of RUBY_Qtrue.
#define NUM2INT
Old name of RB_NUM2INT.
Definition: int.h:44
#define INT2NUM
Old name of RB_INT2NUM.
Definition: int.h:43
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition: value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition: memory.h:399
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
Definition: value_type.h:80
#define DBL2NUM
Old name of rb_float_new.
Definition: double.h:29
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition: memory.h:400
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition: value_type.h:88
void ruby_stop(int ex)
Calls ruby_cleanup() and exits the process.
Definition: eval.c:289
void rb_notimplement(void)
Definition: error.c:3068
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead of returning false.
Definition: error.c:1066
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3025
VALUE rb_eNotImpError
NotImplementedError exception.
Definition: error.c:1109
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:675
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
Definition: error.c:3137
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:802
VALUE rb_eSystemExit
SystemExit exception.
Definition: error.c:1092
void rb_sys_fail(const char *mesg)
Converts a C errno into a Ruby exception, then raises it.
Definition: error.c:3149
void rb_syserr_fail_str(int e, VALUE mesg)
Identical to rb_syserr_fail(), except it takes the message in Ruby's String instead of C's.
Definition: error.c:3143
VALUE rb_eRuntimeError
RuntimeError exception.
Definition: error.c:1097
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
Definition: error.c:418
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of C's.
Definition: error.c:1150
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1100
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:983
void rb_sys_fail_str(VALUE mesg)
Identical to rb_sys_fail(), except it takes the message in Ruby's String instead of C's.
Definition: error.c:3155
void rb_exit(int status)
Terminates the current execution context.
Definition: process.c:4471
VALUE rb_mProcess
Process module.
Definition: process.c:8667
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
Definition: object.c:1950
VALUE rb_cThread
Thread class.
Definition: vm.c:397
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition: object.c:120
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition: object.c:1161
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition: object.c:2998
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition: rgengc.h:232
void rb_enc_copy(VALUE dst, VALUE src)
Destructively copies the encoding of the latter object to that of former one.
Definition: encoding.c:1192
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition: vm_eval.c:1102
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
Definition: array.c:2663
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
Definition: array.c:989
VALUE rb_ary_new(void)
Allocates a new, empty array.
Definition: array.c:750
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
Definition: array.c:1308
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
Definition: array.c:1679
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
Definition: array.c:976
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
Definition: array.c:1148
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition: error.h:35
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition: error.h:294
VALUE rb_f_abort(int argc, const VALUE *argv)
This is similar to rb_f_exit().
Definition: process.c:4549
VALUE rb_f_exit(int argc, const VALUE *argv)
Identical to rb_exit(), except how arguments are passed.
Definition: process.c:4484
void rb_jump_tag(int state)
This function is to re-throw global escapes.
Definition: eval.c:845
VALUE rb_str_encode_ospath(VALUE path)
Converts a string into an "OS Path" encoding, if any.
Definition: file.c:251
void rb_gc_mark(VALUE obj)
Marks an object.
Definition: gc.c:6775
int rb_during_gc(void)
Queries if the GC is busy.
Definition: gc.c:10301
void rb_gc(void)
Triggers a GC process.
Definition: gc.c:10293
VALUE rb_check_hash_type(VALUE obj)
Try converting an object to its hash representation using its to_hash method, if any.
Definition: hash.c:1896
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
Definition: hash.c:2903
VALUE rb_env_clear(void)
Destructively removes every environment variables of the running process.
Definition: hash.c:5888
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Identical to rb_hash_aref(), except it always returns RUBY_Qnil for misshits.
Definition: hash.c:2108
VALUE rb_hash_new(void)
Creates a new, empty hash object.
Definition: hash.c:1529
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io)
Iterates over the passed array to apply rb_io_write() individually.
Definition: io.c:8208
int rb_cloexec_dup2(int oldfd, int newfd)
Identical to rb_cloexec_dup(), except you can specify the destination file descriptor.
Definition: io.c:360
void rb_update_max_fd(int fd)
Informs the interpreter that the passed fd can be the max.
Definition: io.c:234
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Opens a file that closes on exec.
Definition: io.c:314
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
Closes everything.
int rb_reserved_fd_p(int fd)
Queries if the given FD is reserved or not.
int rb_pipe(int *pipes)
This is an rb_cloexec_pipe() + rb_update_max_fd() combo.
Definition: io.c:6792
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Duplicates a file descriptor with closing on exec.
Definition: io.c:447
int rb_cloexec_dup(int oldfd)
Identical to rb_cloexec_fcntl_dupfd(), except it implies minfd is 3.
Definition: io.c:353
VALUE rb_protect(VALUE(*func)(VALUE args), VALUE args, int *state)
Protects a function call from potential global escapes from the function.
int rb_proc_exec(const char *cmd)
Executes a shell command.
Definition: process.c:1874
VALUE rb_proc_times(VALUE _)
Gathers info about resources consumed by the current process.
VALUE rb_last_status_get(void)
Queries the "last status", or the $?.
Definition: process.c:599
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Waits for a process, with releasing GVL.
Definition: process.c:1426
rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errbuf, size_t buflen)
Identical to rb_spawn(), except you can additionally know the detailed situation in case of abnormal ...
Definition: process.c:4725
void rb_syswait(rb_pid_t pid)
This is a shorthand of rb_waitpid without status and flags.
Definition: process.c:4594
VALUE rb_f_exec(int argc, const VALUE *argv)
Replaces the current process by running the given external command.
Definition: process.c:3091
rb_pid_t rb_spawn(int argc, const VALUE *argv)
Identical to rb_f_exec(), except it spawns a child process instead of replacing the current one.
Definition: process.c:4731
void rb_last_status_set(int status, rb_pid_t pid)
Sets the "last status", or the $?.
Definition: process.c:663
VALUE rb_detach_process(rb_pid_t pid)
"Detaches" a subprocess.
Definition: process.c:1629
const char * ruby_signal_name(int signo)
Queries the name of the signal.
Definition: signal.c:316
VALUE rb_f_kill(int argc, const VALUE *argv)
Sends a signal ("kills") to processes.
Definition: signal.c:423
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
Definition: string.c:3317
VALUE rb_str_tmp_new(long len)
Allocates a "temporary" string.
Definition: string.c:1540
VALUE rb_str_subseq(VALUE str, long beg, long len)
Identical to rb_str_substr(), except the numbers are interpreted as byte offsets instead of character...
Definition: string.c:2821
VALUE rb_str_buf_cat(VALUE, const char *, long)
Just another name of rb_str_cat.
size_t rb_str_capacity(VALUE str)
Queries the capacity of the given string.
Definition: string.c:828
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
Definition: string.c:1356
VALUE rb_str_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
Definition: string.c:1808
VALUE rb_str_buf_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition: string.c:3039
VALUE rb_str_new(const char *ptr, long len)
Allocates an instance of rb_cString.
Definition: string.c:918
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition: string.c:2659
VALUE rb_str_new_cstr(const char *ptr)
Identical to rb_str_new(), except it assumes the passed pointer is a pointer to a C string.
Definition: string.c:952
VALUE rb_str_resize(VALUE str, long len)
Overwrites the length of the string.
Definition: string.c:3056
void rb_str_modify_expand(VALUE str, long capa)
Identical to rb_str_modify(), except it additionally expands the capacity of the receiver.
Definition: string.c:2467
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition: string.c:1506
VALUE rb_str_cat_cstr(VALUE dst, const char *src)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
Definition: string.c:3171
VALUE rb_struct_define_under(VALUE space, const char *name,...)
Identical to rb_struct_define(), except it defines the class under the specified namespace instead of...
Definition: struct.c:450
VALUE rb_struct_new(VALUE klass,...)
Creates an instance of the given struct.
Definition: struct.c:795
VALUE rb_thread_local_aref(VALUE thread, ID key)
This badly named function reads from a Fiber local storage.
Definition: thread.c:3493
#define RUBY_UBF_IO
A special UBF for blocking IO operations.
Definition: thread.h:382
void rb_thread_sleep_forever(void)
Blocks indefinitely.
Definition: thread.c:1519
void rb_thread_wait_for(struct timeval time)
Identical to rb_thread_sleep(), except it takes struct timeval instead.
Definition: thread.c:1558
VALUE rb_thread_create(VALUE(*f)(void *g), void *g)
Creates a Ruby thread that is backended by a C function.
void rb_thread_check_ints(void)
Checks for interrupts.
Definition: thread.c:1573
void rb_thread_atfork(void)
A pthread_atfork(3posix)-like API.
Definition: thread.c:4800
VALUE rb_thread_local_aset(VALUE thread, ID key, VALUE val)
This badly named function writes to a Fiber local storage.
Definition: thread.c:3641
#define RUBY_UBF_PROCESS
A special UBF for blocking process operations.
Definition: thread.h:389
void rb_thread_sleep(int sec)
Blocks for the given period of time.
Definition: thread.c:1596
struct timeval rb_time_interval(VALUE num)
Creates a "time interval".
Definition: time.c:2656
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition: variable.c:1293
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition: variable.c:1575
void rb_undef_alloc_func(VALUE klass)
Deletes the allocator function of a class.
Definition: vm_method.c:1117
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition: symbol.h:276
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
Definition: symbol.c:1066
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
Definition: symbol.c:782
VALUE rb_sym2str(VALUE id)
Identical to rb_id2str(), except it takes an instance of rb_cSymbol rather than an ID.
Definition: symbol.c:924
void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Defines a global variable that is purely function-backended.
Definition: variable.c:594
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
Definition: variable.c:3253
int rb_io_modestr_oflags(const char *modestr)
Identical to rb_io_modestr_fmode(), except it returns a mixture of O_ flags.
Definition: io.c:6006
#define GetOpenFile
This is an old name of RB_IO_POINTER.
Definition: io.h:343
VALUE rb_io_check_io(VALUE io)
Try converting an object to its IO representation using its to_io method, if any.
Definition: io.c:807
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Identical to rb_thread_call_without_gvl(), except it does not interface with signals etc.
Definition: thread.c:1797
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Allows the passed function to run in parallel with other Ruby threads.
void ruby_setenv(const char *key, const char *val)
Sets an environment variable.
Definition: hash.c:5134
#define RB_NUM2INT
Just another name of rb_num2int_inline.
Definition: int.h:38
#define RB_INT2NUM
Just another name of rb_int2num_inline.
Definition: int.h:37
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
Definition: sprintf.c:1201
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
Definition: sprintf.c:1241
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition: iterator.h:58
VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2)
Identical to rb_funcallv(), except it additionally passes a function as a block.
Definition: vm_eval.c:1595
VALUE rb_yield(VALUE val)
Yields the block.
Definition: vm_eval.c:1357
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Marshal format compatibility layer.
Definition: marshal.c:148
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition: memory.h:366
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
Definition: memory.h:354
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition: memory.h:161
#define NUM2MODET
Converts a C's mode_t into an instance of rb_cInteger.
Definition: mode_t.h:28
#define PIDT2NUM
Converts a C's pid_t into an instance of rb_cInteger.
Definition: pid_t.h:28
#define NUM2PIDT
Converts an instance of rb_cNumeric into C's pid_t.
Definition: pid_t.h:33
VALUE rb_ractor_stderr(void)
Queries the standard error of the current Ractor that is calling this function.
Definition: ractor.c:2146
#define RARRAY_LEN
Just another name of rb_array_len.
Definition: rarray.h:68
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition: rarray.h:324
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
Definition: rarray.h:571
#define RARRAY_AREF(a, i)
Definition: rarray.h:588
#define DATA_PTR(obj)
Convenient getter macro.
Definition: rdata.h:71
#define RUBY_DEFAULT_FREE
This is a value you can set to RData::dfree.
Definition: rdata.h:82
#define RHASH_SIZE(h)
Queries the size of the hash.
Definition: rhash.h:82
#define RHASH_EMPTY_P(h)
Checks if the hash is empty.
Definition: rhash.h:92
#define SafeStringValue(v)
Definition: rstring.h:104
#define StringValue(v)
Ensures that the parameter object is a String.
Definition: rstring.h:72
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition: rstring.h:497
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
Definition: rstring.h:483
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
Definition: rstring.h:95
#define RTYPEDDATA_DATA(v)
Convenient getter macro.
Definition: rtypeddata.h:102
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
Definition: rtypeddata.h:79
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
Definition: rtypeddata.h:507
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
Definition: rtypeddata.h:489
const char * rb_class2name(VALUE klass)
Queries the name of the passed class.
Definition: variable.c:300
#define FilePathValue(v)
Ensures that the parameter object is a path.
Definition: ruby.h:90
#define InitVM(ext)
This macro is for internal use.
Definition: ruby.h:229
Scheduler APIs.
VALUE rb_fiber_scheduler_current(void)
Identical to rb_fiber_scheduler_get(), except it also returns RUBY_Qnil in case of a blocking fiber.
Definition: scheduler.c:126
VALUE rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE *argv)
Identical to rb_fiber_scheduler_kernel_sleep(), except it can pass multiple arguments.
Definition: scheduler.c:169
VALUE rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags)
Nonblocking waitpid.
Definition: scheduler.c:193
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
#define RTEST
This is an old name of RB_TEST.
Defines old _.
#define _(args)
This was a transition path from K&R to ANSI.
Definition: stdarg.h:35
This is the struct that holds necessary info for a struct.
Definition: rtypeddata.h:190
const char * wrap_struct_name
Name of structs of this kind.
Definition: rtypeddata.h:197
Ruby's IO, metadata and buffers.
Definition: io.h:95
int fd
file descriptor.
Definition: io.h:104
VALUE tied_io_for_writing
Duplex IO object, if set.
Definition: io.h:135
Definition: st.h:79
Definition: win32.h:696
void rb_native_mutex_lock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_lock.
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_unlock.
void rb_native_cond_signal(rb_nativethread_cond_t *cond)
Signals a condition variable.
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
Waits for the passed condition variable to be signalled.
#define UIDT2NUM
Converts a C's uid_t into an instance of rb_cInteger.
Definition: uid_t.h:28
#define NUM2UIDT
Converts an instance of rb_cNumeric into C's uid_t.
Definition: uid_t.h:33
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition: value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
static enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj)
Queries the type of the object.
Definition: value_type.h:181
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition: value_type.h:432
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition: value_type.h:375
void * ruby_xmalloc(size_t size)
Allocates a storage instance.
Definition: gc.c:13704