PageRenderTime 44ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/process.c

https://github.com/vuxuandung/ruby
C | 6877 lines | 4638 code | 699 blank | 1540 comment | 1142 complexity | 669245bc685590d49ec357675d92d3c9 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0, 0BSD
  1. /**********************************************************************
  2. process.c -
  3. $Author$
  4. created at: Tue Aug 10 14:30:50 JST 1993
  5. Copyright (C) 1993-2007 Yukihiro Matsumoto
  6. Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
  7. Copyright (C) 2000 Information-technology Promotion Agency, Japan
  8. **********************************************************************/
  9. #include "ruby/ruby.h"
  10. #include "ruby/io.h"
  11. #include "ruby/thread.h"
  12. #include "ruby/util.h"
  13. #include "internal.h"
  14. #include "vm_core.h"
  15. #include <stdio.h>
  16. #include <errno.h>
  17. #include <signal.h>
  18. #ifdef HAVE_STDLIB_H
  19. #include <stdlib.h>
  20. #endif
  21. #ifdef HAVE_UNISTD_H
  22. #include <unistd.h>
  23. #endif
  24. #ifdef HAVE_FCNTL_H
  25. #include <fcntl.h>
  26. #endif
  27. #ifdef HAVE_PROCESS_H
  28. #include <process.h>
  29. #endif
  30. #include <time.h>
  31. #include <ctype.h>
  32. #ifndef EXIT_SUCCESS
  33. #define EXIT_SUCCESS 0
  34. #endif
  35. #ifndef EXIT_FAILURE
  36. #define EXIT_FAILURE 1
  37. #endif
  38. #ifdef HAVE_SYS_WAIT_H
  39. # include <sys/wait.h>
  40. #endif
  41. #ifdef HAVE_SYS_RESOURCE_H
  42. # include <sys/resource.h>
  43. #endif
  44. #ifdef HAVE_SYS_PARAM_H
  45. # include <sys/param.h>
  46. #endif
  47. #ifndef MAXPATHLEN
  48. # define MAXPATHLEN 1024
  49. #endif
  50. #include "ruby/st.h"
  51. #ifdef __EMX__
  52. #undef HAVE_GETPGRP
  53. #endif
  54. #include <sys/stat.h>
  55. #if defined(__native_client__) && defined(NACL_NEWLIB)
  56. # include "nacl/stat.h"
  57. # include "nacl/unistd.h"
  58. #endif
  59. #ifdef HAVE_SYS_TIMES_H
  60. #include <sys/times.h>
  61. #endif
  62. #ifdef HAVE_PWD_H
  63. #include <pwd.h>
  64. #endif
  65. #ifdef HAVE_GRP_H
  66. #include <grp.h>
  67. #endif
  68. #define numberof(array) (int)(sizeof(array)/sizeof((array)[0]))
  69. #if defined(HAVE_TIMES) || defined(_WIN32)
  70. static VALUE rb_cProcessTms;
  71. #endif
  72. #ifndef WIFEXITED
  73. #define WIFEXITED(w) (((w) & 0xff) == 0)
  74. #endif
  75. #ifndef WIFSIGNALED
  76. #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
  77. #endif
  78. #ifndef WIFSTOPPED
  79. #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
  80. #endif
  81. #ifndef WEXITSTATUS
  82. #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
  83. #endif
  84. #ifndef WTERMSIG
  85. #define WTERMSIG(w) ((w) & 0x7f)
  86. #endif
  87. #ifndef WSTOPSIG
  88. #define WSTOPSIG WEXITSTATUS
  89. #endif
  90. #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
  91. #define HAVE_44BSD_SETUID 1
  92. #define HAVE_44BSD_SETGID 1
  93. #endif
  94. #ifdef __NetBSD__
  95. #undef HAVE_SETRUID
  96. #undef HAVE_SETRGID
  97. #endif
  98. #ifdef BROKEN_SETREUID
  99. #define setreuid ruby_setreuid
  100. int setreuid(rb_uid_t ruid, rb_uid_t euid);
  101. #endif
  102. #ifdef BROKEN_SETREGID
  103. #define setregid ruby_setregid
  104. int setregid(rb_gid_t rgid, rb_gid_t egid);
  105. #endif
  106. #if defined(HAVE_44BSD_SETUID) || defined(__APPLE__)
  107. #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
  108. #define OBSOLETE_SETREUID 1
  109. #endif
  110. #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
  111. #define OBSOLETE_SETREGID 1
  112. #endif
  113. #endif
  114. #define preserving_errno(stmts) \
  115. do {int saved_errno = errno; stmts; errno = saved_errno;} while (0)
  116. static void check_uid_switch(void);
  117. static void check_gid_switch(void);
  118. #if 1
  119. #define p_uid_from_name p_uid_from_name
  120. #define p_gid_from_name p_gid_from_name
  121. #endif
  122. #if defined(HAVE_PWD_H)
  123. # ifdef HAVE_GETPWNAM_R
  124. # define PREPARE_GETPWNAM \
  125. long getpw_buf_len = sysconf(_SC_GETPW_R_SIZE_MAX); \
  126. char *getpw_buf = ALLOCA_N(char, (getpw_buf_len < 0 ? (getpw_buf_len = 4096) : getpw_buf_len));
  127. # define OBJ2UID(id) obj2uid((id), getpw_buf, getpw_buf_len)
  128. static rb_uid_t obj2uid(VALUE id, char *getpw_buf, size_t getpw_buf_len);
  129. # else
  130. # define PREPARE_GETPWNAM /* do nothing */
  131. # define OBJ2UID(id) obj2uid((id))
  132. static rb_uid_t obj2uid(VALUE id);
  133. # endif
  134. #else
  135. # define PREPARE_GETPWNAM /* do nothing */
  136. # define OBJ2UID(id) NUM2UIDT(id)
  137. # ifdef p_uid_from_name
  138. # undef p_uid_from_name
  139. # define p_uid_from_name rb_f_notimplement
  140. # endif
  141. #endif
  142. #if defined(HAVE_GRP_H)
  143. # ifdef HAVE_GETGRNAM_R
  144. # define PREPARE_GETGRNAM \
  145. long getgr_buf_len = sysconf(_SC_GETGR_R_SIZE_MAX); \
  146. char *getgr_buf = ALLOCA_N(char, (getgr_buf_len < 0 ? (getgr_buf_len = 4096) : getgr_buf_len));
  147. # define OBJ2GID(id) obj2gid((id), getgr_buf, getgr_buf_len)
  148. static rb_gid_t obj2gid(VALUE id, char *getgr_buf, size_t getgr_buf_len);
  149. # else
  150. # define PREPARE_GETGRNAM /* do nothing */
  151. # define OBJ2GID(id) obj2gid((id))
  152. static rb_gid_t obj2gid(VALUE id);
  153. # endif
  154. #else
  155. # define PREPARE_GETGRNAM /* do nothing */
  156. # define OBJ2GID(id) NUM2GIDT(id)
  157. # ifdef p_gid_from_name
  158. # undef p_gid_from_name
  159. # define p_gid_from_name rb_f_notimplement
  160. # endif
  161. #endif
  162. /*
  163. * call-seq:
  164. * Process.pid -> fixnum
  165. *
  166. * Returns the process id of this process. Not available on all
  167. * platforms.
  168. *
  169. * Process.pid #=> 27415
  170. */
  171. static VALUE
  172. get_pid(void)
  173. {
  174. rb_secure(2);
  175. return PIDT2NUM(getpid());
  176. }
  177. /*
  178. * call-seq:
  179. * Process.ppid -> fixnum
  180. *
  181. * Returns the process id of the parent of this process. Returns
  182. * untrustworthy value on Win32/64. Not available on all platforms.
  183. *
  184. * puts "I am #{Process.pid}"
  185. * Process.fork { puts "Dad is #{Process.ppid}" }
  186. *
  187. * <em>produces:</em>
  188. *
  189. * I am 27417
  190. * Dad is 27417
  191. */
  192. static VALUE
  193. get_ppid(void)
  194. {
  195. rb_secure(2);
  196. return PIDT2NUM(getppid());
  197. }
  198. /*********************************************************************
  199. *
  200. * Document-class: Process::Status
  201. *
  202. * <code>Process::Status</code> encapsulates the information on the
  203. * status of a running or terminated system process. The built-in
  204. * variable <code>$?</code> is either +nil+ or a
  205. * <code>Process::Status</code> object.
  206. *
  207. * fork { exit 99 } #=> 26557
  208. * Process.wait #=> 26557
  209. * $?.class #=> Process::Status
  210. * $?.to_i #=> 25344
  211. * $? >> 8 #=> 99
  212. * $?.stopped? #=> false
  213. * $?.exited? #=> true
  214. * $?.exitstatus #=> 99
  215. *
  216. * Posix systems record information on processes using a 16-bit
  217. * integer. The lower bits record the process status (stopped,
  218. * exited, signaled) and the upper bits possibly contain additional
  219. * information (for example the program's return code in the case of
  220. * exited processes). Pre Ruby 1.8, these bits were exposed directly
  221. * to the Ruby program. Ruby now encapsulates these in a
  222. * <code>Process::Status</code> object. To maximize compatibility,
  223. * however, these objects retain a bit-oriented interface. In the
  224. * descriptions that follow, when we talk about the integer value of
  225. * _stat_, we're referring to this 16 bit value.
  226. */
  227. static VALUE rb_cProcessStatus;
  228. VALUE
  229. rb_last_status_get(void)
  230. {
  231. return GET_THREAD()->last_status;
  232. }
  233. void
  234. rb_last_status_set(int status, rb_pid_t pid)
  235. {
  236. rb_thread_t *th = GET_THREAD();
  237. th->last_status = rb_obj_alloc(rb_cProcessStatus);
  238. rb_iv_set(th->last_status, "status", INT2FIX(status));
  239. rb_iv_set(th->last_status, "pid", PIDT2NUM(pid));
  240. }
  241. void
  242. rb_last_status_clear(void)
  243. {
  244. GET_THREAD()->last_status = Qnil;
  245. }
  246. /*
  247. * call-seq:
  248. * stat.to_i -> fixnum
  249. * stat.to_int -> fixnum
  250. *
  251. * Returns the bits in _stat_ as a <code>Fixnum</code>. Poking
  252. * around in these bits is platform dependent.
  253. *
  254. * fork { exit 0xab } #=> 26566
  255. * Process.wait #=> 26566
  256. * sprintf('%04x', $?.to_i) #=> "ab00"
  257. */
  258. static VALUE
  259. pst_to_i(VALUE st)
  260. {
  261. return rb_iv_get(st, "status");
  262. }
  263. #define PST2INT(st) NUM2INT(pst_to_i(st))
  264. /*
  265. * call-seq:
  266. * stat.pid -> fixnum
  267. *
  268. * Returns the process ID that this status object represents.
  269. *
  270. * fork { exit } #=> 26569
  271. * Process.wait #=> 26569
  272. * $?.pid #=> 26569
  273. */
  274. static VALUE
  275. pst_pid(VALUE st)
  276. {
  277. return rb_attr_get(st, rb_intern("pid"));
  278. }
  279. static void
  280. pst_message(VALUE str, rb_pid_t pid, int status)
  281. {
  282. rb_str_catf(str, "pid %ld", (long)pid);
  283. if (WIFSTOPPED(status)) {
  284. int stopsig = WSTOPSIG(status);
  285. const char *signame = ruby_signal_name(stopsig);
  286. if (signame) {
  287. rb_str_catf(str, " stopped SIG%s (signal %d)", signame, stopsig);
  288. }
  289. else {
  290. rb_str_catf(str, " stopped signal %d", stopsig);
  291. }
  292. }
  293. if (WIFSIGNALED(status)) {
  294. int termsig = WTERMSIG(status);
  295. const char *signame = ruby_signal_name(termsig);
  296. if (signame) {
  297. rb_str_catf(str, " SIG%s (signal %d)", signame, termsig);
  298. }
  299. else {
  300. rb_str_catf(str, " signal %d", termsig);
  301. }
  302. }
  303. if (WIFEXITED(status)) {
  304. rb_str_catf(str, " exit %d", WEXITSTATUS(status));
  305. }
  306. #ifdef WCOREDUMP
  307. if (WCOREDUMP(status)) {
  308. rb_str_cat2(str, " (core dumped)");
  309. }
  310. #endif
  311. }
  312. /*
  313. * call-seq:
  314. * stat.to_s -> string
  315. *
  316. * Show pid and exit status as a string.
  317. *
  318. * system("false")
  319. * p $?.to_s #=> "pid 12766 exit 1"
  320. *
  321. */
  322. static VALUE
  323. pst_to_s(VALUE st)
  324. {
  325. rb_pid_t pid;
  326. int status;
  327. VALUE str;
  328. pid = NUM2PIDT(pst_pid(st));
  329. status = PST2INT(st);
  330. str = rb_str_buf_new(0);
  331. pst_message(str, pid, status);
  332. return str;
  333. }
  334. /*
  335. * call-seq:
  336. * stat.inspect -> string
  337. *
  338. * Override the inspection method.
  339. *
  340. * system("false")
  341. * p $?.inspect #=> "#<Process::Status: pid 12861 exit 1>"
  342. *
  343. */
  344. static VALUE
  345. pst_inspect(VALUE st)
  346. {
  347. rb_pid_t pid;
  348. int status;
  349. VALUE vpid, str;
  350. vpid = pst_pid(st);
  351. if (NIL_P(vpid)) {
  352. return rb_sprintf("#<%s: uninitialized>", rb_class2name(CLASS_OF(st)));
  353. }
  354. pid = NUM2PIDT(vpid);
  355. status = PST2INT(st);
  356. str = rb_sprintf("#<%s: ", rb_class2name(CLASS_OF(st)));
  357. pst_message(str, pid, status);
  358. rb_str_cat2(str, ">");
  359. return str;
  360. }
  361. /*
  362. * call-seq:
  363. * stat == other -> true or false
  364. *
  365. * Returns +true+ if the integer value of _stat_
  366. * equals <em>other</em>.
  367. */
  368. static VALUE
  369. pst_equal(VALUE st1, VALUE st2)
  370. {
  371. if (st1 == st2) return Qtrue;
  372. return rb_equal(pst_to_i(st1), st2);
  373. }
  374. /*
  375. * call-seq:
  376. * stat & num -> fixnum
  377. *
  378. * Logical AND of the bits in _stat_ with <em>num</em>.
  379. *
  380. * fork { exit 0x37 }
  381. * Process.wait
  382. * sprintf('%04x', $?.to_i) #=> "3700"
  383. * sprintf('%04x', $? & 0x1e00) #=> "1600"
  384. */
  385. static VALUE
  386. pst_bitand(VALUE st1, VALUE st2)
  387. {
  388. int status = PST2INT(st1) & NUM2INT(st2);
  389. return INT2NUM(status);
  390. }
  391. /*
  392. * call-seq:
  393. * stat >> num -> fixnum
  394. *
  395. * Shift the bits in _stat_ right <em>num</em> places.
  396. *
  397. * fork { exit 99 } #=> 26563
  398. * Process.wait #=> 26563
  399. * $?.to_i #=> 25344
  400. * $? >> 8 #=> 99
  401. */
  402. static VALUE
  403. pst_rshift(VALUE st1, VALUE st2)
  404. {
  405. int status = PST2INT(st1) >> NUM2INT(st2);
  406. return INT2NUM(status);
  407. }
  408. /*
  409. * call-seq:
  410. * stat.stopped? -> true or false
  411. *
  412. * Returns +true+ if this process is stopped. This is only
  413. * returned if the corresponding <code>wait</code> call had the
  414. * <code>WUNTRACED</code> flag set.
  415. */
  416. static VALUE
  417. pst_wifstopped(VALUE st)
  418. {
  419. int status = PST2INT(st);
  420. if (WIFSTOPPED(status))
  421. return Qtrue;
  422. else
  423. return Qfalse;
  424. }
  425. /*
  426. * call-seq:
  427. * stat.stopsig -> fixnum or nil
  428. *
  429. * Returns the number of the signal that caused _stat_ to stop
  430. * (or +nil+ if self is not stopped).
  431. */
  432. static VALUE
  433. pst_wstopsig(VALUE st)
  434. {
  435. int status = PST2INT(st);
  436. if (WIFSTOPPED(status))
  437. return INT2NUM(WSTOPSIG(status));
  438. return Qnil;
  439. }
  440. /*
  441. * call-seq:
  442. * stat.signaled? -> true or false
  443. *
  444. * Returns +true+ if _stat_ terminated because of
  445. * an uncaught signal.
  446. */
  447. static VALUE
  448. pst_wifsignaled(VALUE st)
  449. {
  450. int status = PST2INT(st);
  451. if (WIFSIGNALED(status))
  452. return Qtrue;
  453. else
  454. return Qfalse;
  455. }
  456. /*
  457. * call-seq:
  458. * stat.termsig -> fixnum or nil
  459. *
  460. * Returns the number of the signal that caused _stat_ to
  461. * terminate (or +nil+ if self was not terminated by an
  462. * uncaught signal).
  463. */
  464. static VALUE
  465. pst_wtermsig(VALUE st)
  466. {
  467. int status = PST2INT(st);
  468. if (WIFSIGNALED(status))
  469. return INT2NUM(WTERMSIG(status));
  470. return Qnil;
  471. }
  472. /*
  473. * call-seq:
  474. * stat.exited? -> true or false
  475. *
  476. * Returns +true+ if _stat_ exited normally (for
  477. * example using an <code>exit()</code> call or finishing the
  478. * program).
  479. */
  480. static VALUE
  481. pst_wifexited(VALUE st)
  482. {
  483. int status = PST2INT(st);
  484. if (WIFEXITED(status))
  485. return Qtrue;
  486. else
  487. return Qfalse;
  488. }
  489. /*
  490. * call-seq:
  491. * stat.exitstatus -> fixnum or nil
  492. *
  493. * Returns the least significant eight bits of the return code of
  494. * _stat_. Only available if <code>exited?</code> is
  495. * +true+.
  496. *
  497. * fork { } #=> 26572
  498. * Process.wait #=> 26572
  499. * $?.exited? #=> true
  500. * $?.exitstatus #=> 0
  501. *
  502. * fork { exit 99 } #=> 26573
  503. * Process.wait #=> 26573
  504. * $?.exited? #=> true
  505. * $?.exitstatus #=> 99
  506. */
  507. static VALUE
  508. pst_wexitstatus(VALUE st)
  509. {
  510. int status = PST2INT(st);
  511. if (WIFEXITED(status))
  512. return INT2NUM(WEXITSTATUS(status));
  513. return Qnil;
  514. }
  515. /*
  516. * call-seq:
  517. * stat.success? -> true, false or nil
  518. *
  519. * Returns +true+ if _stat_ is successful, +false+ if not.
  520. * Returns +nil+ if <code>exited?</code> is not +true+.
  521. */
  522. static VALUE
  523. pst_success_p(VALUE st)
  524. {
  525. int status = PST2INT(st);
  526. if (!WIFEXITED(status))
  527. return Qnil;
  528. return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
  529. }
  530. /*
  531. * call-seq:
  532. * stat.coredump? -> true or false
  533. *
  534. * Returns +true+ if _stat_ generated a coredump
  535. * when it terminated. Not available on all platforms.
  536. */
  537. static VALUE
  538. pst_wcoredump(VALUE st)
  539. {
  540. #ifdef WCOREDUMP
  541. int status = PST2INT(st);
  542. if (WCOREDUMP(status))
  543. return Qtrue;
  544. else
  545. return Qfalse;
  546. #else
  547. return Qfalse;
  548. #endif
  549. }
  550. #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
  551. #define NO_WAITPID
  552. static st_table *pid_tbl;
  553. struct wait_data {
  554. rb_pid_t pid;
  555. int status;
  556. };
  557. static int
  558. wait_each(rb_pid_t pid, int status, struct wait_data *data)
  559. {
  560. if (data->status != -1) return ST_STOP;
  561. data->pid = pid;
  562. data->status = status;
  563. return ST_DELETE;
  564. }
  565. static int
  566. waitall_each(rb_pid_t pid, int status, VALUE ary)
  567. {
  568. rb_last_status_set(status, pid);
  569. rb_ary_push(ary, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
  570. return ST_DELETE;
  571. }
  572. #else
  573. struct waitpid_arg {
  574. rb_pid_t pid;
  575. int *st;
  576. int flags;
  577. };
  578. #endif
  579. static void *
  580. rb_waitpid_blocking(void *data)
  581. {
  582. rb_pid_t result;
  583. #ifndef NO_WAITPID
  584. struct waitpid_arg *arg = data;
  585. #endif
  586. #if defined NO_WAITPID
  587. result = wait(data);
  588. #elif defined HAVE_WAITPID
  589. result = waitpid(arg->pid, arg->st, arg->flags);
  590. #else /* HAVE_WAIT4 */
  591. result = wait4(arg->pid, arg->st, arg->flags, NULL);
  592. #endif
  593. return (void *)(VALUE)result;
  594. }
  595. rb_pid_t
  596. rb_waitpid(rb_pid_t pid, int *st, int flags)
  597. {
  598. rb_pid_t result;
  599. #ifndef NO_WAITPID
  600. struct waitpid_arg arg;
  601. retry:
  602. arg.pid = pid;
  603. arg.st = st;
  604. arg.flags = flags;
  605. result = (rb_pid_t)(VALUE)rb_thread_call_without_gvl(rb_waitpid_blocking, &arg,
  606. RUBY_UBF_PROCESS, 0);
  607. if (result < 0) {
  608. if (errno == EINTR) {
  609. RUBY_VM_CHECK_INTS(GET_THREAD());
  610. goto retry;
  611. }
  612. return (rb_pid_t)-1;
  613. }
  614. #else /* NO_WAITPID */
  615. if (pid_tbl) {
  616. st_data_t status, piddata = (st_data_t)pid;
  617. if (pid == (rb_pid_t)-1) {
  618. struct wait_data data;
  619. data.pid = (rb_pid_t)-1;
  620. data.status = -1;
  621. st_foreach(pid_tbl, wait_each, (st_data_t)&data);
  622. if (data.status != -1) {
  623. rb_last_status_set(data.status, data.pid);
  624. return data.pid;
  625. }
  626. }
  627. else if (st_delete(pid_tbl, &piddata, &status)) {
  628. rb_last_status_set(*st = (int)status, pid);
  629. return pid;
  630. }
  631. }
  632. if (flags) {
  633. rb_raise(rb_eArgError, "can't do waitpid with flags");
  634. }
  635. for (;;) {
  636. result = (rb_pid_t)(VALUE)rb_thread_blocking_region(rb_waitpid_blocking,
  637. st, RUBY_UBF_PROCESS, 0);
  638. if (result < 0) {
  639. if (errno == EINTR) {
  640. rb_thread_schedule();
  641. continue;
  642. }
  643. return (rb_pid_t)-1;
  644. }
  645. if (result == pid || pid == (rb_pid_t)-1) {
  646. break;
  647. }
  648. if (!pid_tbl)
  649. pid_tbl = st_init_numtable();
  650. st_insert(pid_tbl, pid, (st_data_t)st);
  651. if (!rb_thread_alone()) rb_thread_schedule();
  652. }
  653. #endif
  654. if (result > 0) {
  655. rb_last_status_set(*st, result);
  656. }
  657. return result;
  658. }
  659. /* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
  660. has historically been documented as if it didn't take any arguments
  661. despite the fact that it's just an alias for ::waitpid(). The way I
  662. have it below is more truthful, but a little confusing.
  663. I also took the liberty of putting in the pid values, as they're
  664. pretty useful, and it looked as if the original 'ri' output was
  665. supposed to contain them after "[...]depending on the value of
  666. aPid:".
  667. The 'ansi' and 'bs' formats of the ri output don't display the
  668. definition list for some reason, but the plain text one does.
  669. */
  670. /*
  671. * call-seq:
  672. * Process.wait() -> fixnum
  673. * Process.wait(pid=-1, flags=0) -> fixnum
  674. * Process.waitpid(pid=-1, flags=0) -> fixnum
  675. *
  676. * Waits for a child process to exit, returns its process id, and
  677. * sets <code>$?</code> to a <code>Process::Status</code> object
  678. * containing information on that process. Which child it waits on
  679. * depends on the value of _pid_:
  680. *
  681. * > 0:: Waits for the child whose process ID equals _pid_.
  682. *
  683. * 0:: Waits for any child whose process group ID equals that of the
  684. * calling process.
  685. *
  686. * -1:: Waits for any child process (the default if no _pid_ is
  687. * given).
  688. *
  689. * < -1:: Waits for any child whose process group ID equals the absolute
  690. * value of _pid_.
  691. *
  692. * The _flags_ argument may be a logical or of the flag values
  693. * <code>Process::WNOHANG</code> (do not block if no child available)
  694. * or <code>Process::WUNTRACED</code> (return stopped children that
  695. * haven't been reported). Not all flags are available on all
  696. * platforms, but a flag value of zero will work on all platforms.
  697. *
  698. * Calling this method raises a SystemCallError if there are no child
  699. * processes. Not available on all platforms.
  700. *
  701. * include Process
  702. * fork { exit 99 } #=> 27429
  703. * wait #=> 27429
  704. * $?.exitstatus #=> 99
  705. *
  706. * pid = fork { sleep 3 } #=> 27440
  707. * Time.now #=> 2008-03-08 19:56:16 +0900
  708. * waitpid(pid, Process::WNOHANG) #=> nil
  709. * Time.now #=> 2008-03-08 19:56:16 +0900
  710. * waitpid(pid, 0) #=> 27440
  711. * Time.now #=> 2008-03-08 19:56:19 +0900
  712. */
  713. static VALUE
  714. proc_wait(int argc, VALUE *argv)
  715. {
  716. VALUE vpid, vflags;
  717. rb_pid_t pid;
  718. int flags, status;
  719. rb_secure(2);
  720. flags = 0;
  721. if (argc == 0) {
  722. pid = -1;
  723. }
  724. else {
  725. rb_scan_args(argc, argv, "02", &vpid, &vflags);
  726. pid = NUM2PIDT(vpid);
  727. if (argc == 2 && !NIL_P(vflags)) {
  728. flags = NUM2UINT(vflags);
  729. }
  730. }
  731. if ((pid = rb_waitpid(pid, &status, flags)) < 0)
  732. rb_sys_fail(0);
  733. if (pid == 0) {
  734. rb_last_status_clear();
  735. return Qnil;
  736. }
  737. return PIDT2NUM(pid);
  738. }
  739. /*
  740. * call-seq:
  741. * Process.wait2(pid=-1, flags=0) -> [pid, status]
  742. * Process.waitpid2(pid=-1, flags=0) -> [pid, status]
  743. *
  744. * Waits for a child process to exit (see Process::waitpid for exact
  745. * semantics) and returns an array containing the process id and the
  746. * exit status (a <code>Process::Status</code> object) of that
  747. * child. Raises a SystemCallError if there are no child processes.
  748. *
  749. * Process.fork { exit 99 } #=> 27437
  750. * pid, status = Process.wait2
  751. * pid #=> 27437
  752. * status.exitstatus #=> 99
  753. */
  754. static VALUE
  755. proc_wait2(int argc, VALUE *argv)
  756. {
  757. VALUE pid = proc_wait(argc, argv);
  758. if (NIL_P(pid)) return Qnil;
  759. return rb_assoc_new(pid, rb_last_status_get());
  760. }
  761. /*
  762. * call-seq:
  763. * Process.waitall -> [ [pid1,status1], ...]
  764. *
  765. * Waits for all children, returning an array of
  766. * _pid_/_status_ pairs (where _status_ is a
  767. * <code>Process::Status</code> object).
  768. *
  769. * fork { sleep 0.2; exit 2 } #=> 27432
  770. * fork { sleep 0.1; exit 1 } #=> 27433
  771. * fork { exit 0 } #=> 27434
  772. * p Process.waitall
  773. *
  774. * <em>produces</em>:
  775. *
  776. * [[30982, #<Process::Status: pid 30982 exit 0>],
  777. * [30979, #<Process::Status: pid 30979 exit 1>],
  778. * [30976, #<Process::Status: pid 30976 exit 2>]]
  779. */
  780. static VALUE
  781. proc_waitall(void)
  782. {
  783. VALUE result;
  784. rb_pid_t pid;
  785. int status;
  786. rb_secure(2);
  787. result = rb_ary_new();
  788. #ifdef NO_WAITPID
  789. if (pid_tbl) {
  790. st_foreach(pid_tbl, waitall_each, result);
  791. }
  792. #else
  793. rb_last_status_clear();
  794. #endif
  795. for (pid = -1;;) {
  796. #ifdef NO_WAITPID
  797. pid = wait(&status);
  798. #else
  799. pid = rb_waitpid(-1, &status, 0);
  800. #endif
  801. if (pid == -1) {
  802. if (errno == ECHILD)
  803. break;
  804. #ifdef NO_WAITPID
  805. if (errno == EINTR) {
  806. rb_thread_schedule();
  807. continue;
  808. }
  809. #endif
  810. rb_sys_fail(0);
  811. }
  812. #ifdef NO_WAITPID
  813. rb_last_status_set(status, pid);
  814. #endif
  815. rb_ary_push(result, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
  816. }
  817. return result;
  818. }
  819. static inline ID
  820. id_pid(void)
  821. {
  822. ID pid;
  823. CONST_ID(pid, "pid");
  824. return pid;
  825. }
  826. static VALUE
  827. detach_process_pid(VALUE thread)
  828. {
  829. return rb_thread_local_aref(thread, id_pid());
  830. }
  831. static VALUE
  832. detach_process_watcher(void *arg)
  833. {
  834. rb_pid_t cpid, pid = (rb_pid_t)(VALUE)arg;
  835. int status;
  836. while ((cpid = rb_waitpid(pid, &status, 0)) == 0) {
  837. /* wait while alive */
  838. }
  839. return rb_last_status_get();
  840. }
  841. VALUE
  842. rb_detach_process(rb_pid_t pid)
  843. {
  844. VALUE watcher = rb_thread_create(detach_process_watcher, (void*)(VALUE)pid);
  845. rb_thread_local_aset(watcher, id_pid(), PIDT2NUM(pid));
  846. rb_define_singleton_method(watcher, "pid", detach_process_pid, 0);
  847. return watcher;
  848. }
  849. /*
  850. * call-seq:
  851. * Process.detach(pid) -> thread
  852. *
  853. * Some operating systems retain the status of terminated child
  854. * processes until the parent collects that status (normally using
  855. * some variant of <code>wait()</code>. If the parent never collects
  856. * this status, the child stays around as a <em>zombie</em> process.
  857. * <code>Process::detach</code> prevents this by setting up a
  858. * separate Ruby thread whose sole job is to reap the status of the
  859. * process _pid_ when it terminates. Use <code>detach</code>
  860. * only when you do not intent to explicitly wait for the child to
  861. * terminate.
  862. *
  863. * The waiting thread returns the exit status of the detached process
  864. * when it terminates, so you can use <code>Thread#join</code> to
  865. * know the result. If specified _pid_ is not a valid child process
  866. * ID, the thread returns +nil+ immediately.
  867. *
  868. * The waiting thread has <code>pid</code> method which returns the pid.
  869. *
  870. * In this first example, we don't reap the first child process, so
  871. * it appears as a zombie in the process status display.
  872. *
  873. * p1 = fork { sleep 0.1 }
  874. * p2 = fork { sleep 0.2 }
  875. * Process.waitpid(p2)
  876. * sleep 2
  877. * system("ps -ho pid,state -p #{p1}")
  878. *
  879. * <em>produces:</em>
  880. *
  881. * 27389 Z
  882. *
  883. * In the next example, <code>Process::detach</code> is used to reap
  884. * the child automatically.
  885. *
  886. * p1 = fork { sleep 0.1 }
  887. * p2 = fork { sleep 0.2 }
  888. * Process.detach(p1)
  889. * Process.waitpid(p2)
  890. * sleep 2
  891. * system("ps -ho pid,state -p #{p1}")
  892. *
  893. * <em>(produces no output)</em>
  894. */
  895. static VALUE
  896. proc_detach(VALUE obj, VALUE pid)
  897. {
  898. rb_secure(2);
  899. return rb_detach_process(NUM2PIDT(pid));
  900. }
  901. static int forked_child = 0;
  902. #ifdef SIGPIPE
  903. static RETSIGTYPE (*saved_sigpipe_handler)(int) = 0;
  904. #endif
  905. #ifdef SIGPIPE
  906. static RETSIGTYPE
  907. sig_do_nothing(int sig)
  908. {
  909. }
  910. #endif
  911. /* This function should be async-signal-safe. Actually it is. */
  912. static void
  913. before_exec_async_signal_safe(void)
  914. {
  915. #ifdef SIGPIPE
  916. /*
  917. * Some OS commands don't initialize signal handler properly. Thus we have
  918. * to reset signal handler before exec(). Otherwise, system() and similar
  919. * child process interaction might fail. (e.g. ruby -e "system 'yes | ls'")
  920. * [ruby-dev:12261]
  921. */
  922. saved_sigpipe_handler = signal(SIGPIPE, sig_do_nothing); /* async-signal-safe */
  923. #endif
  924. }
  925. static void
  926. before_exec_non_async_signal_safe(void)
  927. {
  928. if (!forked_child) {
  929. /*
  930. * On Mac OS X 10.5.x (Leopard) or earlier, exec() may return ENOTSUPP
  931. * if the process have multiple threads. Therefore we have to kill
  932. * internal threads temporary. [ruby-core:10583]
  933. * This is also true on Haiku. It returns Errno::EPERM against exec()
  934. * in multiple threads.
  935. */
  936. rb_thread_stop_timer_thread(0);
  937. }
  938. }
  939. static void
  940. before_exec(void)
  941. {
  942. before_exec_non_async_signal_safe();
  943. before_exec_async_signal_safe();
  944. }
  945. /* This function should be async-signal-safe. Actually it is. */
  946. static void
  947. after_exec_async_signal_safe(void)
  948. {
  949. #ifdef SIGPIPE
  950. signal(SIGPIPE, saved_sigpipe_handler); /* async-signal-safe */
  951. #endif
  952. }
  953. static void
  954. after_exec_non_async_signal_safe(void)
  955. {
  956. rb_thread_reset_timer_thread();
  957. rb_thread_start_timer_thread();
  958. forked_child = 0;
  959. }
  960. static void
  961. after_exec(void)
  962. {
  963. after_exec_async_signal_safe();
  964. after_exec_non_async_signal_safe();
  965. }
  966. #define before_fork() before_exec()
  967. #define after_fork() (rb_threadptr_pending_interrupt_clear(GET_THREAD()), after_exec())
  968. #include "dln.h"
  969. static void
  970. security(const char *str)
  971. {
  972. if (rb_env_path_tainted()) {
  973. if (rb_safe_level() > 0) {
  974. rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
  975. }
  976. }
  977. }
  978. #if defined(HAVE_FORK) && !defined(__native_client__)
  979. /* try_with_sh and exec_with_sh should be async-signal-safe. Actually it is.*/
  980. #define try_with_sh(prog, argv, envp) ((saved_errno == ENOEXEC) ? exec_with_sh((prog), (argv), (envp)) : (void)0)
  981. static void
  982. exec_with_sh(const char *prog, char **argv, char **envp)
  983. {
  984. *argv = (char *)prog;
  985. *--argv = (char *)"sh";
  986. if (envp)
  987. execve("/bin/sh", argv, envp); /* async-signal-safe */
  988. else
  989. execv("/bin/sh", argv); /* async-signal-safe */
  990. }
  991. #else
  992. #define try_with_sh(prog, argv, envp) (void)0
  993. #endif
  994. /* This function should be async-signal-safe. Actually it is. */
  995. static int
  996. proc_exec_cmd(const char *prog, VALUE argv_str, VALUE envp_str)
  997. {
  998. #ifdef __native_client__
  999. rb_notimplement();
  1000. UNREACHABLE;
  1001. #else
  1002. char **argv;
  1003. char **envp;
  1004. # if defined(__EMX__) || defined(OS2)
  1005. char **new_argv = NULL;
  1006. # endif
  1007. argv = ARGVSTR2ARGV(argv_str);
  1008. if (!prog) {
  1009. errno = ENOENT;
  1010. return -1;
  1011. }
  1012. # if defined(__EMX__) || defined(OS2)
  1013. {
  1014. # define COMMAND "cmd.exe"
  1015. char *extension;
  1016. if ((extension = strrchr(prog, '.')) != NULL && STRCASECMP(extension, ".bat") == 0) {
  1017. char *p;
  1018. int n;
  1019. for (n = 0; argv[n]; n++)
  1020. /* no-op */;
  1021. new_argv = ALLOC_N(char*, n + 2);
  1022. for (; n > 0; n--)
  1023. new_argv[n + 1] = argv[n];
  1024. new_argv[1] = strcpy(ALLOC_N(char, strlen(argv[0]) + 1), argv[0]);
  1025. for (p = new_argv[1]; *p != '\0'; p++)
  1026. if (*p == '/')
  1027. *p = '\\';
  1028. new_argv[0] = COMMAND;
  1029. argv = new_argv;
  1030. prog = dln_find_exe_r(argv[0], 0, fbuf, sizeof(fbuf));
  1031. if (!prog) {
  1032. errno = ENOENT;
  1033. return -1;
  1034. }
  1035. }
  1036. }
  1037. # endif /* __EMX__ */
  1038. envp = envp_str ? (char **)RSTRING_PTR(envp_str) : NULL;
  1039. if (envp_str)
  1040. execve(prog, argv, envp); /* async-signal-safe */
  1041. else
  1042. execv(prog, argv); /* async-signal-safe */
  1043. preserving_errno(try_with_sh(prog, argv, envp)); /* try_with_sh() is async-signal-safe. */
  1044. # if defined(__EMX__) || defined(OS2)
  1045. if (new_argv) {
  1046. xfree(new_argv[0]);
  1047. xfree(new_argv);
  1048. }
  1049. # endif
  1050. return -1;
  1051. #endif
  1052. }
  1053. /* deprecated */
  1054. static int
  1055. proc_exec_v(char **argv, const char *prog)
  1056. {
  1057. char fbuf[MAXPATHLEN];
  1058. if (!prog)
  1059. prog = argv[0];
  1060. prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
  1061. if (!prog) {
  1062. errno = ENOENT;
  1063. return -1;
  1064. }
  1065. before_exec();
  1066. execv(prog, argv);
  1067. preserving_errno(try_with_sh(prog, argv, 0); after_exec());
  1068. return -1;
  1069. }
  1070. /* deprecated */
  1071. int
  1072. rb_proc_exec_n(int argc, VALUE *argv, const char *prog)
  1073. {
  1074. #define ARGV_COUNT(n) ((n)+1)
  1075. #define ARGV_SIZE(n) (sizeof(char*) * ARGV_COUNT(n))
  1076. #define ALLOC_ARGV(n, v) ALLOCV_N(char*, (v), ARGV_COUNT(n))
  1077. char **args;
  1078. int i;
  1079. int ret = -1;
  1080. VALUE v;
  1081. args = ALLOC_ARGV(argc+1, v);
  1082. for (i=0; i<argc; i++) {
  1083. args[i] = RSTRING_PTR(argv[i]);
  1084. }
  1085. args[i] = 0;
  1086. if (args[0]) {
  1087. ret = proc_exec_v(args, prog);
  1088. }
  1089. ALLOCV_END(v);
  1090. return ret;
  1091. #undef ARGV_COUNT
  1092. #undef ARGV_SIZE
  1093. #undef ALLOC_ARGV
  1094. }
  1095. /* This function should be async-signal-safe. Actually it is. */
  1096. static int
  1097. proc_exec_sh(const char *str, VALUE envp_str)
  1098. {
  1099. #ifdef __native_client__
  1100. rb_notimplement();
  1101. UNREACHABLE;
  1102. #else
  1103. const char *s;
  1104. s = str;
  1105. while (*s == ' ' || *s == '\t' || *s == '\n')
  1106. s++;
  1107. if (!*s) {
  1108. errno = ENOENT;
  1109. return -1;
  1110. }
  1111. #ifdef _WIN32
  1112. rb_w32_spawn(P_OVERLAY, (char *)str, 0);
  1113. return -1;
  1114. #else
  1115. #if defined(__CYGWIN32__) || defined(__EMX__)
  1116. {
  1117. char fbuf[MAXPATHLEN];
  1118. char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
  1119. int status = -1;
  1120. if (shell)
  1121. execl(shell, "sh", "-c", str, (char *) NULL);
  1122. else
  1123. status = system(str);
  1124. if (status != -1)
  1125. exit(status);
  1126. }
  1127. #else
  1128. if (envp_str)
  1129. execle("/bin/sh", "sh", "-c", str, (char *)NULL, (char **)RSTRING_PTR(envp_str)); /* async-signal-safe */
  1130. else
  1131. execl("/bin/sh", "sh", "-c", str, (char *)NULL); /* async-signal-safe */
  1132. #endif
  1133. return -1;
  1134. #endif /* _WIN32 */
  1135. #endif
  1136. }
  1137. int
  1138. rb_proc_exec(const char *str)
  1139. {
  1140. int ret;
  1141. before_exec();
  1142. ret = proc_exec_sh(str, Qfalse);
  1143. preserving_errno(after_exec());
  1144. return ret;
  1145. }
  1146. static void
  1147. mark_exec_arg(void *ptr)
  1148. {
  1149. struct rb_execarg *eargp = ptr;
  1150. if (eargp->use_shell)
  1151. rb_gc_mark(eargp->invoke.sh.shell_script);
  1152. else {
  1153. rb_gc_mark(eargp->invoke.cmd.command_name);
  1154. rb_gc_mark(eargp->invoke.cmd.command_abspath);
  1155. rb_gc_mark(eargp->invoke.cmd.argv_str);
  1156. rb_gc_mark(eargp->invoke.cmd.argv_buf);
  1157. }
  1158. rb_gc_mark(eargp->redirect_fds);
  1159. rb_gc_mark(eargp->envp_str);
  1160. rb_gc_mark(eargp->envp_buf);
  1161. rb_gc_mark(eargp->dup2_tmpbuf);
  1162. rb_gc_mark(eargp->rlimit_limits);
  1163. rb_gc_mark(eargp->fd_dup2);
  1164. rb_gc_mark(eargp->fd_close);
  1165. rb_gc_mark(eargp->fd_open);
  1166. rb_gc_mark(eargp->fd_dup2_child);
  1167. rb_gc_mark(eargp->env_modification);
  1168. rb_gc_mark(eargp->chdir_dir);
  1169. }
  1170. static void
  1171. free_exec_arg(void *ptr)
  1172. {
  1173. xfree(ptr);
  1174. }
  1175. static size_t
  1176. memsize_exec_arg(const void *ptr)
  1177. {
  1178. return ptr ? sizeof(struct rb_execarg) : 0;
  1179. }
  1180. static const rb_data_type_t exec_arg_data_type = {
  1181. "exec_arg",
  1182. {mark_exec_arg, free_exec_arg, memsize_exec_arg},
  1183. };
  1184. #if defined(_WIN32)
  1185. #define HAVE_SPAWNV 1
  1186. #endif
  1187. #if !defined(HAVE_FORK) && defined(HAVE_SPAWNV)
  1188. # define USE_SPAWNV 1
  1189. #else
  1190. # define USE_SPAWNV 0
  1191. #endif
  1192. #ifndef P_NOWAIT
  1193. # define P_NOWAIT _P_NOWAIT
  1194. #endif
  1195. #if USE_SPAWNV
  1196. #if defined(_WIN32)
  1197. #define proc_spawn_cmd_internal(argv, prog) rb_w32_aspawn(P_NOWAIT, (prog), (argv))
  1198. #else
  1199. static rb_pid_t
  1200. proc_spawn_cmd_internal(char **argv, char *prog)
  1201. {
  1202. char fbuf[MAXPATHLEN];
  1203. rb_pid_t status;
  1204. if (!prog)
  1205. prog = argv[0];
  1206. security(prog);
  1207. prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
  1208. if (!prog)
  1209. return -1;
  1210. before_exec();
  1211. status = spawnv(P_NOWAIT, prog, (const char **)argv);
  1212. if (status == -1 && errno == ENOEXEC) {
  1213. *argv = (char *)prog;
  1214. *--argv = (char *)"sh";
  1215. status = spawnv(P_NOWAIT, "/bin/sh", (const char **)argv);
  1216. after_exec();
  1217. if (status == -1) errno = ENOEXEC;
  1218. }
  1219. rb_last_status_set(status == -1 ? 127 : status, 0);
  1220. return status;
  1221. }
  1222. #endif
  1223. static rb_pid_t
  1224. proc_spawn_cmd(char **argv, VALUE prog, struct rb_execarg *eargp)
  1225. {
  1226. rb_pid_t pid = -1;
  1227. if (argv[0]) {
  1228. #if defined(_WIN32)
  1229. DWORD flags = 0;
  1230. if (eargp->new_pgroup_given && eargp->new_pgroup_flag) {
  1231. flags = CREATE_NEW_PROCESS_GROUP;
  1232. }
  1233. pid = rb_w32_aspawn_flags(P_NOWAIT, prog ? RSTRING_PTR(prog) : 0, argv, flags);
  1234. #else
  1235. pid = proc_spawn_cmd_internal(argv, prog ? RSTRING_PTR(prog) : 0);
  1236. #endif
  1237. }
  1238. return pid;
  1239. }
  1240. #if defined(_WIN32)
  1241. #define proc_spawn_sh(str) rb_w32_spawn(P_NOWAIT, (str), 0)
  1242. #else
  1243. static rb_pid_t
  1244. proc_spawn_sh(char *str)
  1245. {
  1246. char fbuf[MAXPATHLEN];
  1247. rb_pid_t status;
  1248. char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
  1249. before_exec();
  1250. status = spawnl(P_NOWAIT, (shell ? shell : "/bin/sh"), "sh", "-c", str, (char*)NULL);
  1251. rb_last_status_set(status == -1 ? 127 : status, 0);
  1252. after_exec();
  1253. return status;
  1254. }
  1255. #endif
  1256. #endif
  1257. static VALUE
  1258. hide_obj(VALUE obj)
  1259. {
  1260. RBASIC(obj)->klass = 0;
  1261. return obj;
  1262. }
  1263. static VALUE
  1264. check_exec_redirect_fd(VALUE v, int iskey)
  1265. {
  1266. VALUE tmp;
  1267. int fd;
  1268. if (FIXNUM_P(v)) {
  1269. fd = FIX2INT(v);
  1270. }
  1271. else if (SYMBOL_P(v)) {
  1272. ID id = SYM2ID(v);
  1273. if (id == rb_intern("in"))
  1274. fd = 0;
  1275. else if (id == rb_intern("out"))
  1276. fd = 1;
  1277. else if (id == rb_intern("err"))
  1278. fd = 2;
  1279. else
  1280. goto wrong;
  1281. }
  1282. else if (!NIL_P(tmp = rb_check_convert_type(v, T_FILE, "IO", "to_io"))) {
  1283. rb_io_t *fptr;
  1284. GetOpenFile(tmp, fptr);
  1285. if (fptr->tied_io_for_writing)
  1286. rb_raise(rb_eArgError, "duplex IO redirection");
  1287. fd = fptr->fd;
  1288. }
  1289. else {
  1290. rb_raise(rb_eArgError, "wrong exec redirect");
  1291. }
  1292. if (fd < 0) {
  1293. wrong:
  1294. rb_raise(rb_eArgError, "negative file descriptor");
  1295. }
  1296. #ifdef _WIN32
  1297. else if (fd >= 3 && iskey) {
  1298. rb_raise(rb_eArgError, "wrong file descriptor (%d)", fd);
  1299. }
  1300. #endif
  1301. return INT2FIX(fd);
  1302. }
  1303. static VALUE
  1304. check_exec_redirect1(VALUE ary, VALUE key, VALUE param)
  1305. {
  1306. if (ary == Qfalse) {
  1307. ary = hide_obj(rb_ary_new());
  1308. }
  1309. if (!RB_TYPE_P(key, T_ARRAY)) {
  1310. VALUE fd = check_exec_redirect_fd(key, !NIL_P(param));
  1311. rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
  1312. }
  1313. else {
  1314. int i, n=0;
  1315. for (i = 0 ; i < RARRAY_LEN(key); i++) {
  1316. VALUE v = RARRAY_PTR(key)[i];
  1317. VALUE fd = check_exec_redirect_fd(v, !NIL_P(param));
  1318. rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
  1319. n++;
  1320. }
  1321. }
  1322. return ary;
  1323. }
  1324. static void
  1325. check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
  1326. {
  1327. VALUE param;
  1328. VALUE path, flags, perm;
  1329. VALUE tmp;
  1330. ID id;
  1331. switch (TYPE(val)) {
  1332. case T_SYMBOL:
  1333. id = SYM2ID(val);
  1334. if (id == rb_intern("close")) {
  1335. param = Qnil;
  1336. eargp->fd_close = check_exec_redirect1(eargp->fd_close, key, param);
  1337. }
  1338. else if (id == rb_intern("in")) {
  1339. param = INT2FIX(0);
  1340. eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
  1341. }
  1342. else if (id == rb_intern("out")) {
  1343. param = INT2FIX(1);
  1344. eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
  1345. }
  1346. else if (id == rb_intern("err")) {
  1347. param = INT2FIX(2);
  1348. eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
  1349. }
  1350. else {
  1351. rb_raise(rb_eArgError, "wrong exec redirect symbol: %s",
  1352. rb_id2name(id));
  1353. }
  1354. break;
  1355. case T_FILE:
  1356. io:
  1357. val = check_exec_redirect_fd(val, 0);
  1358. /* fall through */
  1359. case T_FIXNUM:
  1360. param = val;
  1361. eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
  1362. break;
  1363. case T_ARRAY:
  1364. path = rb_ary_entry(val, 0);
  1365. if (RARRAY_LEN(val) == 2 && SYMBOL_P(path) &&
  1366. SYM2ID(path) == rb_intern("child")) {
  1367. param = check_exec_redirect_fd(rb_ary_entry(val, 1), 0);
  1368. eargp->fd_dup2_child = check_exec_redirect1(eargp->fd_dup2_child, key, param);
  1369. }
  1370. else {
  1371. FilePathValue(path);
  1372. flags = rb_ary_entry(val, 1);
  1373. if (NIL_P(flags))
  1374. flags = INT2NUM(O_RDONLY);
  1375. else if (RB_TYPE_P(flags, T_STRING))
  1376. flags = INT2NUM(rb_io_modestr_oflags(StringValueCStr(flags)));
  1377. else
  1378. flags = rb_to_int(flags);
  1379. perm = rb_ary_entry(val, 2);
  1380. perm = NIL_P(perm) ? INT2FIX(0644) : rb_to_int(perm);
  1381. param = hide_obj(rb_ary_new3(3, hide_obj(rb_str_dup(path)),
  1382. flags, perm));
  1383. eargp->fd_open = check_exec_redirect1(eargp->fd_open, key, param);
  1384. }
  1385. break;
  1386. case T_STRING:
  1387. path = val;
  1388. FilePathValue(path);
  1389. if (RB_TYPE_P(key, T_FILE))
  1390. key = check_exec_redirect_fd(key, 1);
  1391. if (FIXNUM_P(key) && (FIX2INT(key) == 1 || FIX2INT(key) == 2))
  1392. flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
  1393. else
  1394. flags = INT2NUM(O_RDONLY);
  1395. perm = INT2FIX(0644);
  1396. param = hide_obj(rb_ary_new3(3, hide_obj(rb_str_dup(path)),
  1397. flags, perm));
  1398. eargp->fd_open = check_exec_redirect1(eargp->fd_open, key, param);
  1399. break;
  1400. default:
  1401. tmp = val;
  1402. val = rb_io_check_io(tmp);
  1403. if (!NIL_P(val)) goto io;
  1404. rb_raise(rb_eArgError, "wrong exec redirect action");
  1405. }
  1406. }
  1407. #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
  1408. static int rlimit_type_by_lname(const char *name);
  1409. #endif
  1410. int
  1411. rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
  1412. {
  1413. struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
  1414. ID id;
  1415. #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
  1416. int rtype;
  1417. #endif
  1418. rb_secure(2);
  1419. switch (TYPE(key)) {
  1420. case T_SYMBOL:
  1421. id = SYM2ID(key);
  1422. #ifdef HAVE_SETPGID
  1423. if (id == rb_intern("pgroup")) {
  1424. pid_t pgroup;
  1425. if (eargp->pgroup_given) {
  1426. rb_raise(rb_eArgError, "pgroup option specified twice");
  1427. }
  1428. if (!RTEST(val))
  1429. pgroup = -1; /* asis(-1) means "don't call setpgid()". */
  1430. else if (val == Qtrue)
  1431. pgroup = 0; /* new process group. */
  1432. else {
  1433. pgroup = NUM2PIDT(val);
  1434. if (pgroup < 0) {
  1435. rb_raise(rb_eArgError, "negative process group ID : %ld", (long)pgroup);
  1436. }
  1437. }
  1438. eargp->pgroup_given = 1;
  1439. eargp->pgroup_pgid = pgroup;
  1440. }
  1441. else
  1442. #endif
  1443. #ifdef _WIN32
  1444. if (id == rb_intern("new_pgroup")) {
  1445. if (eargp->new_pgroup_given) {
  1446. rb_raise(rb_eArgError, "new_pgroup option specified twice");
  1447. }
  1448. eargp->new_pgroup_given = 1;
  1449. eargp->new_pgroup_flag = RTEST(val) ? 1 : 0;
  1450. }
  1451. else
  1452. #endif
  1453. #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
  1454. if (strncmp("rlimit_", rb_id2name(id), 7) == 0 &&
  1455. (rtype = rlimit_type_by_lname(rb_id2name(id)+7)) != -1) {
  1456. VALUE ary = eargp->rlimit_limits;
  1457. VALUE tmp, softlim, hardlim;
  1458. if (eargp->rlimit_limits == Qfalse)
  1459. ary = eargp->rlimit_limits = hide_obj(rb_ary_new());
  1460. else
  1461. ary = eargp->rlimit_limits;
  1462. tmp = rb_check_array_type(val);
  1463. if (!NIL_P(tmp)) {
  1464. if (RARRAY_LEN(tmp) == 1)
  1465. softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0));
  1466. else if (RARRAY_LEN(tmp) == 2) {
  1467. softlim = rb_to_int(rb_ary_entry(tmp, 0));
  1468. hardlim = rb_to_int(rb_ary_entry(tmp, 1));
  1469. }
  1470. else {
  1471. rb_raise(rb_eArgError, "wrong exec rlimit option");
  1472. }
  1473. }
  1474. else {
  1475. softlim = hardlim = rb_to_int(val);
  1476. }
  1477. tmp = hide_obj(rb_ary_new3(3, INT2NUM(rtype), softlim, hardlim));
  1478. rb_ary_push(ary, tmp);
  1479. }
  1480. else
  1481. #endif
  1482. if (id == rb_intern("unsetenv_others")) {
  1483. if (eargp->unsetenv_others_given) {
  1484. rb_raise(rb_eArgError, "unsetenv_others option specified twice");
  1485. }
  1486. eargp->unsetenv_others_given = 1;
  1487. eargp->unsetenv_others_do = RTEST(val) ? 1 : 0;
  1488. }
  1489. else if (id == rb_intern("chdir")) {
  1490. if (eargp->chdir_given) {
  1491. rb_raise(rb_eArgError, "chdir option specified twice");
  1492. }
  1493. FilePathValue(val);
  1494. eargp->chdir_given = 1;
  1495. eargp->chdir_dir = hide_obj(rb_str_dup(val));
  1496. }
  1497. else if (id == rb_intern("umask")) {
  1498. mode_t cmask = NUM2MODET(val);
  1499. if (eargp->umask_given) {
  1500. rb_raise(rb_eArgError, "umask option specified twice");
  1501. }
  1502. eargp->umask_given = 1;
  1503. eargp->umask_mask = cmask;
  1504. }
  1505. else if (id == rb_intern("close_others")) {
  1506. if (eargp->close_others_given) {
  1507. rb_raise(rb_eArgError, "close_others option specified twice");
  1508. }
  1509. eargp->close_others_given = 1;
  1510. eargp->close_others_do = RTEST(val) ? 1 : 0;
  1511. }
  1512. else if (id == rb_intern("in")) {
  1513. key = INT2FIX(0);
  1514. goto redirect;
  1515. }
  1516. else if (id == rb_intern("out")) {
  1517. key = INT2FIX(1);
  1518. goto redirect;
  1519. }
  1520. else if (id == rb_intern("err")) {
  1521. key = INT2FIX(2);
  1522. goto redirect;
  1523. }
  1524. else if (id == rb_intern("uid")) {
  1525. #ifdef HAVE_SETUID
  1526. if (eargp->uid_given) {
  1527. rb_raise(rb_eArgError, "uid option specified twice");
  1528. }
  1529. check_uid_switch();
  1530. {
  1531. PREPARE_GETPWNAM;
  1532. eargp->uid = OBJ2UID(val);
  1533. eargp->uid_given = 1;
  1534. }
  1535. #else
  1536. rb_raise(rb_eNotImpError,
  1537. "uid option is unimplemented on this machine");
  1538. #endif
  1539. }
  1540. else if (id == rb_intern("gid")) {
  1541. #ifdef HAVE_SETGID
  1542. if (eargp->gid_given) {
  1543. rb_raise(rb_eArgError, "gid option specified twice");
  1544. }
  1545. check_gid_switch();
  1546. {
  1547. PREPARE_GETGRNAM;
  1548. eargp->gid = OBJ2GID(val);
  1549. eargp->gid_given = 1;
  1550. }
  1551. #else
  1552. rb_raise(rb_eNotImpError,
  1553. "gid option is unimplemented on this machine");
  1554. #endif
  1555. }
  1556. else {
  1557. return ST_STOP;
  1558. }
  1559. break;
  1560. case T_FIXNUM:
  1561. case T_FILE:
  1562. case T_ARRAY:
  1563. redirect:
  1564. check_exec_redirect(key, val, eargp);
  1565. break;
  1566. default:
  1567. return ST_STOP;
  1568. }
  1569. RB_GC_GUARD(execarg_obj);
  1570. return ST_CONTINUE;
  1571. }
  1572. int
  1573. rb_exec_arg_addopt(struct rb_exec_arg *e, VALUE key, VALUE val)
  1574. {
  1575. return rb_execarg_addopt(e->execarg_obj, key, val);
  1576. }
  1577. static int
  1578. check_exec_options_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
  1579. {
  1580. VALUE key = (VALUE)st_key;
  1581. VALUE val = (VALUE)st_val;
  1582. VALUE execarg_obj = (VALUE)arg;
  1583. if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) {
  1584. if (SYMBOL_P(key))
  1585. rb_raise(rb_eArgError, "wrong exec option symbol: %"PRIsVALUE,
  1586. key);
  1587. rb_raise(rb_eArgError, "wrong exec option");
  1588. }
  1589. return ST_CONTINUE;
  1590. }
  1591. static int
  1592. check_exec_options_i_extract(st_data_t st_key, st_data_t st_val, st_data_t arg)
  1593. {
  1594. VALUE key = (VALUE)st_key;
  1595. VALUE val = (VALUE)st_val;
  1596. VALUE *args = (VALUE *)arg;
  1597. VALUE execarg_obj = args[0];
  1598. if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) {
  1599. VALUE nonopts = args[1];
  1600. if (NIL_P(nonopts)) args[1] = nonopts = rb_hash_new();
  1601. rb_hash_aset(nonopts, key, val);
  1602. }
  1603. return ST_CONTINUE;
  1604. }
  1605. static int
  1606. check_exec_fds_1(struct rb_execarg *eargp, VALUE h, int maxhint, VALUE ary)
  1607. {
  1608. long i;
  1609. if (ary != Qfalse) {
  1610. for (i = 0; i < RARRAY_LEN(ary); i++) {
  1611. VALUE elt = RARRAY_PTR(ary)[i];
  1612. int fd = FIX2INT(RARRAY_PTR(elt)[0]);
  1613. if (RTEST(rb_hash_lookup(h, INT2FIX(fd)))) {
  1614. rb_raise(rb_eArgError, "fd %d specified twice", fd);
  1615. }
  1616. if (ary == eargp->fd_open || ary == eargp->fd_dup2)
  1617. rb_hash_aset(h, INT2FIX(fd), Qtrue);
  1618. else if (ary == eargp->fd_dup2_child)
  1619. rb_hash_aset(h, INT2FIX(fd), RARRAY_PTR(elt)[1]);
  1620. else /* ary == eargp->fd_close */
  1621. rb_hash_aset(h, INT2FIX(fd), INT2FIX(-1));
  1622. if (maxhint < fd)
  1623. maxhint = fd;
  1624. if (ary == eargp->fd_dup2 || ary == eargp->fd_dup2_child) {
  1625. fd = FIX2INT(RARRAY_PTR(elt)[1]);
  1626. if (maxhint < fd)
  1627. maxhint = fd;
  1628. }
  1629. }
  1630. }
  1631. return maxhint;
  1632. }
  1633. static VALUE
  1634. check_exec_fds(struct rb_execarg *eargp)
  1635. {
  1636. VALUE h = rb_hash_new();
  1637. VALUE ary;
  1638. int maxhint = -1;
  1639. long i;
  1640. maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_dup2);
  1641. maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_close);
  1642. maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_open);
  1643. maxhint = check_exec_fds_1(eargp, h, maxhint, eargp->fd_dup2_child);
  1644. if (eargp->fd_dup2_child) {
  1645. ary = eargp->fd_dup2_child;
  1646. for (i = 0; i < RARRAY_LEN(ary); i++) {
  1647. VALUE elt = RARRAY_PTR(ary)[i];
  1648. int newfd = FIX2INT(RARRAY_PTR(elt)[0]);
  1649. int oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
  1650. int lastfd = oldfd;
  1651. VALUE val = rb_hash_lookup(h, INT2FIX(lastfd));
  1652. long depth = 0;
  1653. while (FIXNUM_P(val) && 0 <= FIX2INT(val)) {
  1654. lastfd = FIX2INT(val);
  1655. val = rb_hash_lookup(h, val);
  1656. if (RARRAY_LEN(ary) < depth)
  1657. rb_raise(rb_eArgError, "cyclic child fd redirection from %d", oldfd);
  1658. depth++;
  1659. }
  1660. if (val != Qtrue)
  1661. rb_raise(rb_eArgError, "child fd %d is not redirected", oldfd);
  1662. if (oldfd != lastfd) {
  1663. VALUE val2;
  1664. rb_ary_store(elt, 1, INT2FIX(lastfd));
  1665. rb_hash_aset(h, INT2FIX(newfd), INT2FIX(lastfd));
  1666. val = INT2FIX(oldfd);
  1667. while (FIXNUM_P(val2 = rb_hash_lookup(h, val))) {
  1668. rb_hash_aset(h, val, INT2FIX(lastfd));
  1669. val = val2;
  1670. }
  1671. }
  1672. }
  1673. }
  1674. eargp->close_others_maxhint = maxhint;
  1675. return h;
  1676. }
  1677. static void
  1678. rb_check_exec_options(VALUE opthash, VALUE execarg_obj)
  1679. {
  1680. if (RHASH_EMPTY_P(opthash))
  1681. return;
  1682. st_foreach(RHASH_TBL(opthash), check_exec_options_i, (st_data_t)execarg_obj);
  1683. }
  1684. VALUE
  1685. rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
  1686. {
  1687. VALUE args[2];
  1688. if (RHASH_EMPTY_P(opthash))
  1689. return Qnil;
  1690. args[0] = execarg_obj;
  1691. args[1] = Qnil;
  1692. st_foreach(RHASH_TBL(opthash), check_exec_options_i_extract, (st_data_t)args);
  1693. return args[1];
  1694. }
  1695. static int
  1696. check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
  1697. {
  1698. VALUE key = (VALUE)st_key;
  1699. VALUE val = (VALUE)st_val;
  1700. VALUE env = (VALUE)arg;
  1701. char *k;
  1702. k = StringValueCStr(key);
  1703. if (strchr(k, '='))
  1704. rb_raise(rb_eArgError, "environment name contains a equal : %s", k);
  1705. if (!NIL_P(val))
  1706. StringValueCStr(val);
  1707. rb_ary_push(env, hide_obj(rb_assoc_new(key, val)));
  1708. return ST_CONTINUE;
  1709. }
  1710. static VALUE
  1711. rb_check_exec_env(VALUE hash)
  1712. {
  1713. VALUE env;
  1714. env = hide_obj(rb_ary_new());
  1715. st_foreach(RHASH_TBL(hash), check_exec_env_i, (st_data_t)env);
  1716. return env;
  1717. }
  1718. static VALUE
  1719. rb_check_argv(int argc, VALUE *argv)
  1720. {
  1721. VALUE tmp, prog;
  1722. int i;
  1723. const char *name = 0;
  1724. rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
  1725. prog = 0;
  1726. tmp = rb_check_array_type(argv[0]);
  1727. if (!NIL_P(tmp)) {
  1728. if (RARRAY_LEN(tmp) != 2) {
  1729. rb_raise(rb_eArgError, "wrong first argument");
  1730. }
  1731. prog = RARRAY_PTR(tmp)[0];
  1732. argv[0] = RARRAY_PTR(tmp)[1];
  1733. SafeStringValue(prog);
  1734. StringValueCStr(prog);
  1735. prog = rb_str_new_frozen(prog);
  1736. name = RSTRING_PTR(prog);
  1737. }
  1738. for (i = 0; i < argc; i++) {
  1739. SafeStringValue(argv[i]);
  1740. argv[i] = rb_str_new_frozen(argv[i]);
  1741. StringValueCStr(argv[i]);
  1742. }
  1743. security(name ? name : RSTRING_PTR(argv[0]));
  1744. return prog;
  1745. }
  1746. static VALUE
  1747. rb_exec_getargs(int *argc_p, VALUE **argv_p, int accept_shell, VALUE *env_ret, VALUE *opthash_ret)
  1748. {
  1749. VALUE hash, prog;
  1750. if (0 < *argc_p) {
  1751. hash = rb_check_hash_type((*argv_p)[*argc_p-1]);
  1752. if (!NIL_P(hash)) {
  1753. *opthash_ret = hash;
  1754. (*argc_p)--;
  1755. }
  1756. }
  1757. if (0 < *argc_p) {
  1758. hash = rb_check_hash_type((*argv_p)[0]);
  1759. if (!NIL_P(hash)) {
  1760. *env_ret = hash;
  1761. (*argc_p)--;
  1762. (*argv_p)++;
  1763. }
  1764. }
  1765. prog = rb_check_argv(*argc_p, *argv_p);
  1766. if (!prog) {
  1767. prog = (*argv_p)[0];
  1768. if (accept_shell && *argc_p == 1) {
  1769. *argc_p = 0;
  1770. *argv_p = 0;
  1771. }
  1772. }
  1773. return prog;
  1774. }
  1775. #ifndef _WIN32
  1776. struct string_part {
  1777. const char *ptr;
  1778. size_t len;
  1779. };
  1780. static int
  1781. compare_posix_sh(const void *key, const void *el)
  1782. {
  1783. const struct string_part *word = key;
  1784. int ret = strncmp(word->ptr, el, word->len);
  1785. if (!ret && ((const char *)el)[word->len]) ret = -1;
  1786. return ret;
  1787. }
  1788. #endif
  1789. static void
  1790. rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VALUE execarg_obj)
  1791. {
  1792. struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
  1793. char fbuf[MAXPATHLEN];
  1794. MEMZERO(eargp, struct rb_execarg, 1);
  1795. if (!NIL_P(opthash)) {
  1796. rb_check_exec_options(opthash, execarg_obj);
  1797. }
  1798. if (!NIL_P(env)) {
  1799. env = rb_check_exec_env(env);
  1800. eargp->env_modification = env;
  1801. }
  1802. eargp->use_shell = argc == 0;
  1803. if (eargp->use_shell)
  1804. eargp->invoke.sh.shell_script = prog;
  1805. else
  1806. eargp->invoke.cmd.command_name = prog;
  1807. #ifndef _WIN32
  1808. if (eargp->use_shell) {
  1809. static const char posix_sh_cmds[][9] = {
  1810. "!", /* reserved */
  1811. ".", /* special built-in */
  1812. ":", /* special built-in */
  1813. "break", /* special built-in */
  1814. "case", /* reserved */
  1815. "continue", /* special built-in */
  1816. "do", /* reserved */
  1817. "done", /* reserved */
  1818. "elif", /* reserved */
  1819. "else", /* reserved */
  1820. "esac", /* reserved */
  1821. "eval", /* special built-in */
  1822. "exec", /* special built-in */
  1823. "exit", /* special built-in */
  1824. "export", /* special built-in */
  1825. "fi", /* reserved */
  1826. "for", /* reserved */
  1827. "if", /* reserved */
  1828. "in", /* reserved */
  1829. "readonly", /* special built-in */
  1830. "return", /* special built-in */
  1831. "set", /* special built-in */
  1832. "shift", /* special built-in */
  1833. "then", /* reserved */
  1834. "times", /* special built-in */
  1835. "trap", /* special built-in */
  1836. "unset", /* special built-in */
  1837. "until", /* reserved */
  1838. "while", /* reserved */
  1839. };
  1840. const char *p;
  1841. struct string_part first = {0, 0};
  1842. int has_meta = 0;
  1843. /*
  1844. * meta characters:
  1845. *
  1846. * * Pathname Expansion
  1847. * ? Pathname Expansion
  1848. * {} Grouping Commands
  1849. * [] Pathname Expansion
  1850. * <> Redirection
  1851. * () Grouping Commands
  1852. * ~ Tilde Expansion
  1853. * & AND Lists, Asynchronous Lists
  1854. * | OR Lists, Pipelines
  1855. * \ Escape Character
  1856. * $ Parameter Expansion
  1857. * ; Sequential Lists
  1858. * ' Single-Quotes
  1859. * ` Command Substitution
  1860. * " Double-Quotes
  1861. * \n Lists
  1862. *
  1863. * # Comment
  1864. * = Assignment preceding command name
  1865. * % (used in Parameter Expansion)
  1866. */
  1867. for (p = RSTRING_PTR(prog); *p; p++) {
  1868. if (*p == ' ' || *p == '\t') {
  1869. if (first.ptr && !first.len) first.len = p - first.ptr;
  1870. }
  1871. else {
  1872. if (!first.ptr) first.ptr = p;
  1873. }
  1874. if (!has_meta && strchr("*?{}[]<>()~&|\\$;'`\"\n#", *p))
  1875. has_meta = 1;
  1876. if (!first.len) {
  1877. if (*p == '=') {
  1878. has_meta = 1;
  1879. }
  1880. else if (*p == '/') {
  1881. first.len = 0x100; /* longer than any posix_sh_cmds */
  1882. }
  1883. }
  1884. if (has_meta)
  1885. break;
  1886. }
  1887. if (!has_meta && first.ptr) {
  1888. if (!first.len) first.len = p - first.ptr;
  1889. if (first.len > 0 && first.len <= sizeof(posix_sh_cmds[0]) &&
  1890. bsearch(&first, posix_sh_cmds, numberof(posix_sh_cmds), sizeof(posix_sh_cmds[0]), compare_posix_sh))
  1891. has_meta = 1;
  1892. }
  1893. if (!has_meta) {
  1894. /* avoid shell since no shell meta charactor found. */
  1895. eargp->use_shell = 0;
  1896. }
  1897. if (!eargp->use_shell) {
  1898. VALUE argv_buf;
  1899. argv_buf = hide_obj(rb_str_buf_new(0));
  1900. p = RSTRING_PTR(prog);
  1901. while (*p) {
  1902. while (*p == ' ' || *p == '\t')
  1903. p++;
  1904. if (*p) {
  1905. const char *w = p;
  1906. while (*p && *p != ' ' && *p != '\t')
  1907. p++;
  1908. rb_str_buf_cat(argv_buf, w, p-w);
  1909. rb_str_buf_cat(argv_buf, "", 1); /* append '\0' */
  1910. }
  1911. }
  1912. eargp->invoke.cmd.argv_buf = argv_buf;
  1913. eargp->invoke.cmd.command_name = hide_obj(rb_str_new_cstr(RSTRING_PTR(argv_buf)));
  1914. }
  1915. }
  1916. #endif
  1917. if (!eargp->use_shell) {
  1918. const char *abspath;
  1919. abspath = dln_find_exe_r(RSTRING_PTR(eargp->invoke.cmd.command_name), 0, fbuf, sizeof(fbuf));
  1920. if (abspath)
  1921. eargp->invoke.cmd.command_abspath = rb_str_new_cstr(abspath);
  1922. else
  1923. eargp->invoke.cmd.command_abspath = Qnil;
  1924. }
  1925. if (!eargp->use_shell && !eargp->invoke.cmd.argv_buf) {
  1926. int i;
  1927. VALUE argv_buf;
  1928. argv_buf = rb_str_buf_new(0);
  1929. hide_obj(argv_buf);
  1930. for (i = 0; i < argc; i++) {
  1931. rb_str_buf_cat2(argv_buf, StringValueCStr(argv[i]));
  1932. rb_str_buf_cat(argv_buf, "", 1); /* append '\0' */
  1933. }
  1934. eargp->invoke.cmd.argv_buf = argv_buf;
  1935. }
  1936. if (!eargp->use_shell) {
  1937. const char *p, *ep, *null=NULL;
  1938. VALUE argv_str;
  1939. argv_str = hide_obj(rb_str_buf_new(sizeof(char*) * (argc + 2)));
  1940. rb_str_buf_cat(argv_str, (char *)&null, sizeof(null)); /* place holder for /bin/sh of try_with_sh. */
  1941. p = RSTRING_PTR(eargp->invoke.cmd.argv_buf);
  1942. ep = p + RSTRING_LEN(eargp->invoke.cmd.argv_buf);
  1943. while (p < ep) {
  1944. rb_str_buf_cat(argv_str, (char *)&p, sizeof(p));
  1945. p += strlen(p) + 1;
  1946. }
  1947. rb_str_buf_cat(argv_str, (char *)&null, sizeof(null)); /* terminator for execve. */
  1948. eargp->invoke.cmd.argv_str = argv_str;
  1949. }
  1950. RB_GC_GUARD(execarg_obj);
  1951. }
  1952. VALUE
  1953. rb_execarg_new(int argc, VALUE *argv, int accept_shell)
  1954. {
  1955. VALUE execarg_obj;
  1956. struct rb_execarg *eargp;
  1957. execarg_obj = TypedData_Make_Struct(rb_cData, struct rb_execarg, &exec_arg_data_type, eargp);
  1958. hide_obj(execarg_obj);
  1959. rb_execarg_init(argc, argv, accept_shell, execarg_obj);
  1960. return execarg_obj;
  1961. }
  1962. struct rb_execarg
  1963. *rb_execarg_get(VALUE execarg_obj)
  1964. {
  1965. struct rb_execarg *eargp;
  1966. TypedData_Get_Struct(execarg_obj, struct rb_execarg, &exec_arg_data_type, eargp);
  1967. return eargp;
  1968. }
  1969. VALUE
  1970. rb_execarg_init(int argc, VALUE *argv, int accept_shell, VALUE execarg_obj)
  1971. {
  1972. struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
  1973. VALUE prog, ret;
  1974. VALUE env = Qnil, opthash = Qnil;
  1975. prog = rb_exec_getargs(&argc, &argv, accept_shell, &env, &opthash);
  1976. rb_exec_fillarg(prog, argc, argv, env, opthash, execarg_obj);
  1977. ret = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
  1978. RB_GC_GUARD(execarg_obj);
  1979. return ret;
  1980. }
  1981. VALUE
  1982. rb_exec_arg_init(int argc, VALUE *argv, int accept_shell, struct rb_exec_arg *e)
  1983. {
  1984. return rb_execarg_init(argc, argv, accept_shell, e->execarg_obj);
  1985. }
  1986. void
  1987. rb_execarg_setenv(VALUE execarg_obj, VALUE env)
  1988. {
  1989. struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
  1990. env = !NIL_P(env) ? rb_check_exec_env(env) : Qfalse;
  1991. eargp->env_modification = env;
  1992. }
  1993. static int
  1994. fill_envp_buf_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
  1995. {
  1996. VALUE key = (VALUE)st_key;
  1997. VALUE val = (VALUE)st_val;
  1998. VALUE envp_buf = (VALUE)arg;
  1999. rb_str_buf_cat2(envp_buf, StringValueCStr(key));
  2000. rb_str_buf_cat2(envp_buf, "=");
  2001. rb_str_buf_cat2(envp_buf, StringValueCStr(val));
  2002. rb_str_buf_cat(envp_buf, "", 1); /* append '\0' */
  2003. return ST_CONTINUE;
  2004. }
  2005. static long run_exec_dup2_tmpbuf_size(long n);
  2006. void
  2007. rb_execarg_fixup(VALUE execarg_obj)
  2008. {
  2009. struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
  2010. int unsetenv_others;
  2011. VALUE envopts;
  2012. VALUE ary;
  2013. eargp->redirect_fds = check_exec_fds(eargp);
  2014. ary = eargp->fd_dup2;
  2015. if (ary != Qfalse) {
  2016. size_t len = run_exec_dup2_tmpbuf_size(RARRAY_LEN(ary));
  2017. VALUE tmpbuf = hide_obj(rb_str_new(0, len));
  2018. rb_str_set_len(tmpbuf, len);
  2019. eargp->dup2_tmpbuf = tmpbuf;
  2020. }
  2021. unsetenv_others = eargp->unsetenv_others_given && eargp->unsetenv_others_do;
  2022. envopts = eargp->env_modification;
  2023. if (unsetenv_others || envopts != Qfalse) {
  2024. VALUE envtbl, envp_str, envp_buf;
  2025. char *p, *ep;
  2026. if (unsetenv_others) {
  2027. envtbl = rb_hash_new();
  2028. }
  2029. else {
  2030. envtbl = rb_const_get(rb_cObject, rb_intern("ENV"));
  2031. envtbl = rb_convert_type(envtbl, T_HASH, "Hash", "to_hash");
  2032. }
  2033. hide_obj(envtbl);
  2034. if (envopts != Qfalse) {
  2035. st_table *stenv = RHASH_TBL(envtbl);
  2036. long i;
  2037. for (i = 0; i < RARRAY_LEN(envopts); i++) {
  2038. VALUE pair = RARRAY_PTR(envopts)[i];
  2039. VALUE key = RARRAY_PTR(pair)[0];
  2040. VALUE val = RARRAY_PTR(pair)[1];
  2041. if (NIL_P(val)) {
  2042. st_data_t stkey = (st_data_t)key;
  2043. st_delete(stenv, &stkey, NULL);
  2044. }
  2045. else {
  2046. st_insert(stenv, (st_data_t)key, (st_data_t)val);
  2047. }
  2048. }
  2049. }
  2050. envp_buf = rb_str_buf_new(0);
  2051. hide_obj(envp_buf);
  2052. st_foreach(RHASH_TBL(envtbl), fill_envp_buf_i, (st_data_t)envp_buf);
  2053. envp_str = rb_str_buf_new(sizeof(char*) * (RHASH_SIZE(envtbl) + 1));
  2054. hide_obj(envp_str);
  2055. p = RSTRING_PTR(envp_buf);
  2056. ep = p + RSTRING_LEN(envp_buf);
  2057. while (p < ep) {
  2058. rb_str_buf_cat(envp_str, (char *)&p, sizeof(p));
  2059. p += strlen(p) + 1;
  2060. }
  2061. p = NULL;
  2062. rb_str_buf_cat(envp_str, (char *)&p, sizeof(p));
  2063. eargp->envp_str = envp_str;
  2064. eargp->envp_buf = envp_buf;
  2065. /*
  2066. char **tmp_envp = (char **)RSTRING_PTR(envp_str);
  2067. while (*tmp_envp) {
  2068. printf("%s\n", *tmp_envp);
  2069. tmp_envp++;
  2070. }
  2071. */
  2072. }
  2073. RB_GC_GUARD(execarg_obj);
  2074. }
  2075. void
  2076. rb_exec_arg_fixup(struct rb_exec_arg *e)
  2077. {
  2078. rb_execarg_fixup(e->execarg_obj);
  2079. }
  2080. static int rb_exec_without_timer_thread(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen);
  2081. /*
  2082. * call-seq:
  2083. * exec([env,] command... [,options])
  2084. *
  2085. * Replaces the current process by running the given external _command_.
  2086. * _command..._ is one of following forms.
  2087. *
  2088. * commandline : command line string which is passed to the standard shell
  2089. * cmdname, arg1, ... : command name and one or more arguments (no shell)
  2090. * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
  2091. *
  2092. * If single string is given as the command,
  2093. * it is taken as a command line that is subject to shell expansion before being executed.
  2094. *
  2095. * The standard shell means always <code>"/bin/sh"</code> on Unix-like systems,
  2096. * <code>ENV["RUBYSHELL"]</code> or <code>ENV["COMSPEC"]</code> on Windows NT series, and
  2097. * similar.
  2098. *
  2099. * If two or more +string+ given,
  2100. * the first is taken as a command name and
  2101. * the rest are passed as parameters to command with no shell expansion.
  2102. *
  2103. * If a two-element array at the beginning of the command,
  2104. * the first element is the command to be executed,
  2105. * and the second argument is used as the <code>argv[0]</code> value,
  2106. * which may show up in process listings.
  2107. *
  2108. * In order to execute the command, one of the <code>exec(2)</code>
  2109. * system calls is used, so the running command may inherit some of the environment
  2110. * of the original program (including open file descriptors).
  2111. * This behavior is modified by env and options.
  2112. * See <code>spawn</code> for details.
  2113. *
  2114. * Raises SystemCallError if the command couldn't execute (typically
  2115. * <code>Errno::ENOENT</code> when it was not found).
  2116. *
  2117. * This method modifies process attributes according to _options_
  2118. * (details described in <code>spawn</code>)
  2119. * before <code>exec(2)</code> system call.
  2120. * The modified attributes may be retained when <code>exec(2)</code> system call fails.
  2121. * For example, hard resource limits is not restorable.
  2122. * If it is not acceptable, consider to create a child process using <code>spawn</code> or <code>system</code>.
  2123. *
  2124. * exec "echo *" # echoes list of files in current directory
  2125. * # never get here
  2126. *
  2127. *
  2128. * exec "echo", "*" # echoes an asterisk
  2129. * # never get here
  2130. */
  2131. VALUE
  2132. rb_f_exec(int argc, VALUE *argv)
  2133. {
  2134. VALUE execarg_obj, fail_str;
  2135. struct rb_execarg *eargp;
  2136. #define CHILD_ERRMSG_BUFLEN 80
  2137. char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
  2138. execarg_obj = rb_execarg_new(argc, argv, TRUE);
  2139. eargp = rb_execarg_get(execarg_obj);
  2140. rb_execarg_fixup(execarg_obj);
  2141. fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
  2142. #if defined(__APPLE__) || defined(__HAIKU__)
  2143. rb_exec_without_timer_thread(eargp, errmsg, sizeof(errmsg));
  2144. #else
  2145. rb_exec_async_signal_safe(eargp, errmsg, sizeof(errmsg));
  2146. #endif
  2147. RB_GC_GUARD(execarg_obj);
  2148. if (errmsg[0])
  2149. rb_sys_fail(errmsg);
  2150. rb_sys_fail_str(fail_str);
  2151. return Qnil; /* dummy */
  2152. }
  2153. #define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
  2154. /*#define DEBUG_REDIRECT*/
  2155. #if defined(DEBUG_REDIRECT)
  2156. #include <stdarg.h>
  2157. static void
  2158. ttyprintf(const char *fmt, ...)
  2159. {
  2160. va_list ap;
  2161. FILE *tty;
  2162. int save = errno;
  2163. #ifdef _WIN32
  2164. tty = fopen("con", "w");
  2165. #else
  2166. tty = fopen("/dev/tty", "w");
  2167. #endif
  2168. if (!tty)
  2169. return;
  2170. va_start(ap, fmt);
  2171. vfprintf(tty, fmt, ap);
  2172. va_end(ap);
  2173. fclose(tty);
  2174. errno = save;
  2175. }
  2176. static int
  2177. redirect_dup(int oldfd)
  2178. {
  2179. int ret;
  2180. ret = dup(oldfd);
  2181. ttyprintf("dup(%d) => %d\n", oldfd, ret);
  2182. return ret;
  2183. }
  2184. #else
  2185. #define redirect_dup(oldfd) dup(oldfd)
  2186. #endif
  2187. #if defined(DEBUG_REDIRECT) || defined(_WIN32)
  2188. static int
  2189. redirect_dup2(int oldfd, int newfd)
  2190. {
  2191. int ret;
  2192. ret = dup2(oldfd, newfd);
  2193. if (newfd >= 0 && newfd <= 2)
  2194. SetStdHandle(newfd == 0 ? STD_INPUT_HANDLE : newfd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, (HANDLE)rb_w32_get_osfhandle(newfd));
  2195. #if defined(DEBUG_REDIRECT)
  2196. ttyprintf("dup2(%d, %d)\n", oldfd, newfd);
  2197. #endif
  2198. return ret;
  2199. }
  2200. #else
  2201. #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
  2202. #endif
  2203. #if defined(DEBUG_REDIRECT)
  2204. static int
  2205. redirect_close(int fd)
  2206. {
  2207. int ret;
  2208. ret = close(fd);
  2209. ttyprintf("close(%d)\n", fd);
  2210. return ret;
  2211. }
  2212. static int
  2213. redirect_open(const char *pathname, int flags, mode_t perm)
  2214. {
  2215. int ret;
  2216. ret = open(pathname, flags, perm);
  2217. ttyprintf("open(\"%s\", 0x%x, 0%o) => %d\n", pathname, flags, perm, ret);
  2218. return ret;
  2219. }
  2220. #else
  2221. #define redirect_close(fd) close(fd)
  2222. #define redirect_open(pathname, flags, perm) open((pathname), (flags), (perm))
  2223. #endif
  2224. static int
  2225. save_redirect_fd(int fd, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
  2226. {
  2227. if (sargp) {
  2228. VALUE newary;
  2229. int save_fd = redirect_dup(fd);
  2230. if (save_fd == -1) {
  2231. if (errno == EBADF)
  2232. return 0;
  2233. ERRMSG("dup");
  2234. return -1;
  2235. }
  2236. rb_update_max_fd(save_fd);
  2237. newary = sargp->fd_dup2;
  2238. if (newary == Qfalse) {
  2239. newary = hide_obj(rb_ary_new());
  2240. sargp->fd_dup2 = newary;
  2241. }
  2242. rb_ary_push(newary,
  2243. hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd))));
  2244. newary = sargp->fd_close;
  2245. if (newary == Qfalse) {
  2246. newary = hide_obj(rb_ary_new());
  2247. sargp->fd_close = newary;
  2248. }
  2249. rb_ary_push(newary, hide_obj(rb_assoc_new(INT2FIX(save_fd), Qnil)));
  2250. }
  2251. return 0;
  2252. }
  2253. static int
  2254. intcmp(const void *a, const void *b)
  2255. {
  2256. return *(int*)a - *(int*)b;
  2257. }
  2258. static int
  2259. intrcmp(const void *a, const void *b)
  2260. {
  2261. return *(int*)b - *(int*)a;
  2262. }
  2263. struct run_exec_dup2_fd_pair {
  2264. int oldfd;
  2265. int newfd;
  2266. long older_index;
  2267. long num_newer;
  2268. };
  2269. static long
  2270. run_exec_dup2_tmpbuf_size(long n)
  2271. {
  2272. return sizeof(struct run_exec_dup2_fd_pair) * n;
  2273. }
  2274. /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
  2275. static int
  2276. run_exec_dup2(VALUE ary, VALUE tmpbuf, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
  2277. {
  2278. long n, i;
  2279. int ret;
  2280. int extra_fd = -1;
  2281. struct run_exec_dup2_fd_pair *pairs = 0;
  2282. n = RARRAY_LEN(ary);
  2283. pairs = (struct run_exec_dup2_fd_pair *)RSTRING_PTR(tmpbuf);
  2284. /* initialize oldfd and newfd: O(n) */
  2285. for (i = 0; i < n; i++) {
  2286. VALUE elt = RARRAY_PTR(ary)[i];
  2287. pairs[i].oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
  2288. pairs[i].newfd = FIX2INT(RARRAY_PTR(elt)[0]); /* unique */
  2289. pairs[i].older_index = -1;
  2290. }
  2291. /* sort the table by oldfd: O(n log n) */
  2292. if (!sargp)
  2293. qsort(pairs, n, sizeof(struct run_exec_dup2_fd_pair), intcmp); /* hopefully async-signal-safe */
  2294. else
  2295. qsort(pairs, n, sizeof(struct run_exec_dup2_fd_pair), intrcmp);
  2296. /* initialize older_index and num_newer: O(n log n) */
  2297. for (i = 0; i < n; i++) {
  2298. int newfd = pairs[i].newfd;
  2299. struct run_exec_dup2_fd_pair key, *found;
  2300. key.oldfd = newfd;
  2301. found = bsearch(&key, pairs, n, sizeof(struct run_exec_dup2_fd_pair), intcmp); /* hopefully async-signal-safe */
  2302. pairs[i].num_newer = 0;
  2303. if (found) {
  2304. while (pairs < found && (found-1)->oldfd == newfd)
  2305. found--;
  2306. while (found < pairs+n && found->oldfd == newfd) {
  2307. pairs[i].num_newer++;
  2308. found->older_index = i;
  2309. found++;
  2310. }
  2311. }
  2312. }
  2313. /* non-cyclic redirection: O(n) */
  2314. for (i = 0; i < n; i++) {
  2315. long j = i;
  2316. while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
  2317. if (save_redirect_fd(pairs[j].newfd, sargp, errmsg, errmsg_buflen) < 0) /* async-signal-safe */
  2318. goto fail;
  2319. ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd); /* async-signal-safe */
  2320. if (ret == -1) {
  2321. ERRMSG("dup2");
  2322. goto fail;
  2323. }
  2324. rb_update_max_fd(pairs[j].newfd); /* async-signal-safe but don't need to call it in a child process. */
  2325. pairs[j].oldfd = -1;
  2326. j = pairs[j].older_index;
  2327. if (j != -1)
  2328. pairs[j].num_newer--;
  2329. }
  2330. }
  2331. /* cyclic redirection: O(n) */
  2332. for (i = 0; i < n; i++) {
  2333. long j;
  2334. if (pairs[i].oldfd == -1)
  2335. continue;
  2336. if (pairs[i].oldfd == pairs[i].newfd) { /* self cycle */
  2337. #ifdef F_GETFD
  2338. int fd = pairs[i].oldfd;
  2339. ret = fcntl(fd, F_GETFD); /* async-signal-safe */
  2340. if (ret == -1) {
  2341. ERRMSG("fcntl(F_GETFD)");
  2342. goto fail;
  2343. }
  2344. if (ret & FD_CLOEXEC) {
  2345. ret &= ~FD_CLOEXEC;
  2346. ret = fcntl(fd, F_SETFD, ret); /* async-signal-safe */
  2347. if (ret == -1) {
  2348. ERRMSG("fcntl(F_SETFD)");
  2349. goto fail;
  2350. }
  2351. }
  2352. #endif
  2353. pairs[i].oldfd = -1;
  2354. continue;
  2355. }
  2356. if (extra_fd == -1) {
  2357. extra_fd = redirect_dup(pairs[i].oldfd); /* async-signal-safe */
  2358. if (extra_fd == -1) {
  2359. ERRMSG("dup");
  2360. goto fail;
  2361. }
  2362. rb_update_max_fd(extra_fd);
  2363. }
  2364. else {
  2365. ret = redirect_dup2(pairs[i].oldfd, extra_fd); /* async-signal-safe */
  2366. if (ret == -1) {
  2367. ERRMSG("dup2");
  2368. goto fail;
  2369. }
  2370. rb_update_max_fd(extra_fd);
  2371. }
  2372. pairs[i].oldfd = extra_fd;
  2373. j = pairs[i].older_index;
  2374. pairs[i].older_index = -1;
  2375. while (j != -1) {
  2376. ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd); /* async-signal-safe */
  2377. if (ret == -1) {
  2378. ERRMSG("dup2");
  2379. goto fail;
  2380. }
  2381. rb_update_max_fd(ret);
  2382. pairs[j].oldfd = -1;
  2383. j = pairs[j].older_index;
  2384. }
  2385. }
  2386. if (extra_fd != -1) {
  2387. ret = redirect_close(extra_fd); /* async-signal-safe */
  2388. if (ret == -1) {
  2389. ERRMSG("close");
  2390. goto fail;
  2391. }
  2392. }
  2393. return 0;
  2394. fail:
  2395. return -1;
  2396. }
  2397. /* This function should be async-signal-safe. Actually it is. */
  2398. static int
  2399. run_exec_close(VALUE ary, char *errmsg, size_t errmsg_buflen)
  2400. {
  2401. long i;
  2402. int ret;
  2403. for (i = 0; i < RARRAY_LEN(ary); i++) {
  2404. VALUE elt = RARRAY_PTR(ary)[i];
  2405. int fd = FIX2INT(RARRAY_PTR(elt)[0]);
  2406. ret = redirect_close(fd); /* async-signal-safe */
  2407. if (ret == -1) {
  2408. ERRMSG("close");
  2409. return -1;
  2410. }
  2411. }
  2412. return 0;
  2413. }
  2414. /* This function should be async-signal-safe when sargp is NULL. Actually it is. */
  2415. static int
  2416. run_exec_open(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
  2417. {
  2418. long i;
  2419. int ret;
  2420. for (i = 0; i < RARRAY_LEN(ary);) {
  2421. VALUE elt = RARRAY_PTR(ary)[i];
  2422. int fd = FIX2INT(RARRAY_PTR(elt)[0]);
  2423. VALUE param = RARRAY_PTR(elt)[1];
  2424. char *path = RSTRING_PTR(RARRAY_PTR(param)[0]);
  2425. int flags = NUM2INT(RARRAY_PTR(param)[1]);
  2426. int perm = NUM2INT(RARRAY_PTR(param)[2]);
  2427. int need_close = 1;
  2428. int fd2 = redirect_open(path, flags, perm); /* async-signal-safe */
  2429. if (fd2 == -1) {
  2430. ERRMSG("open");
  2431. return -1;
  2432. }
  2433. rb_update_max_fd(fd2);
  2434. while (i < RARRAY_LEN(ary) &&
  2435. (elt = RARRAY_PTR(ary)[i], RARRAY_PTR(elt)[1] == param)) {
  2436. fd = FIX2INT(RARRAY_PTR(elt)[0]);
  2437. if (fd == fd2) {
  2438. need_close = 0;
  2439. }
  2440. else {
  2441. if (save_redirect_fd(fd, sargp, errmsg, errmsg_buflen) < 0) /* async-signal-safe */
  2442. return -1;
  2443. ret = redirect_dup2(fd2, fd); /* async-signal-safe */
  2444. if (ret == -1) {
  2445. ERRMSG("dup2");
  2446. return -1;
  2447. }
  2448. rb_update_max_fd(fd);
  2449. }
  2450. i++;
  2451. }
  2452. if (need_close) {
  2453. ret = redirect_close(fd2); /* async-signal-safe */
  2454. if (ret == -1) {
  2455. ERRMSG("close");
  2456. return -1;
  2457. }
  2458. }
  2459. }
  2460. return 0;
  2461. }
  2462. /* This function should be async-signal-safe when sargp is NULL. Actually it is. */
  2463. static int
  2464. run_exec_dup2_child(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
  2465. {
  2466. long i;
  2467. int ret;
  2468. for (i = 0; i < RARRAY_LEN(ary); i++) {
  2469. VALUE elt = RARRAY_PTR(ary)[i];
  2470. int newfd = FIX2INT(RARRAY_PTR(elt)[0]);
  2471. int oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
  2472. if (save_redirect_fd(newfd, sargp, errmsg, errmsg_buflen) < 0) /* async-signal-safe */
  2473. return -1;
  2474. ret = redirect_dup2(oldfd, newfd); /* async-signal-safe */
  2475. if (ret == -1) {
  2476. ERRMSG("dup2");
  2477. return -1;
  2478. }
  2479. rb_update_max_fd(newfd);
  2480. }
  2481. return 0;
  2482. }
  2483. #ifdef HAVE_SETPGID
  2484. /* This function should be async-signal-safe when sargp is NULL. Actually it is. */
  2485. static int
  2486. run_exec_pgroup(const struct rb_execarg *eargp, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
  2487. {
  2488. /*
  2489. * If FD_CLOEXEC is available, rb_fork waits the child's execve.
  2490. * So setpgid is done in the child when rb_fork is returned in the parent.
  2491. * No race condition, even without setpgid from the parent.
  2492. * (Is there an environment which has setpgid but no FD_CLOEXEC?)
  2493. */
  2494. int ret;
  2495. pid_t pgroup;
  2496. pgroup = eargp->pgroup_pgid;
  2497. if (pgroup == -1)
  2498. return 0;
  2499. if (sargp) {
  2500. /* maybe meaningless with no fork environment... */
  2501. sargp->pgroup_given = 1;
  2502. sargp->pgroup_pgid = getpgrp();
  2503. }
  2504. if (pgroup == 0) {
  2505. pgroup = getpid(); /* async-signal-safe */
  2506. }
  2507. ret = setpgid(getpid(), pgroup); /* async-signal-safe */
  2508. if (ret == -1) ERRMSG("setpgid");
  2509. return ret;
  2510. }
  2511. #endif
  2512. #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
  2513. /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
  2514. static int
  2515. run_exec_rlimit(VALUE ary, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
  2516. {
  2517. long i;
  2518. for (i = 0; i < RARRAY_LEN(ary); i++) {
  2519. VALUE elt = RARRAY_PTR(ary)[i];
  2520. int rtype = NUM2INT(RARRAY_PTR(elt)[0]);
  2521. struct rlimit rlim;
  2522. if (sargp) {
  2523. VALUE tmp, newary;
  2524. if (getrlimit(rtype, &rlim) == -1) {
  2525. ERRMSG("getrlimit");
  2526. return -1;
  2527. }
  2528. tmp = hide_obj(rb_ary_new3(3, RARRAY_PTR(elt)[0],
  2529. RLIM2NUM(rlim.rlim_cur),
  2530. RLIM2NUM(rlim.rlim_max)));
  2531. if (sargp->rlimit_limits == Qfalse)
  2532. newary = sargp->rlimit_limits = hide_obj(rb_ary_new());
  2533. else
  2534. newary = sargp->rlimit_limits;
  2535. rb_ary_push(newary, tmp);
  2536. }
  2537. rlim.rlim_cur = NUM2RLIM(RARRAY_PTR(elt)[1]);
  2538. rlim.rlim_max = NUM2RLIM(RARRAY_PTR(elt)[2]);
  2539. if (setrlimit(rtype, &rlim) == -1) { /* hopefully async-signal-safe */
  2540. ERRMSG("setrlimit");
  2541. return -1;
  2542. }
  2543. }
  2544. return 0;
  2545. }
  2546. #endif
  2547. #if !defined(HAVE_FORK)
  2548. static VALUE
  2549. save_env_i(VALUE i, VALUE ary, int argc, VALUE *argv)
  2550. {
  2551. rb_ary_push(ary, hide_obj(rb_ary_dup(argv[0])));
  2552. return Qnil;
  2553. }
  2554. static void
  2555. save_env(struct rb_execarg *sargp)
  2556. {
  2557. if (!sargp)
  2558. return;
  2559. if (sargp->env_modification == Qfalse) {
  2560. VALUE env = rb_const_get(rb_cObject, rb_intern("ENV"));
  2561. if (RTEST(env)) {
  2562. VALUE ary = hide_obj(rb_ary_new());
  2563. rb_block_call(env, idEach, 0, 0, save_env_i,
  2564. (VALUE)ary);
  2565. sargp->env_modification = ary;
  2566. }
  2567. sargp->unsetenv_others_given = 1;
  2568. sargp->unsetenv_others_do = 1;
  2569. }
  2570. }
  2571. #endif
  2572. /* This function should be async-signal-safe when sargp is NULL. Hopefully it is. */
  2573. int
  2574. rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
  2575. {
  2576. VALUE obj;
  2577. if (sargp) {
  2578. /* assume that sargp is always NULL on fork-able environments */
  2579. MEMZERO(sargp, struct rb_execarg, 1);
  2580. sargp->redirect_fds = Qnil;
  2581. }
  2582. #ifdef HAVE_SETPGID
  2583. if (eargp->pgroup_given) {
  2584. if (run_exec_pgroup(eargp, sargp, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
  2585. return -1;
  2586. }
  2587. #endif
  2588. #if defined(HAVE_SETRLIMIT) && defined(RLIM2NUM)
  2589. obj = eargp->rlimit_limits;
  2590. if (obj != Qfalse) {
  2591. if (run_exec_rlimit(obj, sargp, errmsg, errmsg_buflen) == -1) /* hopefully async-signal-safe */
  2592. return -1;
  2593. }
  2594. #endif
  2595. #if !defined(HAVE_FORK)
  2596. if (eargp->unsetenv_others_given && eargp->unsetenv_others_do) {
  2597. save_env(sargp);
  2598. rb_env_clear();
  2599. }
  2600. obj = eargp->env_modification;
  2601. if (obj != Qfalse) {
  2602. long i;
  2603. save_env(sargp);
  2604. for (i = 0; i < RARRAY_LEN(obj); i++) {
  2605. VALUE pair = RARRAY_PTR(obj)[i];
  2606. VALUE key = RARRAY_PTR(pair)[0];
  2607. VALUE val = RARRAY_PTR(pair)[1];
  2608. if (NIL_P(val))
  2609. ruby_setenv(StringValueCStr(key), 0);
  2610. else
  2611. ruby_setenv(StringValueCStr(key), StringValueCStr(val));
  2612. }
  2613. }
  2614. #endif
  2615. if (eargp->umask_given) {
  2616. mode_t mask = eargp->umask_mask;
  2617. mode_t oldmask = umask(mask); /* never fail */ /* async-signal-safe */
  2618. if (sargp) {
  2619. sargp->umask_given = 1;
  2620. sargp->umask_mask = oldmask;
  2621. }
  2622. }
  2623. obj = eargp->fd_dup2;
  2624. if (obj != Qfalse) {
  2625. if (run_exec_dup2(obj, eargp->dup2_tmpbuf, sargp, errmsg, errmsg_buflen) == -1) /* hopefully async-signal-safe */
  2626. return -1;
  2627. }
  2628. obj = eargp->fd_close;
  2629. if (obj != Qfalse) {
  2630. if (sargp)
  2631. rb_warn("cannot close fd before spawn");
  2632. else {
  2633. if (run_exec_close(obj, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
  2634. return -1;
  2635. }
  2636. }
  2637. #ifdef HAVE_FORK
  2638. if (!eargp->close_others_given || eargp->close_others_do) {
  2639. rb_close_before_exec(3, eargp->close_others_maxhint, eargp->redirect_fds); /* async-signal-safe */
  2640. }
  2641. #endif
  2642. obj = eargp->fd_open;
  2643. if (obj != Qfalse) {
  2644. if (run_exec_open(obj, sargp, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
  2645. return -1;
  2646. }
  2647. obj = eargp->fd_dup2_child;
  2648. if (obj != Qfalse) {
  2649. if (run_exec_dup2_child(obj, sargp, errmsg, errmsg_buflen) == -1) /* async-signal-safe */
  2650. return -1;
  2651. }
  2652. if (eargp->chdir_given) {
  2653. if (sargp) {
  2654. char *cwd = my_getcwd();
  2655. sargp->chdir_given = 1;
  2656. sargp->chdir_dir = hide_obj(rb_str_new2(cwd));
  2657. xfree(cwd);
  2658. }
  2659. if (chdir(RSTRING_PTR(eargp->chdir_dir)) == -1) { /* async-signal-safe */
  2660. ERRMSG("chdir");
  2661. return -1;
  2662. }
  2663. }
  2664. #ifdef HAVE_SETGID
  2665. if (eargp->gid_given) {
  2666. if (setgid(eargp->gid) < 0) {
  2667. ERRMSG("setgid");
  2668. return -1;
  2669. }
  2670. }
  2671. #endif
  2672. #ifdef HAVE_SETUID
  2673. if (eargp->uid_given) {
  2674. if (setuid(eargp->uid) < 0) {
  2675. ERRMSG("setuid");
  2676. return -1;
  2677. }
  2678. }
  2679. #endif
  2680. if (sargp) {
  2681. VALUE ary = sargp->fd_dup2;
  2682. if (ary != Qfalse) {
  2683. size_t len = run_exec_dup2_tmpbuf_size(RARRAY_LEN(ary));
  2684. VALUE tmpbuf = hide_obj(rb_str_new(0, len));
  2685. rb_str_set_len(tmpbuf, len);
  2686. sargp->dup2_tmpbuf = tmpbuf;
  2687. }
  2688. }
  2689. return 0;
  2690. }
  2691. int
  2692. rb_run_exec_options_err(const struct rb_exec_arg *e, struct rb_exec_arg *s, char *errmsg, size_t errmsg_buflen)
  2693. {
  2694. return rb_execarg_run_options(rb_execarg_get(e->execarg_obj), rb_execarg_get(s->execarg_obj), errmsg, errmsg_buflen);
  2695. }
  2696. int
  2697. rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
  2698. {
  2699. return rb_execarg_run_options(rb_execarg_get(e->execarg_obj), rb_execarg_get(s->execarg_obj), NULL, 0);
  2700. }
  2701. /* This function should be async-signal-safe. Hopefully it is. */
  2702. int
  2703. rb_exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
  2704. {
  2705. #if !defined(HAVE_FORK)
  2706. struct rb_execarg sarg, *const sargp = &sarg;
  2707. #else
  2708. struct rb_execarg *const sargp = NULL;
  2709. #endif
  2710. before_exec_async_signal_safe(); /* async-signal-safe */
  2711. if (rb_execarg_run_options(eargp, sargp, errmsg, errmsg_buflen) < 0) { /* hopefully async-signal-safe */
  2712. goto failure;
  2713. }
  2714. if (eargp->use_shell) {
  2715. proc_exec_sh(RSTRING_PTR(eargp->invoke.sh.shell_script), eargp->envp_str); /* async-signal-safe */
  2716. }
  2717. else {
  2718. char *abspath = NULL;
  2719. if (!NIL_P(eargp->invoke.cmd.command_abspath))
  2720. abspath = RSTRING_PTR(eargp->invoke.cmd.command_abspath);
  2721. proc_exec_cmd(abspath, eargp->invoke.cmd.argv_str, eargp->envp_str); /* async-signal-safe */
  2722. }
  2723. #if !defined(HAVE_FORK)
  2724. preserving_errno(rb_execarg_run_options(sargp, NULL, errmsg, errmsg_buflen));
  2725. #endif
  2726. failure:
  2727. preserving_errno(after_exec_async_signal_safe()); /* async-signal-safe */
  2728. return -1;
  2729. }
  2730. static int
  2731. rb_exec_without_timer_thread(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
  2732. {
  2733. int ret;
  2734. before_exec_non_async_signal_safe(); /* async-signal-safe if forked_child is true */
  2735. ret = rb_exec_async_signal_safe(eargp, errmsg, errmsg_buflen); /* hopefully async-signal-safe */
  2736. preserving_errno(after_exec_non_async_signal_safe()); /* not async-signal-safe because it calls rb_thread_start_timer_thread. */
  2737. return ret;
  2738. }
  2739. int
  2740. rb_exec_err(const struct rb_exec_arg *e, char *errmsg, size_t errmsg_buflen)
  2741. {
  2742. return rb_exec_without_timer_thread(rb_execarg_get(e->execarg_obj), errmsg, errmsg_buflen);
  2743. }
  2744. int
  2745. rb_exec(const struct rb_exec_arg *e)
  2746. {
  2747. #if !defined FD_CLOEXEC && !defined HAVE_SPAWNV
  2748. char errmsg[80] = { '\0' };
  2749. int ret = rb_exec_without_timer_thread(rb_execarg_get(e->execarg_obj), errmsg, sizeof(errmsg));
  2750. preserving_errno(
  2751. if (errmsg[0]) {
  2752. fprintf(stderr, "%s\n", errmsg);
  2753. }
  2754. else {
  2755. fprintf(stderr, "%s:%d: command not found: %s\n",
  2756. rb_sourcefile(), rb_sourceline(),
  2757. RSTRING_PTR(e->use_shell ? e->invoke.sh.shell_script : e->invoke.cmd.command_name));
  2758. }
  2759. );
  2760. return ret;
  2761. #else
  2762. return rb_exec_without_timer_thread(rb_execarg_get(e->execarg_obj), NULL, 0);
  2763. #endif
  2764. }
  2765. #ifdef HAVE_FORK
  2766. /* This function should be async-signal-safe. Hopefully it is. */
  2767. static int
  2768. rb_exec_atfork(void* arg, char *errmsg, size_t errmsg_buflen)
  2769. {
  2770. return rb_exec_async_signal_safe(arg, errmsg, errmsg_buflen); /* hopefully async-signal-safe */
  2771. }
  2772. #endif
  2773. #ifdef HAVE_FORK
  2774. #if SIZEOF_INT == SIZEOF_LONG
  2775. #define proc_syswait (VALUE (*)(VALUE))rb_syswait
  2776. #else
  2777. static VALUE
  2778. proc_syswait(VALUE pid)
  2779. {
  2780. rb_syswait((int)pid);
  2781. return Qnil;
  2782. }
  2783. #endif
  2784. static int
  2785. move_fds_to_avoid_crash(int *fdp, int n, VALUE fds)
  2786. {
  2787. int min = 0;
  2788. int i;
  2789. for (i = 0; i < n; i++) {
  2790. int ret;
  2791. while (RTEST(rb_hash_lookup(fds, INT2FIX(fdp[i])))) {
  2792. if (min <= fdp[i])
  2793. min = fdp[i]+1;
  2794. while (RTEST(rb_hash_lookup(fds, INT2FIX(min))))
  2795. min++;
  2796. ret = rb_cloexec_fcntl_dupfd(fdp[i], min);
  2797. if (ret == -1)
  2798. return -1;
  2799. rb_update_max_fd(ret);
  2800. close(fdp[i]);
  2801. fdp[i] = ret;
  2802. }
  2803. }
  2804. return 0;
  2805. }
  2806. static int
  2807. pipe_nocrash(int filedes[2], VALUE fds)
  2808. {
  2809. int ret;
  2810. ret = rb_pipe(filedes);
  2811. if (ret == -1)
  2812. return -1;
  2813. if (RTEST(fds)) {
  2814. int save = errno;
  2815. if (move_fds_to_avoid_crash(filedes, 2, fds) == -1) {
  2816. close(filedes[0]);
  2817. close(filedes[1]);
  2818. return -1;
  2819. }
  2820. errno = save;
  2821. }
  2822. return ret;
  2823. }
  2824. struct chfunc_protect_t {
  2825. int (*chfunc)(void*, char *, size_t);
  2826. void *arg;
  2827. char *errmsg;
  2828. size_t buflen;
  2829. };
  2830. static VALUE
  2831. chfunc_protect(VALUE arg)
  2832. {
  2833. struct chfunc_protect_t *p = (struct chfunc_protect_t *)arg;
  2834. return (VALUE)(*p->chfunc)(p->arg, p->errmsg, p->buflen);
  2835. }
  2836. #ifndef O_BINARY
  2837. #define O_BINARY 0
  2838. #endif
  2839. /*
  2840. * Forks child process, and returns the process ID in the parent
  2841. * process.
  2842. *
  2843. * If +status+ is given, protects from any exceptions and sets the
  2844. * jump status to it, and returns -1. If failed to fork new process
  2845. * but no exceptions occurred, sets 0 to it. Otherwise, if forked
  2846. * successfully, the value of +status+ is undetermined.
  2847. *
  2848. * In the child process, just returns 0 if +chfunc+ is +NULL+.
  2849. * Otherwise +chfunc+ will be called with +charg+, and then the child
  2850. * process exits with +EXIT_SUCCESS+ when it returned zero.
  2851. *
  2852. * In the case of the function is called and returns non-zero value,
  2853. * the child process exits with non-+EXIT_SUCCESS+ value (normally
  2854. * 127). And, on the platforms where +FD_CLOEXEC+ is available,
  2855. * +errno+ is propagated to the parent process, and this function
  2856. * returns -1 in the parent process. On the other platforms, just
  2857. * returns pid.
  2858. *
  2859. * If fds is not Qnil, internal pipe for the errno propagation is
  2860. * arranged to avoid conflicts of the hash keys in +fds+.
  2861. *
  2862. * +chfunc+ must not raise any exceptions.
  2863. */
  2864. static rb_pid_t
  2865. retry_fork(int *status, int *ep, int chfunc_is_async_signal_safe)
  2866. {
  2867. rb_pid_t pid;
  2868. int state = 0;
  2869. #define prefork() ( \
  2870. rb_io_flush(rb_stdout), \
  2871. rb_io_flush(rb_stderr) \
  2872. )
  2873. while (1) {
  2874. prefork();
  2875. if (!chfunc_is_async_signal_safe)
  2876. before_fork();
  2877. pid = fork();
  2878. if (pid == 0) /* fork succeed, child process */
  2879. return pid;
  2880. if (!chfunc_is_async_signal_safe)
  2881. preserving_errno(after_fork());
  2882. if (0 < pid) /* fork succeed, parent process */
  2883. return pid;
  2884. /* fork failed */
  2885. switch (errno) {
  2886. case EAGAIN:
  2887. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  2888. case EWOULDBLOCK:
  2889. #endif
  2890. if (!status && !ep) {
  2891. rb_thread_sleep(1);
  2892. continue;
  2893. }
  2894. else {
  2895. rb_protect((VALUE (*)())rb_thread_sleep, 1, &state);
  2896. if (status) *status = state;
  2897. if (!state) continue;
  2898. }
  2899. /* fall through */
  2900. default:
  2901. if (ep) {
  2902. preserving_errno((close(ep[0]), close(ep[1])));
  2903. }
  2904. if (state && !status) rb_jump_tag(state);
  2905. return -1;
  2906. }
  2907. }
  2908. }
  2909. static void
  2910. send_child_error(int fd, int state, char *errmsg, size_t errmsg_buflen, int chfunc_is_async_signal_safe)
  2911. {
  2912. VALUE io = Qnil;
  2913. int err;
  2914. if (!chfunc_is_async_signal_safe) {
  2915. if (write(fd, &state, sizeof(state)) == sizeof(state) && state) {
  2916. VALUE errinfo = rb_errinfo();
  2917. io = rb_io_fdopen(fd, O_WRONLY|O_BINARY, NULL);
  2918. rb_marshal_dump(errinfo, io);
  2919. rb_io_flush(io);
  2920. }
  2921. }
  2922. err = errno;
  2923. if (write(fd, &err, sizeof(err)) < 0) err = errno;
  2924. if (errmsg && 0 < errmsg_buflen) {
  2925. errmsg[errmsg_buflen-1] = '\0';
  2926. errmsg_buflen = strlen(errmsg);
  2927. if (errmsg_buflen > 0 && write(fd, errmsg, errmsg_buflen) < 0)
  2928. err = errno;
  2929. }
  2930. if (!NIL_P(io)) rb_io_close(io);
  2931. }
  2932. static int
  2933. recv_child_error(int fd, int *statep, VALUE *excp, int *errp, char *errmsg, size_t errmsg_buflen, int chfunc_is_async_signal_safe)
  2934. {
  2935. int err, state = 0;
  2936. VALUE io = Qnil;
  2937. ssize_t size;
  2938. VALUE exc = Qnil;
  2939. if (!chfunc_is_async_signal_safe) {
  2940. if ((read(fd, &state, sizeof(state))) == sizeof(state) && state) {
  2941. io = rb_io_fdopen(fd, O_RDONLY|O_BINARY, NULL);
  2942. exc = rb_marshal_load(io);
  2943. rb_set_errinfo(exc);
  2944. }
  2945. if (!*statep && state) *statep = state;
  2946. *excp = exc;
  2947. }
  2948. #define READ_FROM_CHILD(ptr, len) \
  2949. (NIL_P(io) ? read(fd, (ptr), (len)) : rb_io_bufread(io, (ptr), (len)))
  2950. if ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) {
  2951. err = errno;
  2952. }
  2953. *errp = err;
  2954. if (size == sizeof(err) &&
  2955. errmsg && 0 < errmsg_buflen) {
  2956. ssize_t ret = READ_FROM_CHILD(errmsg, errmsg_buflen-1);
  2957. if (0 <= ret) {
  2958. errmsg[ret] = '\0';
  2959. }
  2960. }
  2961. if (NIL_P(io))
  2962. close(fd);
  2963. else
  2964. rb_io_close(io);
  2965. return size != 0;
  2966. }
  2967. static rb_pid_t
  2968. rb_fork_internal(int *status, int (*chfunc)(void*, char *, size_t), void *charg,
  2969. int chfunc_is_async_signal_safe, VALUE fds,
  2970. char *errmsg, size_t errmsg_buflen)
  2971. {
  2972. rb_pid_t pid;
  2973. int err, state = 0;
  2974. int ep[2];
  2975. VALUE exc = Qnil;
  2976. int error_occured;
  2977. if (status) *status = 0;
  2978. if (!chfunc) {
  2979. pid = retry_fork(status, NULL, FALSE);
  2980. if (pid < 0)
  2981. return pid;
  2982. if (!pid) {
  2983. forked_child = 1;
  2984. after_fork();
  2985. }
  2986. return pid;
  2987. }
  2988. else {
  2989. if (pipe_nocrash(ep, fds)) return -1;
  2990. if (fcntl(ep[1], F_SETFD, FD_CLOEXEC)) {
  2991. preserving_errno((close(ep[0]), close(ep[1])));
  2992. return -1;
  2993. }
  2994. pid = retry_fork(status, ep, chfunc_is_async_signal_safe);
  2995. if (pid < 0)
  2996. return pid;
  2997. if (!pid) {
  2998. int ret;
  2999. forked_child = 1;
  3000. close(ep[0]);
  3001. if (chfunc_is_async_signal_safe)
  3002. ret = chfunc(charg, errmsg, errmsg_buflen);
  3003. else {
  3004. struct chfunc_protect_t arg;
  3005. arg.chfunc = chfunc;
  3006. arg.arg = charg;
  3007. arg.errmsg = errmsg;
  3008. arg.buflen = errmsg_buflen;
  3009. ret = (int)rb_protect(chfunc_protect, (VALUE)&arg, &state);
  3010. }
  3011. if (!ret) _exit(EXIT_SUCCESS);
  3012. send_child_error(ep[1], state, errmsg, errmsg_buflen, chfunc_is_async_signal_safe);
  3013. #if EXIT_SUCCESS == 127
  3014. _exit(EXIT_FAILURE);
  3015. #else
  3016. _exit(127);
  3017. #endif
  3018. }
  3019. close(ep[1]);
  3020. error_occured = recv_child_error(ep[0], &state, &exc, &err, errmsg, errmsg_buflen, chfunc_is_async_signal_safe);
  3021. if (state || error_occured) {
  3022. if (status) {
  3023. rb_protect(proc_syswait, (VALUE)pid, status);
  3024. if (state) *status = state;
  3025. }
  3026. else {
  3027. rb_syswait(pid);
  3028. if (state) rb_exc_raise(exc);
  3029. }
  3030. errno = err;
  3031. return -1;
  3032. }
  3033. return pid;
  3034. }
  3035. }
  3036. rb_pid_t
  3037. rb_fork_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds,
  3038. char *errmsg, size_t errmsg_buflen)
  3039. {
  3040. return rb_fork_internal(status, chfunc, charg, FALSE, fds, errmsg, errmsg_buflen);
  3041. }
  3042. rb_pid_t
  3043. rb_fork_async_signal_safe(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds,
  3044. char *errmsg, size_t errmsg_buflen)
  3045. {
  3046. return rb_fork_internal(status, chfunc, charg, TRUE, fds, errmsg, errmsg_buflen);
  3047. }
  3048. struct chfunc_wrapper_t {
  3049. int (*chfunc)(void*);
  3050. void *arg;
  3051. };
  3052. static int
  3053. chfunc_wrapper(void *arg_, char *errmsg, size_t errmsg_buflen)
  3054. {
  3055. struct chfunc_wrapper_t *arg = arg_;
  3056. return arg->chfunc(arg->arg);
  3057. }
  3058. rb_pid_t
  3059. rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds)
  3060. {
  3061. if (chfunc) {
  3062. struct chfunc_wrapper_t warg;
  3063. warg.chfunc = chfunc;
  3064. warg.arg = charg;
  3065. return rb_fork_internal(status, chfunc_wrapper, &warg, FALSE, fds, NULL, 0);
  3066. }
  3067. else {
  3068. return rb_fork_internal(status, NULL, NULL, FALSE, fds, NULL, 0);
  3069. }
  3070. }
  3071. rb_pid_t
  3072. rb_fork_ruby(int *status)
  3073. {
  3074. return rb_fork_internal(status, NULL, NULL, FALSE, Qnil, NULL, 0);
  3075. }
  3076. #endif
  3077. #if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
  3078. /*
  3079. * call-seq:
  3080. * Kernel.fork [{ block }] -> fixnum or nil
  3081. * Process.fork [{ block }] -> fixnum or nil
  3082. *
  3083. * Creates a subprocess. If a block is specified, that block is run
  3084. * in the subprocess, and the subprocess terminates with a status of
  3085. * zero. Otherwise, the +fork+ call returns twice, once in
  3086. * the parent, returning the process ID of the child, and once in
  3087. * the child, returning _nil_. The child process can exit using
  3088. * <code>Kernel.exit!</code> to avoid running any
  3089. * <code>at_exit</code> functions. The parent process should
  3090. * use <code>Process.wait</code> to collect the termination statuses
  3091. * of its children or use <code>Process.detach</code> to register
  3092. * disinterest in their status; otherwise, the operating system
  3093. * may accumulate zombie processes.
  3094. *
  3095. * The thread calling fork is the only thread in the created child process.
  3096. * fork doesn't copy other threads.
  3097. *
  3098. * If fork is not usable, Process.respond_to?(:fork) returns false.
  3099. */
  3100. static VALUE
  3101. rb_f_fork(VALUE obj)
  3102. {
  3103. rb_pid_t pid;
  3104. rb_secure(2);
  3105. switch (pid = rb_fork_ruby(NULL)) {
  3106. case 0:
  3107. rb_thread_atfork();
  3108. if (rb_block_given_p()) {
  3109. int status;
  3110. rb_protect(rb_yield, Qundef, &status);
  3111. ruby_stop(status);
  3112. }
  3113. return Qnil;
  3114. case -1:
  3115. rb_sys_fail("fork(2)");
  3116. return Qnil;
  3117. default:
  3118. return PIDT2NUM(pid);
  3119. }
  3120. }
  3121. #else
  3122. #define rb_f_fork rb_f_notimplement
  3123. #endif
  3124. static int
  3125. exit_status_code(VALUE status)
  3126. {
  3127. int istatus;
  3128. switch (status) {
  3129. case Qtrue:
  3130. istatus = EXIT_SUCCESS;
  3131. break;
  3132. case Qfalse:
  3133. istatus = EXIT_FAILURE;
  3134. break;
  3135. default:
  3136. istatus = NUM2INT(status);
  3137. #if EXIT_SUCCESS != 0
  3138. if (istatus == 0)
  3139. istatus = EXIT_SUCCESS;
  3140. #endif
  3141. break;
  3142. }
  3143. return istatus;
  3144. }
  3145. /*
  3146. * call-seq:
  3147. * Process.exit!(status=false)
  3148. *
  3149. * Exits the process immediately. No exit handlers are
  3150. * run. <em>status</em> is returned to the underlying system as the
  3151. * exit status.
  3152. *
  3153. * Process.exit!(true)
  3154. */
  3155. static VALUE
  3156. rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
  3157. {
  3158. VALUE status;
  3159. int istatus;
  3160. rb_secure(4);
  3161. if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
  3162. istatus = exit_status_code(status);
  3163. }
  3164. else {
  3165. istatus = EXIT_FAILURE;
  3166. }
  3167. _exit(istatus);
  3168. UNREACHABLE;
  3169. }
  3170. void
  3171. rb_exit(int status)
  3172. {
  3173. if (GET_THREAD()->tag) {
  3174. VALUE args[2];
  3175. args[0] = INT2NUM(status);
  3176. args[1] = rb_str_new2("exit");
  3177. rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
  3178. }
  3179. ruby_finalize();
  3180. exit(status);
  3181. }
  3182. /*
  3183. * call-seq:
  3184. * exit(status=true)
  3185. * Kernel::exit(status=true)
  3186. * Process::exit(status=true)
  3187. *
  3188. * Initiates the termination of the Ruby script by raising the
  3189. * <code>SystemExit</code> exception. This exception may be caught. The
  3190. * optional parameter is used to return a status code to the invoking
  3191. * environment.
  3192. * +true+ and +FALSE+ of _status_ means success and failure
  3193. * respectively. The interpretation of other integer values are
  3194. * system dependent.
  3195. *
  3196. * begin
  3197. * exit
  3198. * puts "never get here"
  3199. * rescue SystemExit
  3200. * puts "rescued a SystemExit exception"
  3201. * end
  3202. * puts "after begin block"
  3203. *
  3204. * <em>produces:</em>
  3205. *
  3206. * rescued a SystemExit exception
  3207. * after begin block
  3208. *
  3209. * Just prior to termination, Ruby executes any <code>at_exit</code> functions
  3210. * (see Kernel::at_exit) and runs any object finalizers (see
  3211. * ObjectSpace::define_finalizer).
  3212. *
  3213. * at_exit { puts "at_exit function" }
  3214. * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
  3215. * exit
  3216. *
  3217. * <em>produces:</em>
  3218. *
  3219. * at_exit function
  3220. * in finalizer
  3221. */
  3222. VALUE
  3223. rb_f_exit(int argc, VALUE *argv)
  3224. {
  3225. VALUE status;
  3226. int istatus;
  3227. rb_secure(4);
  3228. if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
  3229. istatus = exit_status_code(status);
  3230. }
  3231. else {
  3232. istatus = EXIT_SUCCESS;
  3233. }
  3234. rb_exit(istatus);
  3235. UNREACHABLE;
  3236. }
  3237. /*
  3238. * call-seq:
  3239. * abort
  3240. * Kernel::abort([msg])
  3241. * Process::abort([msg])
  3242. *
  3243. * Terminate execution immediately, effectively by calling
  3244. * <code>Kernel.exit(false)</code>. If _msg_ is given, it is written
  3245. * to STDERR prior to terminating.
  3246. */
  3247. VALUE
  3248. rb_f_abort(int argc, VALUE *argv)
  3249. {
  3250. rb_secure(4);
  3251. if (argc == 0) {
  3252. if (!NIL_P(GET_THREAD()->errinfo)) {
  3253. ruby_error_print();
  3254. }
  3255. rb_exit(EXIT_FAILURE);
  3256. }
  3257. else {
  3258. VALUE args[2];
  3259. rb_scan_args(argc, argv, "1", &args[1]);
  3260. StringValue(argv[0]);
  3261. rb_io_puts(argc, argv, rb_stderr);
  3262. args[0] = INT2NUM(EXIT_FAILURE);
  3263. rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
  3264. }
  3265. UNREACHABLE;
  3266. }
  3267. void
  3268. rb_syswait(rb_pid_t pid)
  3269. {
  3270. int status;
  3271. rb_waitpid(pid, &status, 0);
  3272. }
  3273. static rb_pid_t
  3274. rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
  3275. {
  3276. rb_pid_t pid;
  3277. #if !USE_SPAWNV
  3278. int status;
  3279. #endif
  3280. #if !defined HAVE_FORK || USE_SPAWNV
  3281. VALUE prog;
  3282. struct rb_execarg sarg;
  3283. #endif
  3284. #if defined HAVE_FORK && !USE_SPAWNV
  3285. pid = rb_fork_async_signal_safe(&status, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen);
  3286. #else
  3287. prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
  3288. if (rb_execarg_run_options(eargp, &sarg, errmsg, errmsg_buflen) < 0) {
  3289. return -1;
  3290. }
  3291. if (prog && !eargp->use_shell) {
  3292. char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
  3293. argv[0] = RSTRING_PTR(prog);
  3294. }
  3295. # if defined HAVE_SPAWNV
  3296. if (eargp->use_shell) {
  3297. pid = proc_spawn_sh(RSTRING_PTR(prog));
  3298. }
  3299. else {
  3300. char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
  3301. pid = proc_spawn_cmd(argv, prog, eargp);
  3302. }
  3303. # if defined(_WIN32)
  3304. if (pid == -1)
  3305. rb_last_status_set(0x7f << 8, 0);
  3306. # endif
  3307. # else
  3308. if (!eargp->use_shell) {
  3309. char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
  3310. int argc = ARGVSTR2ARGC(eargp->invoke.cmd.argv_str);
  3311. prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
  3312. }
  3313. status = system(StringValuePtr(prog));
  3314. rb_last_status_set((status & 0xff) << 8, 0);
  3315. # endif
  3316. rb_execarg_run_options(&sarg, NULL, errmsg, errmsg_buflen);
  3317. #endif
  3318. return pid;
  3319. }
  3320. static rb_pid_t
  3321. rb_spawn_internal(int argc, VALUE *argv, char *errmsg, size_t errmsg_buflen)
  3322. {
  3323. VALUE execarg_obj;
  3324. struct rb_execarg *eargp;
  3325. rb_pid_t ret;
  3326. execarg_obj = rb_execarg_new(argc, argv, TRUE);
  3327. eargp = rb_execarg_get(execarg_obj);
  3328. rb_execarg_fixup(execarg_obj);
  3329. ret = rb_spawn_process(eargp, errmsg, errmsg_buflen);
  3330. RB_GC_GUARD(execarg_obj);
  3331. return ret;
  3332. }
  3333. rb_pid_t
  3334. rb_spawn_err(int argc, VALUE *argv, char *errmsg, size_t errmsg_buflen)
  3335. {
  3336. return rb_spawn_internal(argc, argv, errmsg, errmsg_buflen);
  3337. }
  3338. rb_pid_t
  3339. rb_spawn(int argc, VALUE *argv)
  3340. {
  3341. return rb_spawn_internal(argc, argv, NULL, 0);
  3342. }
  3343. /*
  3344. * call-seq:
  3345. * system([env,] command... [,options]) -> true, false or nil
  3346. *
  3347. * Executes _command..._ in a subshell.
  3348. * _command..._ is one of following forms.
  3349. *
  3350. * commandline : command line string which is passed to the standard shell
  3351. * cmdname, arg1, ... : command name and one or more arguments (no shell)
  3352. * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
  3353. *
  3354. * system returns +true+ if the command gives zero exit status,
  3355. * +false+ for non zero exit status.
  3356. * Returns +nil+ if command execution fails.
  3357. * An error status is available in <code>$?</code>.
  3358. * The arguments are processed in the same way as
  3359. * for <code>Kernel.spawn</code>.
  3360. *
  3361. * The hash arguments, env and options, are same as
  3362. * <code>exec</code> and <code>spawn</code>.
  3363. * See <code>Kernel.spawn</code> for details.
  3364. *
  3365. * system("echo *")
  3366. * system("echo", "*")
  3367. *
  3368. * <em>produces:</em>
  3369. *
  3370. * config.h main.rb
  3371. * *
  3372. *
  3373. * See <code>Kernel.exec</code> for the standard shell.
  3374. */
  3375. static VALUE
  3376. rb_f_system(int argc, VALUE *argv)
  3377. {
  3378. rb_pid_t pid;
  3379. int status;
  3380. #if defined(SIGCLD) && !defined(SIGCHLD)
  3381. # define SIGCHLD SIGCLD
  3382. #endif
  3383. #ifdef SIGCHLD
  3384. RETSIGTYPE (*chfunc)(int);
  3385. rb_last_status_clear();
  3386. chfunc = signal(SIGCHLD, SIG_DFL);
  3387. #endif
  3388. pid = rb_spawn_internal(argc, argv, NULL, 0);
  3389. #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
  3390. if (pid > 0) {
  3391. int ret, status;
  3392. ret = rb_waitpid(pid, &status, 0);
  3393. if (ret == (rb_pid_t)-1)
  3394. rb_sys_fail("Another thread waited the process started by system().");
  3395. }
  3396. #endif
  3397. #ifdef SIGCHLD
  3398. signal(SIGCHLD, chfunc);
  3399. #endif
  3400. if (pid < 0) {
  3401. return Qnil;
  3402. }
  3403. status = PST2INT(rb_last_status_get());
  3404. if (status == EXIT_SUCCESS) return Qtrue;
  3405. return Qfalse;
  3406. }
  3407. /*
  3408. * call-seq:
  3409. * spawn([env,] command... [,options]) -> pid
  3410. * Process.spawn([env,] command... [,options]) -> pid
  3411. *
  3412. * spawn executes specified command and return its pid.
  3413. *
  3414. * This method doesn't wait for end of the command.
  3415. * The parent process should
  3416. * use <code>Process.wait</code> to collect
  3417. * the termination status of its child or
  3418. * use <code>Process.detach</code> to register
  3419. * disinterest in their status;
  3420. * otherwise, the operating system may accumulate zombie processes.
  3421. *
  3422. * spawn has bunch of options to specify process attributes:
  3423. *
  3424. * env: hash
  3425. * name => val : set the environment variable
  3426. * name => nil : unset the environment variable
  3427. * command...:
  3428. * commandline : command line string which is passed to the standard shell
  3429. * cmdname, arg1, ... : command name and one or more arguments (no shell)
  3430. * [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
  3431. * options: hash
  3432. * clearing environment variables:
  3433. * :unsetenv_others => true : clear environment variables except specified by env
  3434. * :unsetenv_others => false : don't clear (default)
  3435. * process group:
  3436. * :pgroup => true or 0 : make a new process group
  3437. * :pgroup => pgid : join to specified process group
  3438. * :pgroup => nil : don't change the process group (default)
  3439. * create new process group: Windows only
  3440. * :new_pgroup => true : the new process is the root process of a new process group
  3441. * :new_pgroup => false : don't create a new process group (default)
  3442. * resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
  3443. * :rlimit_resourcename => limit
  3444. * :rlimit_resourcename => [cur_limit, max_limit]
  3445. * umask:
  3446. * :umask => int
  3447. * redirection:
  3448. * key:
  3449. * FD : single file descriptor in child process
  3450. * [FD, FD, ...] : multiple file descriptor in child process
  3451. * value:
  3452. * FD : redirect to the file descriptor in parent process
  3453. * string : redirect to file with open(string, "r" or "w")
  3454. * [string] : redirect to file with open(string, File::RDONLY)
  3455. * [string, open_mode] : redirect to file with open(string, open_mode, 0644)
  3456. * [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
  3457. * [:child, FD] : redirect to the redirected file descriptor
  3458. * :close : close the file descriptor in child process
  3459. * FD is one of follows
  3460. * :in : the file descriptor 0 which is the standard input
  3461. * :out : the file descriptor 1 which is the standard output
  3462. * :err : the file descriptor 2 which is the standard error
  3463. * integer : the file descriptor of specified the integer
  3464. * io : the file descriptor specified as io.fileno
  3465. * file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
  3466. * :close_others => true : don't inherit
  3467. * current directory:
  3468. * :chdir => str
  3469. *
  3470. * If a hash is given as +env+, the environment is
  3471. * updated by +env+ before <code>exec(2)</code> in the child process.
  3472. * If a pair in +env+ has nil as the value, the variable is deleted.
  3473. *
  3474. * # set FOO as BAR and unset BAZ.
  3475. * pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
  3476. *
  3477. * If a hash is given as +options+,
  3478. * it specifies
  3479. * process group,
  3480. * create new process group,
  3481. * resource limit,
  3482. * current directory,
  3483. * umask and
  3484. * redirects for the child process.
  3485. * Also, it can be specified to clear environment variables.
  3486. *
  3487. * The <code>:unsetenv_others</code> key in +options+ specifies
  3488. * to clear environment variables, other than specified by +env+.
  3489. *
  3490. * pid = spawn(command, :unsetenv_others=>true) # no environment variable
  3491. * pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
  3492. *
  3493. * The <code>:pgroup</code> key in +options+ specifies a process group.
  3494. * The corresponding value should be true, zero or positive integer.
  3495. * true and zero means the process should be a process leader of a new
  3496. * process group.
  3497. * Other values specifies a process group to be belongs.
  3498. *
  3499. * pid = spawn(command, :pgroup=>true) # process leader
  3500. * pid = spawn(command, :pgroup=>10) # belongs to the process group 10
  3501. *
  3502. * The <code>:new_pgroup</code> key in +options+ specifies to pass
  3503. * +CREATE_NEW_PROCESS_GROUP+ flag to <code>CreateProcessW()</code> that is
  3504. * Windows API. This option is only for Windows.
  3505. * true means the new process is the root process of the new process group.
  3506. * The new process has CTRL+C disabled. This flag is necessary for
  3507. * <code>Process.kill(:SIGINT, pid)</code> on the subprocess.
  3508. * :new_pgroup is false by default.
  3509. *
  3510. * pid = spawn(command, :new_pgroup=>true) # new process group
  3511. * pid = spawn(command, :new_pgroup=>false) # same process group
  3512. *
  3513. * The <code>:rlimit_</code><em>foo</em> key specifies a resource limit.
  3514. * <em>foo</em> should be one of resource types such as <code>core</code>.
  3515. * The corresponding value should be an integer or an array which have one or
  3516. * two integers: same as cur_limit and max_limit arguments for
  3517. * Process.setrlimit.
  3518. *
  3519. * cur, max = Process.getrlimit(:CORE)
  3520. * pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
  3521. * pid = spawn(command, :rlimit_core=>max) # enable core dump
  3522. * pid = spawn(command, :rlimit_core=>0) # never dump core.
  3523. *
  3524. * The <code>:umask</code> key in +options+ specifies the umask.
  3525. *
  3526. * pid = spawn(command, :umask=>077)
  3527. *
  3528. * The :in, :out, :err, a fixnum, an IO and an array key specifies a redirection.
  3529. * The redirection maps a file descriptor in the child process.
  3530. *
  3531. * For example, stderr can be merged into stdout as follows:
  3532. *
  3533. * pid = spawn(command, :err=>:out)
  3534. * pid = spawn(command, 2=>1)
  3535. * pid = spawn(command, STDERR=>:out)
  3536. * pid = spawn(command, STDERR=>STDOUT)
  3537. *
  3538. * The hash keys specifies a file descriptor
  3539. * in the child process started by <code>spawn</code>.
  3540. * :err, 2 and STDERR specifies the standard error stream (stderr).
  3541. *
  3542. * The hash values specifies a file descriptor
  3543. * in the parent process which invokes <code>spawn</code>.
  3544. * :out, 1 and STDOUT specifies the standard output stream (stdout).
  3545. *
  3546. * In the above example,
  3547. * the standard output in the child process is not specified.
  3548. * So it is inherited from the parent process.
  3549. *
  3550. * The standard input stream (stdin) can be specified by :in, 0 and STDIN.
  3551. *
  3552. * A filename can be specified as a hash value.
  3553. *
  3554. * pid = spawn(command, :in=>"/dev/null") # read mode
  3555. * pid = spawn(command, :out=>"/dev/null") # write mode
  3556. * pid = spawn(command, :err=>"log") # write mode
  3557. * pid = spawn(command, 3=>"/dev/null") # read mode
  3558. *
  3559. * For stdout and stderr,
  3560. * it is opened in write mode.
  3561. * Otherwise read mode is used.
  3562. *
  3563. * For specifying flags and permission of file creation explicitly,
  3564. * an array is used instead.
  3565. *
  3566. * pid = spawn(command, :in=>["file"]) # read mode is assumed
  3567. * pid = spawn(command, :in=>["file", "r"])
  3568. * pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
  3569. * pid = spawn(command, :out=>["log", "w", 0600])
  3570. * pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
  3571. *
  3572. * The array specifies a filename, flags and permission.
  3573. * The flags can be a string or an integer.
  3574. * If the flags is omitted or nil, File::RDONLY is assumed.
  3575. * The permission should be an integer.
  3576. * If the permission is omitted or nil, 0644 is assumed.
  3577. *
  3578. * If an array of IOs and integers are specified as a hash key,
  3579. * all the elements are redirected.
  3580. *
  3581. * # stdout and stderr is redirected to log file.
  3582. * # The file "log" is opened just once.
  3583. * pid = spawn(command, [:out, :err]=>["log", "w"])
  3584. *
  3585. * Another way to merge multiple file descriptors is [:child, fd].
  3586. * \[:child, fd] means the file descriptor in the child process.
  3587. * This is different from fd.
  3588. * For example, :err=>:out means redirecting child stderr to parent stdout.
  3589. * But :err=>[:child, :out] means redirecting child stderr to child stdout.
  3590. * They differ if stdout is redirected in the child process as follows.
  3591. *
  3592. * # stdout and stderr is redirected to log file.
  3593. * # The file "log" is opened just once.
  3594. * pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
  3595. *
  3596. * \[:child, :out] can be used to merge stderr into stdout in IO.popen.
  3597. * In this case, IO.popen redirects stdout to a pipe in the child process
  3598. * and [:child, :out] refers the redirected stdout.
  3599. *
  3600. * io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
  3601. * p io.read #=> "out\nerr\n"
  3602. *
  3603. * The <code>:chdir</code> key in +options+ specifies the current directory.
  3604. *
  3605. * pid = spawn(command, :chdir=>"/var/tmp")
  3606. *
  3607. * spawn closes all non-standard unspecified descriptors by default.
  3608. * The "standard" descriptors are 0, 1 and 2.
  3609. * This behavior is specified by :close_others option.
  3610. * :close_others doesn't affect the standard descriptors which are
  3611. * closed only if :close is specified explicitly.
  3612. *
  3613. * pid = spawn(command, :close_others=>true) # close 3,4,5,... (default)
  3614. * pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
  3615. *
  3616. * :close_others is true by default for spawn and IO.popen.
  3617. *
  3618. * Note that fds which close-on-exec flag is already set are closed
  3619. * regardless of :close_others option.
  3620. *
  3621. * So IO.pipe and spawn can be used as IO.popen.
  3622. *
  3623. * # similar to r = IO.popen(command)
  3624. * r, w = IO.pipe
  3625. * pid = spawn(command, :out=>w) # r, w is closed in the child process.
  3626. * w.close
  3627. *
  3628. * :close is specified as a hash value to close a fd individually.
  3629. *
  3630. * f = open(foo)
  3631. * system(command, f=>:close) # don't inherit f.
  3632. *
  3633. * If a file descriptor need to be inherited,
  3634. * io=>io can be used.
  3635. *
  3636. * # valgrind has --log-fd option for log destination.
  3637. * # log_w=>log_w indicates log_w.fileno inherits to child process.
  3638. * log_r, log_w = IO.pipe
  3639. * pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
  3640. * log_w.close
  3641. * p log_r.read
  3642. *
  3643. * It is also possible to exchange file descriptors.
  3644. *
  3645. * pid = spawn(command, :out=>:err, :err=>:out)
  3646. *
  3647. * The hash keys specify file descriptors in the child process.
  3648. * The hash values specifies file descriptors in the parent process.
  3649. * So the above specifies exchanging stdout and stderr.
  3650. * Internally, +spawn+ uses an extra file descriptor to resolve such cyclic
  3651. * file descriptor mapping.
  3652. *
  3653. * See <code>Kernel.exec</code> for the standard shell.
  3654. */
  3655. static VALUE
  3656. rb_f_spawn(int argc, VALUE *argv)
  3657. {
  3658. rb_pid_t pid;
  3659. char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
  3660. VALUE execarg_obj, fail_str;
  3661. struct rb_execarg *eargp;
  3662. execarg_obj = rb_execarg_new(argc, argv, TRUE);
  3663. eargp = rb_execarg_get(execarg_obj);
  3664. rb_execarg_fixup(execarg_obj);
  3665. fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
  3666. pid = rb_spawn_process(eargp, errmsg, sizeof(errmsg));
  3667. RB_GC_GUARD(execarg_obj);
  3668. if (pid == -1) {
  3669. const char *prog = errmsg;
  3670. if (!prog[0]) {
  3671. rb_sys_fail_str(fail_str);
  3672. }
  3673. rb_sys_fail(prog);
  3674. }
  3675. #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
  3676. return PIDT2NUM(pid);
  3677. #else
  3678. return Qnil;
  3679. #endif
  3680. }
  3681. /*
  3682. * call-seq:
  3683. * sleep([duration]) -> fixnum
  3684. *
  3685. * Suspends the current thread for _duration_ seconds (which may be any number,
  3686. * including a +Float+ with fractional seconds). Returns the actual number of
  3687. * seconds slept (rounded), which may be less than that asked for if another
  3688. * thread calls <code>Thread#run</code>. Called without an argument, sleep()
  3689. * will sleep forever.
  3690. *
  3691. * Time.new #=> 2008-03-08 19:56:19 +0900
  3692. * sleep 1.2 #=> 1
  3693. * Time.new #=> 2008-03-08 19:56:20 +0900
  3694. * sleep 1.9 #=> 2
  3695. * Time.new #=> 2008-03-08 19:56:22 +0900
  3696. */
  3697. static VALUE
  3698. rb_f_sleep(int argc, VALUE *argv)
  3699. {
  3700. time_t beg, end;
  3701. beg = time(0);
  3702. if (argc == 0) {
  3703. rb_thread_sleep_forever();
  3704. }
  3705. else {
  3706. rb_check_arity(argc, 0, 1);
  3707. rb_thread_wait_for(rb_time_interval(argv[0]));
  3708. }
  3709. end = time(0) - beg;
  3710. return INT2FIX(end);
  3711. }
  3712. #if (defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)) || defined(HAVE_GETPGID)
  3713. /*
  3714. * call-seq:
  3715. * Process.getpgrp -> integer
  3716. *
  3717. * Returns the process group ID for this process. Not available on
  3718. * all platforms.
  3719. *
  3720. * Process.getpgid(0) #=> 25527
  3721. * Process.getpgrp #=> 25527
  3722. */
  3723. static VALUE
  3724. proc_getpgrp(void)
  3725. {
  3726. rb_pid_t pgrp;
  3727. rb_secure(2);
  3728. #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
  3729. pgrp = getpgrp();
  3730. if (pgrp < 0) rb_sys_fail(0);
  3731. return PIDT2NUM(pgrp);
  3732. #else /* defined(HAVE_GETPGID) */
  3733. pgrp = getpgid(0);
  3734. if (pgrp < 0) rb_sys_fail(0);
  3735. return PIDT2NUM(pgrp);
  3736. #endif
  3737. }
  3738. #else
  3739. #define proc_getpgrp rb_f_notimplement
  3740. #endif
  3741. #if defined(HAVE_SETPGID) || (defined(HAVE_SETPGRP) && defined(SETPGRP_VOID))
  3742. /*
  3743. * call-seq:
  3744. * Process.setpgrp -> 0
  3745. *
  3746. * Equivalent to <code>setpgid(0,0)</code>. Not available on all
  3747. * platforms.
  3748. */
  3749. static VALUE
  3750. proc_setpgrp(void)
  3751. {
  3752. rb_secure(2);
  3753. /* check for posix setpgid() first; this matches the posix */
  3754. /* getpgrp() above. It appears that configure will set SETPGRP_VOID */
  3755. /* even though setpgrp(0,0) would be preferred. The posix call avoids */
  3756. /* this confusion. */
  3757. #ifdef HAVE_SETPGID
  3758. if (setpgid(0,0) < 0) rb_sys_fail(0);
  3759. #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
  3760. if (setpgrp() < 0) rb_sys_fail(0);
  3761. #endif
  3762. return INT2FIX(0);
  3763. }
  3764. #else
  3765. #define proc_setpgrp rb_f_notimplement
  3766. #endif
  3767. #if defined(HAVE_GETPGID)
  3768. /*
  3769. * call-seq:
  3770. * Process.getpgid(pid) -> integer
  3771. *
  3772. * Returns the process group ID for the given process id. Not
  3773. * available on all platforms.
  3774. *
  3775. * Process.getpgid(Process.ppid()) #=> 25527
  3776. */
  3777. static VALUE
  3778. proc_getpgid(VALUE obj, VALUE pid)
  3779. {
  3780. rb_pid_t i;
  3781. rb_secure(2);
  3782. i = getpgid(NUM2PIDT(pid));
  3783. if (i < 0) rb_sys_fail(0);
  3784. return PIDT2NUM(i);
  3785. }
  3786. #else
  3787. #define proc_getpgid rb_f_notimplement
  3788. #endif
  3789. #ifdef HAVE_SETPGID
  3790. /*
  3791. * call-seq:
  3792. * Process.setpgid(pid, integer) -> 0
  3793. *
  3794. * Sets the process group ID of _pid_ (0 indicates this
  3795. * process) to <em>integer</em>. Not available on all platforms.
  3796. */
  3797. static VALUE
  3798. proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
  3799. {
  3800. rb_pid_t ipid, ipgrp;
  3801. rb_secure(2);
  3802. ipid = NUM2PIDT(pid);
  3803. ipgrp = NUM2PIDT(pgrp);
  3804. if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
  3805. return INT2FIX(0);
  3806. }
  3807. #else
  3808. #define proc_setpgid rb_f_notimplement
  3809. #endif
  3810. #ifdef HAVE_GETSID
  3811. /*
  3812. * call-seq:
  3813. * Process.getsid() -> integer
  3814. * Process.getsid(pid) -> integer
  3815. *
  3816. * Returns the session ID for for the given process id. If not give,
  3817. * return current process sid. Not available on all platforms.
  3818. *
  3819. * Process.getsid() #=> 27422
  3820. * Process.getsid(0) #=> 27422
  3821. * Process.getsid(Process.pid()) #=> 27422
  3822. */
  3823. static VALUE
  3824. proc_getsid(int argc, VALUE *argv)
  3825. {
  3826. rb_pid_t sid;
  3827. VALUE pid;
  3828. rb_secure(2);
  3829. rb_scan_args(argc, argv, "01", &pid);
  3830. if (NIL_P(pid))
  3831. pid = INT2NUM(0);
  3832. sid = getsid(NUM2PIDT(pid));
  3833. if (sid < 0) rb_sys_fail(0);
  3834. return PIDT2NUM(sid);
  3835. }
  3836. #else
  3837. #define proc_getsid rb_f_notimplement
  3838. #endif
  3839. #if defined(HAVE_SETSID) || (defined(HAVE_SETPGRP) && defined(TIOCNOTTY))
  3840. #if !defined(HAVE_SETSID)
  3841. static rb_pid_t ruby_setsid(void);
  3842. #define setsid() ruby_setsid()
  3843. #endif
  3844. /*
  3845. * call-seq:
  3846. * Process.setsid -> fixnum
  3847. *
  3848. * Establishes this process as a new session and process group
  3849. * leader, with no controlling tty. Returns the session id. Not
  3850. * available on all platforms.
  3851. *
  3852. * Process.setsid #=> 27422
  3853. */
  3854. static VALUE
  3855. proc_setsid(void)
  3856. {
  3857. rb_pid_t pid;
  3858. rb_secure(2);
  3859. pid = setsid();
  3860. if (pid < 0) rb_sys_fail(0);
  3861. return PIDT2NUM(pid);
  3862. }
  3863. #if !defined(HAVE_SETSID)
  3864. #define HAVE_SETSID 1
  3865. static rb_pid_t
  3866. ruby_setsid(void)
  3867. {
  3868. rb_pid_t pid;
  3869. int ret;
  3870. pid = getpid();
  3871. #if defined(SETPGRP_VOID)
  3872. ret = setpgrp();
  3873. /* If `pid_t setpgrp(void)' is equivalent to setsid(),
  3874. `ret' will be the same value as `pid', and following open() will fail.
  3875. In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
  3876. #else
  3877. ret = setpgrp(0, pid);
  3878. #endif
  3879. if (ret == -1) return -1;
  3880. if ((fd = rb_cloexec_open("/dev/tty", O_RDWR, 0)) >= 0) {
  3881. rb_update_max_fd(fd);
  3882. ioctl(fd, TIOCNOTTY, NULL);
  3883. close(fd);
  3884. }
  3885. return pid;
  3886. }
  3887. #endif
  3888. #else
  3889. #define proc_setsid rb_f_notimplement
  3890. #endif
  3891. #ifdef HAVE_GETPRIORITY
  3892. /*
  3893. * call-seq:
  3894. * Process.getpriority(kind, integer) -> fixnum
  3895. *
  3896. * Gets the scheduling priority for specified process, process group,
  3897. * or user. <em>kind</em> indicates the kind of entity to find: one
  3898. * of <code>Process::PRIO_PGRP</code>,
  3899. * <code>Process::PRIO_USER</code>, or
  3900. * <code>Process::PRIO_PROCESS</code>. _integer_ is an id
  3901. * indicating the particular process, process group, or user (an id
  3902. * of 0 means _current_). Lower priorities are more favorable
  3903. * for scheduling. Not available on all platforms.
  3904. *
  3905. * Process.getpriority(Process::PRIO_USER, 0) #=> 19
  3906. * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
  3907. */
  3908. static VALUE
  3909. proc_getpriority(VALUE obj, VALUE which, VALUE who)
  3910. {
  3911. int prio, iwhich, iwho;
  3912. rb_secure(2);
  3913. iwhich = NUM2INT(which);
  3914. iwho = NUM2INT(who);
  3915. errno = 0;
  3916. prio = getpriority(iwhich, iwho);
  3917. if (errno) rb_sys_fail(0);
  3918. return INT2FIX(prio);
  3919. }
  3920. #else
  3921. #define proc_getpriority rb_f_notimplement
  3922. #endif
  3923. #ifdef HAVE_GETPRIORITY
  3924. /*
  3925. * call-seq:
  3926. * Process.setpriority(kind, integer, priority) -> 0
  3927. *
  3928. * See <code>Process#getpriority</code>.
  3929. *
  3930. * Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0
  3931. * Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0
  3932. * Process.getpriority(Process::PRIO_USER, 0) #=> 19
  3933. * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
  3934. */
  3935. static VALUE
  3936. proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
  3937. {
  3938. int iwhich, iwho, iprio;
  3939. rb_secure(2);
  3940. iwhich = NUM2INT(which);
  3941. iwho = NUM2INT(who);
  3942. iprio = NUM2INT(prio);
  3943. if (setpriority(iwhich, iwho, iprio) < 0)
  3944. rb_sys_fail(0);
  3945. return INT2FIX(0);
  3946. }
  3947. #else
  3948. #define proc_setpriority rb_f_notimplement
  3949. #endif
  3950. #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
  3951. static int
  3952. rlimit_resource_name2int(const char *name, int casetype)
  3953. {
  3954. int resource;
  3955. const char *p;
  3956. #define RESCHECK(r) \
  3957. do { \
  3958. if (STRCASECMP(name, #r) == 0) { \
  3959. resource = RLIMIT_##r; \
  3960. goto found; \
  3961. } \
  3962. } while (0)
  3963. switch (TOUPPER(*name)) {
  3964. case 'A':
  3965. #ifdef RLIMIT_AS
  3966. RESCHECK(AS);
  3967. #endif
  3968. break;
  3969. case 'C':
  3970. #ifdef RLIMIT_CORE
  3971. RESCHECK(CORE);
  3972. #endif
  3973. #ifdef RLIMIT_CPU
  3974. RESCHECK(CPU);
  3975. #endif
  3976. break;
  3977. case 'D':
  3978. #ifdef RLIMIT_DATA
  3979. RESCHECK(DATA);
  3980. #endif
  3981. break;
  3982. case 'F':
  3983. #ifdef RLIMIT_FSIZE
  3984. RESCHECK(FSIZE);
  3985. #endif
  3986. break;
  3987. case 'M':
  3988. #ifdef RLIMIT_MEMLOCK
  3989. RESCHECK(MEMLOCK);
  3990. #endif
  3991. #ifdef RLIMIT_MSGQUEUE
  3992. RESCHECK(MSGQUEUE);
  3993. #endif
  3994. break;
  3995. case 'N':
  3996. #ifdef RLIMIT_NOFILE
  3997. RESCHECK(NOFILE);
  3998. #endif
  3999. #ifdef RLIMIT_NPROC
  4000. RESCHECK(NPROC);
  4001. #endif
  4002. #ifdef RLIMIT_NICE
  4003. RESCHECK(NICE);
  4004. #endif
  4005. break;
  4006. case 'R':
  4007. #ifdef RLIMIT_RSS
  4008. RESCHECK(RSS);
  4009. #endif
  4010. #ifdef RLIMIT_RTPRIO
  4011. RESCHECK(RTPRIO);
  4012. #endif
  4013. #ifdef RLIMIT_RTTIME
  4014. RESCHECK(RTTIME);
  4015. #endif
  4016. break;
  4017. case 'S':
  4018. #ifdef RLIMIT_STACK
  4019. RESCHECK(STACK);
  4020. #endif
  4021. #ifdef RLIMIT_SBSIZE
  4022. RESCHECK(SBSIZE);
  4023. #endif
  4024. #ifdef RLIMIT_SIGPENDING
  4025. RESCHECK(SIGPENDING);
  4026. #endif
  4027. break;
  4028. }
  4029. return -1;
  4030. found:
  4031. switch (casetype) {
  4032. case 0:
  4033. for (p = name; *p; p++)
  4034. if (!ISUPPER(*p))
  4035. return -1;
  4036. break;
  4037. case 1:
  4038. for (p = name; *p; p++)
  4039. if (!ISLOWER(*p))
  4040. return -1;
  4041. break;
  4042. default:
  4043. rb_bug("unexpected casetype");
  4044. }
  4045. return resource;
  4046. #undef RESCHECK
  4047. }
  4048. static int
  4049. rlimit_type_by_hname(const char *name)
  4050. {
  4051. return rlimit_resource_name2int(name, 0);
  4052. }
  4053. static int
  4054. rlimit_type_by_lname(const char *name)
  4055. {
  4056. return rlimit_resource_name2int(name, 1);
  4057. }
  4058. static int
  4059. rlimit_resource_type(VALUE rtype)
  4060. {
  4061. const char *name;
  4062. VALUE v;
  4063. int r;
  4064. switch (TYPE(rtype)) {
  4065. case T_SYMBOL:
  4066. name = rb_id2name(SYM2ID(rtype));
  4067. break;
  4068. default:
  4069. v = rb_check_string_type(rtype);
  4070. if (!NIL_P(v)) {
  4071. rtype = v;
  4072. case T_STRING:
  4073. name = StringValueCStr(rtype);
  4074. break;
  4075. }
  4076. /* fall through */
  4077. case T_FIXNUM:
  4078. case T_BIGNUM:
  4079. return NUM2INT(rtype);
  4080. }
  4081. r = rlimit_type_by_hname(name);
  4082. if (r != -1)
  4083. return r;
  4084. rb_raise(rb_eArgError, "invalid resource name: %s", name);
  4085. UNREACHABLE;
  4086. }
  4087. static rlim_t
  4088. rlimit_resource_value(VALUE rval)
  4089. {
  4090. const char *name;
  4091. VALUE v;
  4092. switch (TYPE(rval)) {
  4093. case T_SYMBOL:
  4094. name = rb_id2name(SYM2ID(rval));
  4095. break;
  4096. default:
  4097. v = rb_check_string_type(rval);
  4098. if (!NIL_P(v)) {
  4099. rval = v;
  4100. case T_STRING:
  4101. name = StringValueCStr(rval);
  4102. break;
  4103. }
  4104. /* fall through */
  4105. case T_FIXNUM:
  4106. case T_BIGNUM:
  4107. return NUM2RLIM(rval);
  4108. }
  4109. #ifdef RLIM_INFINITY
  4110. if (strcmp(name, "INFINITY") == 0) return RLIM_INFINITY;
  4111. #endif
  4112. #ifdef RLIM_SAVED_MAX
  4113. if (strcmp(name, "SAVED_MAX") == 0) return RLIM_SAVED_MAX;
  4114. #endif
  4115. #ifdef RLIM_SAVED_CUR
  4116. if (strcmp(name, "SAVED_CUR") == 0) return RLIM_SAVED_CUR;
  4117. #endif
  4118. rb_raise(rb_eArgError, "invalid resource value: %s", name);
  4119. UNREACHABLE;
  4120. }
  4121. #endif
  4122. #if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
  4123. /*
  4124. * call-seq:
  4125. * Process.getrlimit(resource) -> [cur_limit, max_limit]
  4126. *
  4127. * Gets the resource limit of the process.
  4128. * _cur_limit_ means current (soft) limit and
  4129. * _max_limit_ means maximum (hard) limit.
  4130. *
  4131. * _resource_ indicates the kind of resource to limit.
  4132. * It is specified as a symbol such as <code>:CORE</code>,
  4133. * a string such as <code>"CORE"</code> or
  4134. * a constant such as <code>Process::RLIMIT_CORE</code>.
  4135. * See Process.setrlimit for details.
  4136. *
  4137. * _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
  4138. * <code>Process::RLIM_SAVED_MAX</code> or
  4139. * <code>Process::RLIM_SAVED_CUR</code>.
  4140. * See Process.setrlimit and the system getrlimit(2) manual for details.
  4141. */
  4142. static VALUE
  4143. proc_getrlimit(VALUE obj, VALUE resource)
  4144. {
  4145. struct rlimit rlim;
  4146. rb_secure(2);
  4147. if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
  4148. rb_sys_fail("getrlimit");
  4149. }
  4150. return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
  4151. }
  4152. #else
  4153. #define proc_getrlimit rb_f_notimplement
  4154. #endif
  4155. #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
  4156. /*
  4157. * call-seq:
  4158. * Process.setrlimit(resource, cur_limit, max_limit) -> nil
  4159. * Process.setrlimit(resource, cur_limit) -> nil
  4160. *
  4161. * Sets the resource limit of the process.
  4162. * _cur_limit_ means current (soft) limit and
  4163. * _max_limit_ means maximum (hard) limit.
  4164. *
  4165. * If _max_limit_ is not given, _cur_limit_ is used.
  4166. *
  4167. * _resource_ indicates the kind of resource to limit.
  4168. * It should be a symbol such as <code>:CORE</code>,
  4169. * a string such as <code>"CORE"</code> or
  4170. * a constant such as <code>Process::RLIMIT_CORE</code>.
  4171. * The available resources are OS dependent.
  4172. * Ruby may support following resources.
  4173. *
  4174. * [AS] total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)
  4175. * [CORE] core size (bytes) (SUSv3)
  4176. * [CPU] CPU time (seconds) (SUSv3)
  4177. * [DATA] data segment (bytes) (SUSv3)
  4178. * [FSIZE] file size (bytes) (SUSv3)
  4179. * [MEMLOCK] total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)
  4180. * [MSGQUEUE] allocation for POSIX message queues (bytes) (GNU/Linux)
  4181. * [NICE] ceiling on process's nice(2) value (number) (GNU/Linux)
  4182. * [NOFILE] file descriptors (number) (SUSv3)
  4183. * [NPROC] number of processes for the user (number) (4.4BSD, GNU/Linux)
  4184. * [RSS] resident memory size (bytes) (4.2BSD, GNU/Linux)
  4185. * [RTPRIO] ceiling on the process's real-time priority (number) (GNU/Linux)
  4186. * [RTTIME] CPU time for real-time process (us) (GNU/Linux)
  4187. * [SBSIZE] all socket buffers (bytes) (NetBSD, FreeBSD)
  4188. * [SIGPENDING] number of queued signals allowed (signals) (GNU/Linux)
  4189. * [STACK] stack size (bytes) (SUSv3)
  4190. *
  4191. * _cur_limit_ and _max_limit_ may be
  4192. * <code>:INFINITY</code>, <code>"INFINITY"</code> or
  4193. * <code>Process::RLIM_INFINITY</code>,
  4194. * which means that the resource is not limited.
  4195. * They may be <code>Process::RLIM_SAVED_MAX</code>,
  4196. * <code>Process::RLIM_SAVED_CUR</code> and
  4197. * corresponding symbols and strings too.
  4198. * See system setrlimit(2) manual for details.
  4199. *
  4200. * The following example raises the soft limit of core size to
  4201. * the hard limit to try to make core dump possible.
  4202. *
  4203. * Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])
  4204. *
  4205. */
  4206. static VALUE
  4207. proc_setrlimit(int argc, VALUE *argv, VALUE obj)
  4208. {
  4209. VALUE resource, rlim_cur, rlim_max;
  4210. struct rlimit rlim;
  4211. rb_secure(2);
  4212. rb_scan_args(argc, argv, "21", &resource, &rlim_cur, &rlim_max);
  4213. if (rlim_max == Qnil)
  4214. rlim_max = rlim_cur;
  4215. rlim.rlim_cur = rlimit_resource_value(rlim_cur);
  4216. rlim.rlim_max = rlimit_resource_value(rlim_max);
  4217. if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
  4218. rb_sys_fail("setrlimit");
  4219. }
  4220. return Qnil;
  4221. }
  4222. #else
  4223. #define proc_setrlimit rb_f_notimplement
  4224. #endif
  4225. static int under_uid_switch = 0;
  4226. static void
  4227. check_uid_switch(void)
  4228. {
  4229. rb_secure(2);
  4230. if (under_uid_switch) {
  4231. rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
  4232. }
  4233. }
  4234. static int under_gid_switch = 0;
  4235. static void
  4236. check_gid_switch(void)
  4237. {
  4238. rb_secure(2);
  4239. if (under_gid_switch) {
  4240. rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
  4241. }
  4242. }
  4243. /*********************************************************************
  4244. * Document-class: Process::Sys
  4245. *
  4246. * The <code>Process::Sys</code> module contains UID and GID
  4247. * functions which provide direct bindings to the system calls of the
  4248. * same names instead of the more-portable versions of the same
  4249. * functionality found in the <code>Process</code>,
  4250. * <code>Process::UID</code>, and <code>Process::GID</code> modules.
  4251. */
  4252. #if defined(HAVE_PWD_H)
  4253. static rb_uid_t
  4254. obj2uid(VALUE id
  4255. # ifdef HAVE_GETPWNAM_R
  4256. , char *getpw_buf, size_t getpw_buf_len
  4257. # endif
  4258. )
  4259. {
  4260. rb_uid_t uid;
  4261. VALUE tmp;
  4262. if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
  4263. uid = NUM2UIDT(id);
  4264. }
  4265. else {
  4266. const char *usrname = StringValueCStr(id);
  4267. struct passwd *pwptr;
  4268. #ifdef HAVE_GETPWNAM_R
  4269. struct passwd pwbuf;
  4270. if (getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr))
  4271. rb_sys_fail("getpwnam_r");
  4272. #else
  4273. pwptr = getpwnam(usrname);
  4274. #endif
  4275. if (!pwptr) {
  4276. #ifndef HAVE_GETPWNAM_R
  4277. endpwent();
  4278. #endif
  4279. rb_raise(rb_eArgError, "can't find user for %s", usrname);
  4280. }
  4281. uid = pwptr->pw_uid;
  4282. #ifndef HAVE_GETPWNAM_R
  4283. endpwent();
  4284. #endif
  4285. }
  4286. return uid;
  4287. }
  4288. # ifdef p_uid_from_name
  4289. static VALUE
  4290. p_uid_from_name(VALUE self, VALUE id)
  4291. {
  4292. PREPARE_GETPWNAM
  4293. return UIDT2NUM(OBJ2UID(id));
  4294. }
  4295. # endif
  4296. #endif
  4297. #if defined(HAVE_GRP_H)
  4298. static rb_gid_t
  4299. obj2gid(VALUE id
  4300. # ifdef HAVE_GETGRNAM_R
  4301. , char *getgr_buf, size_t getgr_buf_len
  4302. # endif
  4303. )
  4304. {
  4305. rb_gid_t gid;
  4306. VALUE tmp;
  4307. if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
  4308. gid = NUM2GIDT(id);
  4309. }
  4310. else {
  4311. const char *grpname = StringValueCStr(id);
  4312. struct group *grptr;
  4313. #ifdef HAVE_GETGRNAM_R
  4314. struct group grbuf;
  4315. if (getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr))
  4316. rb_sys_fail("getgrnam_r");
  4317. #else
  4318. grptr = getgrnam(grpname);
  4319. #endif
  4320. if (!grptr) {
  4321. #ifndef HAVE_GETGRNAM_R
  4322. endgrent();
  4323. #endif
  4324. rb_raise(rb_eArgError, "can't find group for %s", grpname);
  4325. }
  4326. gid = grptr->gr_gid;
  4327. #ifndef HAVE_GETGRNAM_R
  4328. endgrent();
  4329. #endif
  4330. }
  4331. return gid;
  4332. }
  4333. # ifdef p_gid_from_name
  4334. static VALUE
  4335. p_gid_from_name(VALUE self, VALUE id)
  4336. {
  4337. PREPARE_GETGRNAM;
  4338. return GIDT2NUM(OBJ2GID(id));
  4339. }
  4340. # endif
  4341. #endif
  4342. #if defined HAVE_SETUID
  4343. /*
  4344. * call-seq:
  4345. * Process::Sys.setuid(user) -> nil
  4346. *
  4347. * Set the user ID of the current process to _user_. Not
  4348. * available on all platforms.
  4349. *
  4350. */
  4351. static VALUE
  4352. p_sys_setuid(VALUE obj, VALUE id)
  4353. {
  4354. PREPARE_GETPWNAM;
  4355. check_uid_switch();
  4356. if (setuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
  4357. return Qnil;
  4358. }
  4359. #else
  4360. #define p_sys_setuid rb_f_notimplement
  4361. #endif
  4362. #if defined HAVE_SETRUID
  4363. /*
  4364. * call-seq:
  4365. * Process::Sys.setruid(user) -> nil
  4366. *
  4367. * Set the real user ID of the calling process to _user_.
  4368. * Not available on all platforms.
  4369. *
  4370. */
  4371. static VALUE
  4372. p_sys_setruid(VALUE obj, VALUE id)
  4373. {
  4374. PREPARE_GETPWNAM;
  4375. check_uid_switch();
  4376. if (setruid(OBJ2UID(id)) != 0) rb_sys_fail(0);
  4377. return Qnil;
  4378. }
  4379. #else
  4380. #define p_sys_setruid rb_f_notimplement
  4381. #endif
  4382. #if defined HAVE_SETEUID
  4383. /*
  4384. * call-seq:
  4385. * Process::Sys.seteuid(user) -> nil
  4386. *
  4387. * Set the effective user ID of the calling process to
  4388. * _user_. Not available on all platforms.
  4389. *
  4390. */
  4391. static VALUE
  4392. p_sys_seteuid(VALUE obj, VALUE id)
  4393. {
  4394. PREPARE_GETPWNAM;
  4395. check_uid_switch();
  4396. if (seteuid(OBJ2UID(id)) != 0) rb_sys_fail(0);
  4397. return Qnil;
  4398. }
  4399. #else
  4400. #define p_sys_seteuid rb_f_notimplement
  4401. #endif
  4402. #if defined HAVE_SETREUID
  4403. /*
  4404. * call-seq:
  4405. * Process::Sys.setreuid(rid, eid) -> nil
  4406. *
  4407. * Sets the (user) real and/or effective user IDs of the current
  4408. * process to _rid_ and _eid_, respectively. A value of
  4409. * <code>-1</code> for either means to leave that ID unchanged. Not
  4410. * available on all platforms.
  4411. *
  4412. */
  4413. static VALUE
  4414. p_sys_setreuid(VALUE obj, VALUE rid, VALUE eid)
  4415. {
  4416. PREPARE_GETPWNAM;
  4417. check_uid_switch();
  4418. if (setreuid(OBJ2UID(rid), OBJ2UID(eid)) != 0) rb_sys_fail(0);
  4419. return Qnil;
  4420. }
  4421. #else
  4422. #define p_sys_setreuid rb_f_notimplement
  4423. #endif
  4424. #if defined HAVE_SETRESUID
  4425. /*
  4426. * call-seq:
  4427. * Process::Sys.setresuid(rid, eid, sid) -> nil
  4428. *
  4429. * Sets the (user) real, effective, and saved user IDs of the
  4430. * current process to _rid_, _eid_, and _sid_ respectively. A
  4431. * value of <code>-1</code> for any value means to
  4432. * leave that ID unchanged. Not available on all platforms.
  4433. *
  4434. */
  4435. static VALUE
  4436. p_sys_setresuid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
  4437. {
  4438. PREPARE_GETPWNAM;
  4439. check_uid_switch();
  4440. if (setresuid(OBJ2UID(rid), OBJ2UID(eid), OBJ2UID(sid)) != 0) rb_sys_fail(0);
  4441. return Qnil;
  4442. }
  4443. #else
  4444. #define p_sys_setresuid rb_f_notimplement
  4445. #endif
  4446. /*
  4447. * call-seq:
  4448. * Process.uid -> fixnum
  4449. * Process::UID.rid -> fixnum
  4450. * Process::Sys.getuid -> fixnum
  4451. *
  4452. * Returns the (real) user ID of this process.
  4453. *
  4454. * Process.uid #=> 501
  4455. */
  4456. static VALUE
  4457. proc_getuid(VALUE obj)
  4458. {
  4459. rb_uid_t uid = getuid();
  4460. return UIDT2NUM(uid);
  4461. }
  4462. #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRUID) || defined(HAVE_SETUID)
  4463. /*
  4464. * call-seq:
  4465. * Process.uid= user -> numeric
  4466. *
  4467. * Sets the (user) user ID for this process. Not available on all
  4468. * platforms.
  4469. */
  4470. static VALUE
  4471. proc_setuid(VALUE obj, VALUE id)
  4472. {
  4473. rb_uid_t uid;
  4474. PREPARE_GETPWNAM;
  4475. check_uid_switch();
  4476. uid = OBJ2UID(id);
  4477. #if defined(HAVE_SETRESUID)
  4478. if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
  4479. #elif defined HAVE_SETREUID
  4480. if (setreuid(uid, -1) < 0) rb_sys_fail(0);
  4481. #elif defined HAVE_SETRUID
  4482. if (setruid(uid) < 0) rb_sys_fail(0);
  4483. #elif defined HAVE_SETUID
  4484. {
  4485. if (geteuid() == uid) {
  4486. if (setuid(uid) < 0) rb_sys_fail(0);
  4487. }
  4488. else {
  4489. rb_notimplement();
  4490. }
  4491. }
  4492. #endif
  4493. return id;
  4494. }
  4495. #else
  4496. #define proc_setuid rb_f_notimplement
  4497. #endif
  4498. /********************************************************************
  4499. *
  4500. * Document-class: Process::UID
  4501. *
  4502. * The <code>Process::UID</code> module contains a collection of
  4503. * module functions which can be used to portably get, set, and
  4504. * switch the current process's real, effective, and saved user IDs.
  4505. *
  4506. */
  4507. static rb_uid_t SAVED_USER_ID = -1;
  4508. #ifdef BROKEN_SETREUID
  4509. int
  4510. setreuid(rb_uid_t ruid, rb_uid_t euid)
  4511. {
  4512. if (ruid != (rb_uid_t)-1 && ruid != getuid()) {
  4513. if (euid == (rb_uid_t)-1) euid = geteuid();
  4514. if (setuid(ruid) < 0) return -1;
  4515. }
  4516. if (euid != (rb_uid_t)-1 && euid != geteuid()) {
  4517. if (seteuid(euid) < 0) return -1;
  4518. }
  4519. return 0;
  4520. }
  4521. #endif
  4522. /*
  4523. * call-seq:
  4524. * Process::UID.change_privilege(user) -> fixnum
  4525. *
  4526. * Change the current process's real and effective user ID to that
  4527. * specified by _user_. Returns the new user ID. Not
  4528. * available on all platforms.
  4529. *
  4530. * [Process.uid, Process.euid] #=> [0, 0]
  4531. * Process::UID.change_privilege(31) #=> 31
  4532. * [Process.uid, Process.euid] #=> [31, 31]
  4533. */
  4534. static VALUE
  4535. p_uid_change_privilege(VALUE obj, VALUE id)
  4536. {
  4537. rb_uid_t uid;
  4538. PREPARE_GETPWNAM;
  4539. check_uid_switch();
  4540. uid = OBJ2UID(id);
  4541. if (geteuid() == 0) { /* root-user */
  4542. #if defined(HAVE_SETRESUID)
  4543. if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
  4544. SAVED_USER_ID = uid;
  4545. #elif defined(HAVE_SETUID)
  4546. if (setuid(uid) < 0) rb_sys_fail(0);
  4547. SAVED_USER_ID = uid;
  4548. #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
  4549. if (getuid() == uid) {
  4550. if (SAVED_USER_ID == uid) {
  4551. if (setreuid(-1, uid) < 0) rb_sys_fail(0);
  4552. }
  4553. else {
  4554. if (uid == 0) { /* (r,e,s) == (root, root, x) */
  4555. if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
  4556. if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
  4557. SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
  4558. if (setreuid(uid, uid) < 0) rb_sys_fail(0);
  4559. SAVED_USER_ID = uid;
  4560. }
  4561. else {
  4562. if (setreuid(0, -1) < 0) rb_sys_fail(0);
  4563. SAVED_USER_ID = 0;
  4564. if (setreuid(uid, uid) < 0) rb_sys_fail(0);
  4565. SAVED_USER_ID = uid;
  4566. }
  4567. }
  4568. }
  4569. else {
  4570. if (setreuid(uid, uid) < 0) rb_sys_fail(0);
  4571. SAVED_USER_ID = uid;
  4572. }
  4573. #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
  4574. if (getuid() == uid) {
  4575. if (SAVED_USER_ID == uid) {
  4576. if (seteuid(uid) < 0) rb_sys_fail(0);
  4577. }
  4578. else {
  4579. if (uid == 0) {
  4580. if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
  4581. SAVED_USER_ID = 0;
  4582. if (setruid(0) < 0) rb_sys_fail(0);
  4583. }
  4584. else {
  4585. if (setruid(0) < 0) rb_sys_fail(0);
  4586. SAVED_USER_ID = 0;
  4587. if (seteuid(uid) < 0) rb_sys_fail(0);
  4588. if (setruid(uid) < 0) rb_sys_fail(0);
  4589. SAVED_USER_ID = uid;
  4590. }
  4591. }
  4592. }
  4593. else {
  4594. if (seteuid(uid) < 0) rb_sys_fail(0);
  4595. if (setruid(uid) < 0) rb_sys_fail(0);
  4596. SAVED_USER_ID = uid;
  4597. }
  4598. #else
  4599. (void)uid;
  4600. rb_notimplement();
  4601. #endif
  4602. }
  4603. else { /* unprivileged user */
  4604. #if defined(HAVE_SETRESUID)
  4605. if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
  4606. (geteuid() == uid)? (rb_uid_t)-1: uid,
  4607. (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
  4608. SAVED_USER_ID = uid;
  4609. #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
  4610. if (SAVED_USER_ID == uid) {
  4611. if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
  4612. (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
  4613. rb_sys_fail(0);
  4614. }
  4615. else if (getuid() != uid) {
  4616. if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
  4617. rb_sys_fail(0);
  4618. SAVED_USER_ID = uid;
  4619. }
  4620. else if (/* getuid() == uid && */ geteuid() != uid) {
  4621. if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
  4622. SAVED_USER_ID = uid;
  4623. if (setreuid(uid, -1) < 0) rb_sys_fail(0);
  4624. }
  4625. else { /* getuid() == uid && geteuid() == uid */
  4626. if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
  4627. if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
  4628. SAVED_USER_ID = uid;
  4629. if (setreuid(uid, -1) < 0) rb_sys_fail(0);
  4630. }
  4631. #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
  4632. if (SAVED_USER_ID == uid) {
  4633. if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
  4634. if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
  4635. }
  4636. else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
  4637. if (getuid() != uid) {
  4638. if (setruid(uid) < 0) rb_sys_fail(0);
  4639. SAVED_USER_ID = uid;
  4640. }
  4641. else {
  4642. if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
  4643. SAVED_USER_ID = uid;
  4644. if (setruid(uid) < 0) rb_sys_fail(0);
  4645. }
  4646. }
  4647. else if (/* geteuid() != uid && */ getuid() == uid) {
  4648. if (seteuid(uid) < 0) rb_sys_fail(0);
  4649. if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
  4650. SAVED_USER_ID = uid;
  4651. if (setruid(uid) < 0) rb_sys_fail(0);
  4652. }
  4653. else {
  4654. errno = EPERM;
  4655. rb_sys_fail(0);
  4656. }
  4657. #elif defined HAVE_44BSD_SETUID
  4658. if (getuid() == uid) {
  4659. /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
  4660. if (setuid(uid) < 0) rb_sys_fail(0);
  4661. SAVED_USER_ID = uid;
  4662. }
  4663. else {
  4664. errno = EPERM;
  4665. rb_sys_fail(0);
  4666. }
  4667. #elif defined HAVE_SETEUID
  4668. if (getuid() == uid && SAVED_USER_ID == uid) {
  4669. if (seteuid(uid) < 0) rb_sys_fail(0);
  4670. }
  4671. else {
  4672. errno = EPERM;
  4673. rb_sys_fail(0);
  4674. }
  4675. #elif defined HAVE_SETUID
  4676. if (getuid() == uid && SAVED_USER_ID == uid) {
  4677. if (setuid(uid) < 0) rb_sys_fail(0);
  4678. }
  4679. else {
  4680. errno = EPERM;
  4681. rb_sys_fail(0);
  4682. }
  4683. #else
  4684. rb_notimplement();
  4685. #endif
  4686. }
  4687. return id;
  4688. }
  4689. #if defined HAVE_SETGID
  4690. /*
  4691. * call-seq:
  4692. * Process::Sys.setgid(group) -> nil
  4693. *
  4694. * Set the group ID of the current process to _group_. Not
  4695. * available on all platforms.
  4696. *
  4697. */
  4698. static VALUE
  4699. p_sys_setgid(VALUE obj, VALUE id)
  4700. {
  4701. PREPARE_GETGRNAM;
  4702. check_gid_switch();
  4703. if (setgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
  4704. return Qnil;
  4705. }
  4706. #else
  4707. #define p_sys_setgid rb_f_notimplement
  4708. #endif
  4709. #if defined HAVE_SETRGID
  4710. /*
  4711. * call-seq:
  4712. * Process::Sys.setrgid(group) -> nil
  4713. *
  4714. * Set the real group ID of the calling process to _group_.
  4715. * Not available on all platforms.
  4716. *
  4717. */
  4718. static VALUE
  4719. p_sys_setrgid(VALUE obj, VALUE id)
  4720. {
  4721. PREPARE_GETGRNAM;
  4722. check_gid_switch();
  4723. if (setrgid(OBJ2GID(id)) != 0) rb_sys_fail(0);
  4724. return Qnil;
  4725. }
  4726. #else
  4727. #define p_sys_setrgid rb_f_notimplement
  4728. #endif
  4729. #if defined HAVE_SETEGID
  4730. /*
  4731. * call-seq:
  4732. * Process::Sys.setegid(group) -> nil
  4733. *
  4734. * Set the effective group ID of the calling process to
  4735. * _group_. Not available on all platforms.
  4736. *
  4737. */
  4738. static VALUE
  4739. p_sys_setegid(VALUE obj, VALUE id)
  4740. {
  4741. PREPARE_GETGRNAM;
  4742. check_gid_switch();
  4743. if (setegid(OBJ2GID(id)) != 0) rb_sys_fail(0);
  4744. return Qnil;
  4745. }
  4746. #else
  4747. #define p_sys_setegid rb_f_notimplement
  4748. #endif
  4749. #if defined HAVE_SETREGID
  4750. /*
  4751. * call-seq:
  4752. * Process::Sys.setregid(rid, eid) -> nil
  4753. *
  4754. * Sets the (group) real and/or effective group IDs of the current
  4755. * process to <em>rid</em> and <em>eid</em>, respectively. A value of
  4756. * <code>-1</code> for either means to leave that ID unchanged. Not
  4757. * available on all platforms.
  4758. *
  4759. */
  4760. static VALUE
  4761. p_sys_setregid(VALUE obj, VALUE rid, VALUE eid)
  4762. {
  4763. PREPARE_GETGRNAM;
  4764. check_gid_switch();
  4765. if (setregid(OBJ2GID(rid), OBJ2GID(eid)) != 0) rb_sys_fail(0);
  4766. return Qnil;
  4767. }
  4768. #else
  4769. #define p_sys_setregid rb_f_notimplement
  4770. #endif
  4771. #if defined HAVE_SETRESGID
  4772. /*
  4773. * call-seq:
  4774. * Process::Sys.setresgid(rid, eid, sid) -> nil
  4775. *
  4776. * Sets the (group) real, effective, and saved user IDs of the
  4777. * current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
  4778. * respectively. A value of <code>-1</code> for any value means to
  4779. * leave that ID unchanged. Not available on all platforms.
  4780. *
  4781. */
  4782. static VALUE
  4783. p_sys_setresgid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
  4784. {
  4785. PREPARE_GETGRNAM;
  4786. check_gid_switch();
  4787. if (setresgid(OBJ2GID(rid), OBJ2GID(eid), OBJ2GID(sid)) != 0) rb_sys_fail(0);
  4788. return Qnil;
  4789. }
  4790. #else
  4791. #define p_sys_setresgid rb_f_notimplement
  4792. #endif
  4793. #if defined HAVE_ISSETUGID
  4794. /*
  4795. * call-seq:
  4796. * Process::Sys.issetugid -> true or false
  4797. *
  4798. * Returns +true+ if the process was created as a result
  4799. * of an execve(2) system call which had either of the setuid or
  4800. * setgid bits set (and extra privileges were given as a result) or
  4801. * if it has changed any of its real, effective or saved user or
  4802. * group IDs since it began execution.
  4803. *
  4804. */
  4805. static VALUE
  4806. p_sys_issetugid(VALUE obj)
  4807. {
  4808. rb_secure(2);
  4809. if (issetugid()) {
  4810. return Qtrue;
  4811. }
  4812. else {
  4813. return Qfalse;
  4814. }
  4815. }
  4816. #else
  4817. #define p_sys_issetugid rb_f_notimplement
  4818. #endif
  4819. /*
  4820. * call-seq:
  4821. * Process.gid -> fixnum
  4822. * Process::GID.rid -> fixnum
  4823. * Process::Sys.getgid -> fixnum
  4824. *
  4825. * Returns the (real) group ID for this process.
  4826. *
  4827. * Process.gid #=> 500
  4828. */
  4829. static VALUE
  4830. proc_getgid(VALUE obj)
  4831. {
  4832. rb_gid_t gid = getgid();
  4833. return GIDT2NUM(gid);
  4834. }
  4835. #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETRGID) || defined(HAVE_SETGID)
  4836. /*
  4837. * call-seq:
  4838. * Process.gid= fixnum -> fixnum
  4839. *
  4840. * Sets the group ID for this process.
  4841. */
  4842. static VALUE
  4843. proc_setgid(VALUE obj, VALUE id)
  4844. {
  4845. rb_gid_t gid;
  4846. PREPARE_GETGRNAM;
  4847. check_gid_switch();
  4848. gid = OBJ2GID(id);
  4849. #if defined(HAVE_SETRESGID)
  4850. if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
  4851. #elif defined HAVE_SETREGID
  4852. if (setregid(gid, -1) < 0) rb_sys_fail(0);
  4853. #elif defined HAVE_SETRGID
  4854. if (setrgid(gid) < 0) rb_sys_fail(0);
  4855. #elif defined HAVE_SETGID
  4856. {
  4857. if (getegid() == gid) {
  4858. if (setgid(gid) < 0) rb_sys_fail(0);
  4859. }
  4860. else {
  4861. rb_notimplement();
  4862. }
  4863. }
  4864. #endif
  4865. return GIDT2NUM(gid);
  4866. }
  4867. #else
  4868. #define proc_setgid rb_f_notimplement
  4869. #endif
  4870. #if defined(HAVE_SETGROUPS) || defined(HAVE_GETGROUPS)
  4871. /*
  4872. * Maximum supplementary groups are platform dependent.
  4873. * FWIW, 65536 is enough big for our supported OSs.
  4874. *
  4875. * OS Name max groups
  4876. * -----------------------------------------------
  4877. * Linux Kernel >= 2.6.3 65536
  4878. * Linux Kernel < 2.6.3 32
  4879. * IBM AIX 5.2 64
  4880. * IBM AIX 5.3 ... 6.1 128
  4881. * IBM AIX 7.1 128 (can be configured to be up to 2048)
  4882. * OpenBSD, NetBSD 16
  4883. * FreeBSD < 8.0 16
  4884. * FreeBSD >=8.0 1023
  4885. * Darwin (Mac OS X) 16
  4886. * Sun Solaris 7,8,9,10 16
  4887. * Sun Solaris 11 / OpenSolaris 1024
  4888. * HP-UX 20
  4889. * Windows 1015
  4890. */
  4891. #define RB_MAX_GROUPS (65536)
  4892. static int _maxgroups = -1;
  4893. static int
  4894. get_sc_ngroups_max(void)
  4895. {
  4896. #ifdef _SC_NGROUPS_MAX
  4897. return (int)sysconf(_SC_NGROUPS_MAX);
  4898. #elif defined(NGROUPS_MAX)
  4899. return (int)NGROUPS_MAX;
  4900. #else
  4901. return -1;
  4902. #endif
  4903. }
  4904. static int
  4905. maxgroups(void)
  4906. {
  4907. if (_maxgroups < 0) {
  4908. _maxgroups = get_sc_ngroups_max();
  4909. if (_maxgroups < 0)
  4910. _maxgroups = RB_MAX_GROUPS;
  4911. }
  4912. return _maxgroups;
  4913. }
  4914. #endif
  4915. #ifdef HAVE_GETGROUPS
  4916. /*
  4917. * call-seq:
  4918. * Process.groups -> array
  4919. *
  4920. * Get an <code>Array</code> of the gids of groups in the
  4921. * supplemental group access list for this process.
  4922. *
  4923. * Process.groups #=> [27, 6, 10, 11]
  4924. *
  4925. */
  4926. static VALUE
  4927. proc_getgroups(VALUE obj)
  4928. {
  4929. VALUE ary;
  4930. int i, ngroups;
  4931. rb_gid_t *groups;
  4932. ngroups = getgroups(0, NULL);
  4933. if (ngroups == -1)
  4934. rb_sys_fail(0);
  4935. groups = ALLOCA_N(rb_gid_t, ngroups);
  4936. ngroups = getgroups(ngroups, groups);
  4937. if (ngroups == -1)
  4938. rb_sys_fail(0);
  4939. ary = rb_ary_new();
  4940. for (i = 0; i < ngroups; i++)
  4941. rb_ary_push(ary, GIDT2NUM(groups[i]));
  4942. return ary;
  4943. }
  4944. #else
  4945. #define proc_getgroups rb_f_notimplement
  4946. #endif
  4947. #ifdef HAVE_SETGROUPS
  4948. /*
  4949. * call-seq:
  4950. * Process.groups= array -> array
  4951. *
  4952. * Set the supplemental group access list to the given
  4953. * <code>Array</code> of group IDs.
  4954. *
  4955. * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
  4956. * Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11]
  4957. * Process.groups #=> [27, 6, 10, 11]
  4958. *
  4959. */
  4960. static VALUE
  4961. proc_setgroups(VALUE obj, VALUE ary)
  4962. {
  4963. int ngroups, i;
  4964. rb_gid_t *groups;
  4965. PREPARE_GETGRNAM;
  4966. Check_Type(ary, T_ARRAY);
  4967. ngroups = RARRAY_LENINT(ary);
  4968. if (ngroups > maxgroups())
  4969. rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());
  4970. groups = ALLOCA_N(rb_gid_t, ngroups);
  4971. for (i = 0; i < ngroups; i++) {
  4972. VALUE g = RARRAY_PTR(ary)[i];
  4973. groups[i] = OBJ2GID(g);
  4974. }
  4975. if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
  4976. rb_sys_fail(0);
  4977. return proc_getgroups(obj);
  4978. }
  4979. #else
  4980. #define proc_setgroups rb_f_notimplement
  4981. #endif
  4982. #ifdef HAVE_INITGROUPS
  4983. /*
  4984. * call-seq:
  4985. * Process.initgroups(username, gid) -> array
  4986. *
  4987. * Initializes the supplemental group access list by reading the
  4988. * system group database and using all groups of which the given user
  4989. * is a member. The group with the specified <em>gid</em> is also
  4990. * added to the list. Returns the resulting <code>Array</code> of the
  4991. * gids of all the groups in the supplementary group access list. Not
  4992. * available on all platforms.
  4993. *
  4994. * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
  4995. * Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
  4996. * Process.groups #=> [30, 6, 10, 11]
  4997. *
  4998. */
  4999. static VALUE
  5000. proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
  5001. {
  5002. PREPARE_GETGRNAM;
  5003. if (initgroups(StringValuePtr(uname), OBJ2GID(base_grp)) != 0) {
  5004. rb_sys_fail(0);
  5005. }
  5006. return proc_getgroups(obj);
  5007. }
  5008. #else
  5009. #define proc_initgroups rb_f_notimplement
  5010. #endif
  5011. #if defined(_SC_NGROUPS_MAX) || defined(NGROUPS_MAX)
  5012. /*
  5013. * call-seq:
  5014. * Process.maxgroups -> fixnum
  5015. *
  5016. * Returns the maximum number of gids allowed in the supplemental
  5017. * group access list.
  5018. *
  5019. * Process.maxgroups #=> 32
  5020. */
  5021. static VALUE
  5022. proc_getmaxgroups(VALUE obj)
  5023. {
  5024. return INT2FIX(maxgroups());
  5025. }
  5026. #else
  5027. #define proc_getmaxgroups rb_f_notimplement
  5028. #endif
  5029. #ifdef HAVE_SETGROUPS
  5030. /*
  5031. * call-seq:
  5032. * Process.maxgroups= fixnum -> fixnum
  5033. *
  5034. * Sets the maximum number of gids allowed in the supplemental group
  5035. * access list.
  5036. */
  5037. static VALUE
  5038. proc_setmaxgroups(VALUE obj, VALUE val)
  5039. {
  5040. int ngroups = FIX2INT(val);
  5041. int ngroups_max = get_sc_ngroups_max();
  5042. if (ngroups <= 0)
  5043. rb_raise(rb_eArgError, "maxgroups %d shold be positive", ngroups);
  5044. if (ngroups > RB_MAX_GROUPS)
  5045. ngroups = RB_MAX_GROUPS;
  5046. if (ngroups_max > 0 && ngroups > ngroups_max)
  5047. ngroups = ngroups_max;
  5048. _maxgroups = ngroups;
  5049. return INT2FIX(_maxgroups);
  5050. }
  5051. #else
  5052. #define proc_setmaxgroups rb_f_notimplement
  5053. #endif
  5054. #if defined(HAVE_DAEMON) || (defined(HAVE_FORK) && defined(HAVE_SETSID))
  5055. static int rb_daemon(int nochdir, int noclose);
  5056. /*
  5057. * call-seq:
  5058. * Process.daemon() -> 0
  5059. * Process.daemon(nochdir=nil,noclose=nil) -> 0
  5060. *
  5061. * Detach the process from controlling terminal and run in
  5062. * the background as system daemon. Unless the argument
  5063. * nochdir is true (i.e. non false), it changes the current
  5064. * working directory to the root ("/"). Unless the argument
  5065. * noclose is true, daemon() will redirect standard input,
  5066. * standard output and standard error to /dev/null.
  5067. * Return zero on success, or raise one of Errno::*.
  5068. */
  5069. static VALUE
  5070. proc_daemon(int argc, VALUE *argv)
  5071. {
  5072. VALUE nochdir, noclose;
  5073. int n;
  5074. rb_secure(2);
  5075. rb_scan_args(argc, argv, "02", &nochdir, &noclose);
  5076. prefork();
  5077. n = rb_daemon(RTEST(nochdir), RTEST(noclose));
  5078. if (n < 0) rb_sys_fail("daemon");
  5079. return INT2FIX(n);
  5080. }
  5081. static int
  5082. rb_daemon(int nochdir, int noclose)
  5083. {
  5084. int err = 0;
  5085. #ifdef HAVE_DAEMON
  5086. before_fork();
  5087. err = daemon(nochdir, noclose);
  5088. after_fork();
  5089. #else
  5090. int n;
  5091. switch (rb_fork_ruby(NULL)) {
  5092. case -1:
  5093. rb_sys_fail("daemon");
  5094. case 0:
  5095. break;
  5096. default:
  5097. _exit(EXIT_SUCCESS);
  5098. }
  5099. proc_setsid();
  5100. /* must not be process-leader */
  5101. switch (rb_fork_ruby(NULL)) {
  5102. case -1:
  5103. return -1;
  5104. case 0:
  5105. break;
  5106. default:
  5107. _exit(EXIT_SUCCESS);
  5108. }
  5109. if (!nochdir)
  5110. err = chdir("/");
  5111. if (!noclose && (n = rb_cloexec_open("/dev/null", O_RDWR, 0)) != -1) {
  5112. rb_update_max_fd(n);
  5113. (void)dup2(n, 0);
  5114. (void)dup2(n, 1);
  5115. (void)dup2(n, 2);
  5116. if (n > 2)
  5117. (void)close (n);
  5118. }
  5119. #endif
  5120. return err;
  5121. }
  5122. #else
  5123. #define proc_daemon rb_f_notimplement
  5124. #endif
  5125. /********************************************************************
  5126. *
  5127. * Document-class: Process::GID
  5128. *
  5129. * The <code>Process::GID</code> module contains a collection of
  5130. * module functions which can be used to portably get, set, and
  5131. * switch the current process's real, effective, and saved group IDs.
  5132. *
  5133. */
  5134. static rb_gid_t SAVED_GROUP_ID = -1;
  5135. #ifdef BROKEN_SETREGID
  5136. int
  5137. setregid(rb_gid_t rgid, rb_gid_t egid)
  5138. {
  5139. if (rgid != (rb_gid_t)-1 && rgid != getgid()) {
  5140. if (egid == (rb_gid_t)-1) egid = getegid();
  5141. if (setgid(rgid) < 0) return -1;
  5142. }
  5143. if (egid != (rb_gid_t)-1 && egid != getegid()) {
  5144. if (setegid(egid) < 0) return -1;
  5145. }
  5146. return 0;
  5147. }
  5148. #endif
  5149. /*
  5150. * call-seq:
  5151. * Process::GID.change_privilege(group) -> fixnum
  5152. *
  5153. * Change the current process's real and effective group ID to that
  5154. * specified by _group_. Returns the new group ID. Not
  5155. * available on all platforms.
  5156. *
  5157. * [Process.gid, Process.egid] #=> [0, 0]
  5158. * Process::GID.change_privilege(33) #=> 33
  5159. * [Process.gid, Process.egid] #=> [33, 33]
  5160. */
  5161. static VALUE
  5162. p_gid_change_privilege(VALUE obj, VALUE id)
  5163. {
  5164. rb_gid_t gid;
  5165. PREPARE_GETGRNAM;
  5166. check_gid_switch();
  5167. gid = OBJ2GID(id);
  5168. if (geteuid() == 0) { /* root-user */
  5169. #if defined(HAVE_SETRESGID)
  5170. if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
  5171. SAVED_GROUP_ID = gid;
  5172. #elif defined HAVE_SETGID
  5173. if (setgid(gid) < 0) rb_sys_fail(0);
  5174. SAVED_GROUP_ID = gid;
  5175. #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
  5176. if (getgid() == gid) {
  5177. if (SAVED_GROUP_ID == gid) {
  5178. if (setregid(-1, gid) < 0) rb_sys_fail(0);
  5179. }
  5180. else {
  5181. if (gid == 0) { /* (r,e,s) == (root, y, x) */
  5182. if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
  5183. if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
  5184. SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
  5185. if (setregid(gid, gid) < 0) rb_sys_fail(0);
  5186. SAVED_GROUP_ID = gid;
  5187. }
  5188. else { /* (r,e,s) == (z, y, x) */
  5189. if (setregid(0, 0) < 0) rb_sys_fail(0);
  5190. SAVED_GROUP_ID = 0;
  5191. if (setregid(gid, gid) < 0) rb_sys_fail(0);
  5192. SAVED_GROUP_ID = gid;
  5193. }
  5194. }
  5195. }
  5196. else {
  5197. if (setregid(gid, gid) < 0) rb_sys_fail(0);
  5198. SAVED_GROUP_ID = gid;
  5199. }
  5200. #elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
  5201. if (getgid() == gid) {
  5202. if (SAVED_GROUP_ID == gid) {
  5203. if (setegid(gid) < 0) rb_sys_fail(0);
  5204. }
  5205. else {
  5206. if (gid == 0) {
  5207. if (setegid(gid) < 0) rb_sys_fail(0);
  5208. if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
  5209. SAVED_GROUP_ID = 0;
  5210. if (setrgid(0) < 0) rb_sys_fail(0);
  5211. }
  5212. else {
  5213. if (setrgid(0) < 0) rb_sys_fail(0);
  5214. SAVED_GROUP_ID = 0;
  5215. if (setegid(gid) < 0) rb_sys_fail(0);
  5216. if (setrgid(gid) < 0) rb_sys_fail(0);
  5217. SAVED_GROUP_ID = gid;
  5218. }
  5219. }
  5220. }
  5221. else {
  5222. if (setegid(gid) < 0) rb_sys_fail(0);
  5223. if (setrgid(gid) < 0) rb_sys_fail(0);
  5224. SAVED_GROUP_ID = gid;
  5225. }
  5226. #else
  5227. rb_notimplement();
  5228. #endif
  5229. }
  5230. else { /* unprivileged user */
  5231. #if defined(HAVE_SETRESGID)
  5232. if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
  5233. (getegid() == gid)? (rb_gid_t)-1: gid,
  5234. (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
  5235. SAVED_GROUP_ID = gid;
  5236. #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
  5237. if (SAVED_GROUP_ID == gid) {
  5238. if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
  5239. (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
  5240. rb_sys_fail(0);
  5241. }
  5242. else if (getgid() != gid) {
  5243. if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
  5244. rb_sys_fail(0);
  5245. SAVED_GROUP_ID = gid;
  5246. }
  5247. else if (/* getgid() == gid && */ getegid() != gid) {
  5248. if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
  5249. SAVED_GROUP_ID = gid;
  5250. if (setregid(gid, -1) < 0) rb_sys_fail(0);
  5251. }
  5252. else { /* getgid() == gid && getegid() == gid */
  5253. if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
  5254. if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
  5255. SAVED_GROUP_ID = gid;
  5256. if (setregid(gid, -1) < 0) rb_sys_fail(0);
  5257. }
  5258. #elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
  5259. if (SAVED_GROUP_ID == gid) {
  5260. if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
  5261. if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
  5262. }
  5263. else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
  5264. if (getgid() != gid) {
  5265. if (setrgid(gid) < 0) rb_sys_fail(0);
  5266. SAVED_GROUP_ID = gid;
  5267. }
  5268. else {
  5269. if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
  5270. SAVED_GROUP_ID = gid;
  5271. if (setrgid(gid) < 0) rb_sys_fail(0);
  5272. }
  5273. }
  5274. else if (/* getegid() != gid && */ getgid() == gid) {
  5275. if (setegid(gid) < 0) rb_sys_fail(0);
  5276. if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
  5277. SAVED_GROUP_ID = gid;
  5278. if (setrgid(gid) < 0) rb_sys_fail(0);
  5279. }
  5280. else {
  5281. errno = EPERM;
  5282. rb_sys_fail(0);
  5283. }
  5284. #elif defined HAVE_44BSD_SETGID
  5285. if (getgid() == gid) {
  5286. /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
  5287. if (setgid(gid) < 0) rb_sys_fail(0);
  5288. SAVED_GROUP_ID = gid;
  5289. }
  5290. else {
  5291. errno = EPERM;
  5292. rb_sys_fail(0);
  5293. }
  5294. #elif defined HAVE_SETEGID
  5295. if (getgid() == gid && SAVED_GROUP_ID == gid) {
  5296. if (setegid(gid) < 0) rb_sys_fail(0);
  5297. }
  5298. else {
  5299. errno = EPERM;
  5300. rb_sys_fail(0);
  5301. }
  5302. #elif defined HAVE_SETGID
  5303. if (getgid() == gid && SAVED_GROUP_ID == gid) {
  5304. if (setgid(gid) < 0) rb_sys_fail(0);
  5305. }
  5306. else {
  5307. errno = EPERM;
  5308. rb_sys_fail(0);
  5309. }
  5310. #else
  5311. (void)gid;
  5312. rb_notimplement();
  5313. #endif
  5314. }
  5315. return id;
  5316. }
  5317. /*
  5318. * call-seq:
  5319. * Process.euid -> fixnum
  5320. * Process::UID.eid -> fixnum
  5321. * Process::Sys.geteuid -> fixnum
  5322. *
  5323. * Returns the effective user ID for this process.
  5324. *
  5325. * Process.euid #=> 501
  5326. */
  5327. static VALUE
  5328. proc_geteuid(VALUE obj)
  5329. {
  5330. rb_uid_t euid = geteuid();
  5331. return UIDT2NUM(euid);
  5332. }
  5333. #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID) || defined(_POSIX_SAVED_IDS)
  5334. static void
  5335. proc_seteuid(rb_uid_t uid)
  5336. {
  5337. #if defined(HAVE_SETRESUID)
  5338. if (setresuid(-1, uid, -1) < 0) rb_sys_fail(0);
  5339. #elif defined HAVE_SETREUID
  5340. if (setreuid(-1, uid) < 0) rb_sys_fail(0);
  5341. #elif defined HAVE_SETEUID
  5342. if (seteuid(uid) < 0) rb_sys_fail(0);
  5343. #elif defined HAVE_SETUID
  5344. if (uid == getuid()) {
  5345. if (setuid(uid) < 0) rb_sys_fail(0);
  5346. }
  5347. else {
  5348. rb_notimplement();
  5349. }
  5350. #else
  5351. rb_notimplement();
  5352. #endif
  5353. }
  5354. #endif
  5355. #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) || defined(HAVE_SETUID)
  5356. /*
  5357. * call-seq:
  5358. * Process.euid= user
  5359. *
  5360. * Sets the effective user ID for this process. Not available on all
  5361. * platforms.
  5362. */
  5363. static VALUE
  5364. proc_seteuid_m(VALUE mod, VALUE euid)
  5365. {
  5366. PREPARE_GETPWNAM;
  5367. check_uid_switch();
  5368. proc_seteuid(OBJ2UID(euid));
  5369. return euid;
  5370. }
  5371. #else
  5372. #define proc_seteuid_m rb_f_notimplement
  5373. #endif
  5374. static rb_uid_t
  5375. rb_seteuid_core(rb_uid_t euid)
  5376. {
  5377. #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
  5378. rb_uid_t uid;
  5379. #endif
  5380. check_uid_switch();
  5381. #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
  5382. uid = getuid();
  5383. #endif
  5384. #if defined(HAVE_SETRESUID)
  5385. if (uid != euid) {
  5386. if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
  5387. SAVED_USER_ID = euid;
  5388. }
  5389. else {
  5390. if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
  5391. }
  5392. #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
  5393. if (setreuid(-1, euid) < 0) rb_sys_fail(0);
  5394. if (uid != euid) {
  5395. if (setreuid(euid,uid) < 0) rb_sys_fail(0);
  5396. if (setreuid(uid,euid) < 0) rb_sys_fail(0);
  5397. SAVED_USER_ID = euid;
  5398. }
  5399. #elif defined HAVE_SETEUID
  5400. if (seteuid(euid) < 0) rb_sys_fail(0);
  5401. #elif defined HAVE_SETUID
  5402. if (geteuid() == 0) rb_sys_fail(0);
  5403. if (setuid(euid) < 0) rb_sys_fail(0);
  5404. #else
  5405. rb_notimplement();
  5406. #endif
  5407. return euid;
  5408. }
  5409. /*
  5410. * call-seq:
  5411. * Process::UID.grant_privilege(user) -> fixnum
  5412. * Process::UID.eid= user -> fixnum
  5413. *
  5414. * Set the effective user ID, and if possible, the saved user ID of
  5415. * the process to the given _user_. Returns the new
  5416. * effective user ID. Not available on all platforms.
  5417. *
  5418. * [Process.uid, Process.euid] #=> [0, 0]
  5419. * Process::UID.grant_privilege(31) #=> 31
  5420. * [Process.uid, Process.euid] #=> [0, 31]
  5421. */
  5422. static VALUE
  5423. p_uid_grant_privilege(VALUE obj, VALUE id)
  5424. {
  5425. PREPARE_GETPWNAM;
  5426. rb_seteuid_core(OBJ2UID(id));
  5427. return id;
  5428. }
  5429. /*
  5430. * call-seq:
  5431. * Process.egid -> fixnum
  5432. * Process::GID.eid -> fixnum
  5433. * Process::Sys.geteid -> fixnum
  5434. *
  5435. * Returns the effective group ID for this process. Not available on
  5436. * all platforms.
  5437. *
  5438. * Process.egid #=> 500
  5439. */
  5440. static VALUE
  5441. proc_getegid(VALUE obj)
  5442. {
  5443. rb_gid_t egid = getegid();
  5444. return GIDT2NUM(egid);
  5445. }
  5446. #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID) || defined(_POSIX_SAVED_IDS)
  5447. /*
  5448. * call-seq:
  5449. * Process.egid = fixnum -> fixnum
  5450. *
  5451. * Sets the effective group ID for this process. Not available on all
  5452. * platforms.
  5453. */
  5454. static VALUE
  5455. proc_setegid(VALUE obj, VALUE egid)
  5456. {
  5457. #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
  5458. rb_gid_t gid;
  5459. PREPARE_GETGRNAM;
  5460. #endif
  5461. check_gid_switch();
  5462. #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
  5463. gid = OBJ2GID(egid);
  5464. #endif
  5465. #if defined(HAVE_SETRESGID)
  5466. if (setresgid(-1, gid, -1) < 0) rb_sys_fail(0);
  5467. #elif defined HAVE_SETREGID
  5468. if (setregid(-1, gid) < 0) rb_sys_fail(0);
  5469. #elif defined HAVE_SETEGID
  5470. if (setegid(gid) < 0) rb_sys_fail(0);
  5471. #elif defined HAVE_SETGID
  5472. if (gid == getgid()) {
  5473. if (setgid(gid) < 0) rb_sys_fail(0);
  5474. }
  5475. else {
  5476. rb_notimplement();
  5477. }
  5478. #else
  5479. rb_notimplement();
  5480. #endif
  5481. return egid;
  5482. }
  5483. #endif
  5484. #if defined(HAVE_SETRESGID) || defined(HAVE_SETREGID) || defined(HAVE_SETEGID) || defined(HAVE_SETGID)
  5485. #define proc_setegid_m proc_setegid
  5486. #else
  5487. #define proc_setegid_m rb_f_notimplement
  5488. #endif
  5489. static rb_gid_t
  5490. rb_setegid_core(rb_gid_t egid)
  5491. {
  5492. #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
  5493. rb_gid_t gid;
  5494. #endif
  5495. check_gid_switch();
  5496. #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
  5497. gid = getgid();
  5498. #endif
  5499. #if defined(HAVE_SETRESGID)
  5500. if (gid != egid) {
  5501. if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
  5502. SAVED_GROUP_ID = egid;
  5503. }
  5504. else {
  5505. if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
  5506. }
  5507. #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
  5508. if (setregid(-1, egid) < 0) rb_sys_fail(0);
  5509. if (gid != egid) {
  5510. if (setregid(egid,gid) < 0) rb_sys_fail(0);
  5511. if (setregid(gid,egid) < 0) rb_sys_fail(0);
  5512. SAVED_GROUP_ID = egid;
  5513. }
  5514. #elif defined HAVE_SETEGID
  5515. if (setegid(egid) < 0) rb_sys_fail(0);
  5516. #elif defined HAVE_SETGID
  5517. if (geteuid() == 0 /* root user */) rb_sys_fail(0);
  5518. if (setgid(egid) < 0) rb_sys_fail(0);
  5519. #else
  5520. rb_notimplement();
  5521. #endif
  5522. return egid;
  5523. }
  5524. /*
  5525. * call-seq:
  5526. * Process::GID.grant_privilege(group) -> fixnum
  5527. * Process::GID.eid = group -> fixnum
  5528. *
  5529. * Set the effective group ID, and if possible, the saved group ID of
  5530. * the process to the given _group_. Returns the new
  5531. * effective group ID. Not available on all platforms.
  5532. *
  5533. * [Process.gid, Process.egid] #=> [0, 0]
  5534. * Process::GID.grant_privilege(31) #=> 33
  5535. * [Process.gid, Process.egid] #=> [0, 33]
  5536. */
  5537. static VALUE
  5538. p_gid_grant_privilege(VALUE obj, VALUE id)
  5539. {
  5540. PREPARE_GETGRNAM;
  5541. rb_setegid_core(OBJ2GID(id));
  5542. return id;
  5543. }
  5544. /*
  5545. * call-seq:
  5546. * Process::UID.re_exchangeable? -> true or false
  5547. *
  5548. * Returns +true+ if the real and effective user IDs of a
  5549. * process may be exchanged on the current platform.
  5550. *
  5551. */
  5552. static VALUE
  5553. p_uid_exchangeable(void)
  5554. {
  5555. #if defined(HAVE_SETRESUID)
  5556. return Qtrue;
  5557. #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
  5558. return Qtrue;
  5559. #else
  5560. return Qfalse;
  5561. #endif
  5562. }
  5563. /*
  5564. * call-seq:
  5565. * Process::UID.re_exchange -> fixnum
  5566. *
  5567. * Exchange real and effective user IDs and return the new effective
  5568. * user ID. Not available on all platforms.
  5569. *
  5570. * [Process.uid, Process.euid] #=> [0, 31]
  5571. * Process::UID.re_exchange #=> 0
  5572. * [Process.uid, Process.euid] #=> [31, 0]
  5573. */
  5574. static VALUE
  5575. p_uid_exchange(VALUE obj)
  5576. {
  5577. rb_uid_t uid;
  5578. #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
  5579. rb_uid_t euid;
  5580. #endif
  5581. check_uid_switch();
  5582. uid = getuid();
  5583. #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
  5584. euid = geteuid();
  5585. #endif
  5586. #if defined(HAVE_SETRESUID)
  5587. if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
  5588. SAVED_USER_ID = uid;
  5589. #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
  5590. if (setreuid(euid,uid) < 0) rb_sys_fail(0);
  5591. SAVED_USER_ID = uid;
  5592. #else
  5593. rb_notimplement();
  5594. #endif
  5595. return UIDT2NUM(uid);
  5596. }
  5597. /*
  5598. * call-seq:
  5599. * Process::GID.re_exchangeable? -> true or false
  5600. *
  5601. * Returns +true+ if the real and effective group IDs of a
  5602. * process may be exchanged on the current platform.
  5603. *
  5604. */
  5605. static VALUE
  5606. p_gid_exchangeable(void)
  5607. {
  5608. #if defined(HAVE_SETRESGID)
  5609. return Qtrue;
  5610. #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
  5611. return Qtrue;
  5612. #else
  5613. return Qfalse;
  5614. #endif
  5615. }
  5616. /*
  5617. * call-seq:
  5618. * Process::GID.re_exchange -> fixnum
  5619. *
  5620. * Exchange real and effective group IDs and return the new effective
  5621. * group ID. Not available on all platforms.
  5622. *
  5623. * [Process.gid, Process.egid] #=> [0, 33]
  5624. * Process::GID.re_exchange #=> 0
  5625. * [Process.gid, Process.egid] #=> [33, 0]
  5626. */
  5627. static VALUE
  5628. p_gid_exchange(VALUE obj)
  5629. {
  5630. rb_gid_t gid;
  5631. #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
  5632. rb_gid_t egid;
  5633. #endif
  5634. check_gid_switch();
  5635. gid = getgid();
  5636. #if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
  5637. egid = getegid();
  5638. #endif
  5639. #if defined(HAVE_SETRESGID)
  5640. if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
  5641. SAVED_GROUP_ID = gid;
  5642. #elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
  5643. if (setregid(egid,gid) < 0) rb_sys_fail(0);
  5644. SAVED_GROUP_ID = gid;
  5645. #else
  5646. rb_notimplement();
  5647. #endif
  5648. return GIDT2NUM(gid);
  5649. }
  5650. /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
  5651. /*
  5652. * call-seq:
  5653. * Process::UID.sid_available? -> true or false
  5654. *
  5655. * Returns +true+ if the current platform has saved user
  5656. * ID functionality.
  5657. *
  5658. */
  5659. static VALUE
  5660. p_uid_have_saved_id(void)
  5661. {
  5662. #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
  5663. return Qtrue;
  5664. #else
  5665. return Qfalse;
  5666. #endif
  5667. }
  5668. #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
  5669. static VALUE
  5670. p_uid_sw_ensure(rb_uid_t id)
  5671. {
  5672. under_uid_switch = 0;
  5673. id = rb_seteuid_core(id);
  5674. return UIDT2NUM(id);
  5675. }
  5676. /*
  5677. * call-seq:
  5678. * Process::UID.switch -> fixnum
  5679. * Process::UID.switch {|| block} -> object
  5680. *
  5681. * Switch the effective and real user IDs of the current process. If
  5682. * a <em>block</em> is given, the user IDs will be switched back
  5683. * after the block is executed. Returns the new effective user ID if
  5684. * called without a block, and the return value of the block if one
  5685. * is given.
  5686. *
  5687. */
  5688. static VALUE
  5689. p_uid_switch(VALUE obj)
  5690. {
  5691. rb_uid_t uid, euid;
  5692. check_uid_switch();
  5693. uid = getuid();
  5694. euid = geteuid();
  5695. if (uid != euid) {
  5696. proc_seteuid(uid);
  5697. if (rb_block_given_p()) {
  5698. under_uid_switch = 1;
  5699. return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
  5700. }
  5701. else {
  5702. return UIDT2NUM(euid);
  5703. }
  5704. }
  5705. else if (euid != SAVED_USER_ID) {
  5706. proc_seteuid(SAVED_USER_ID);
  5707. if (rb_block_given_p()) {
  5708. under_uid_switch = 1;
  5709. return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
  5710. }
  5711. else {
  5712. return UIDT2NUM(uid);
  5713. }
  5714. }
  5715. else {
  5716. errno = EPERM;
  5717. rb_sys_fail(0);
  5718. }
  5719. UNREACHABLE;
  5720. }
  5721. #else
  5722. static VALUE
  5723. p_uid_sw_ensure(VALUE obj)
  5724. {
  5725. under_uid_switch = 0;
  5726. return p_uid_exchange(obj);
  5727. }
  5728. static VALUE
  5729. p_uid_switch(VALUE obj)
  5730. {
  5731. rb_uid_t uid, euid;
  5732. check_uid_switch();
  5733. uid = getuid();
  5734. euid = geteuid();
  5735. if (uid == euid) {
  5736. errno = EPERM;
  5737. rb_sys_fail(0);
  5738. }
  5739. p_uid_exchange(obj);
  5740. if (rb_block_given_p()) {
  5741. under_uid_switch = 1;
  5742. return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
  5743. }
  5744. else {
  5745. return UIDT2NUM(euid);
  5746. }
  5747. }
  5748. #endif
  5749. /* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
  5750. /*
  5751. * call-seq:
  5752. * Process::GID.sid_available? -> true or false
  5753. *
  5754. * Returns +true+ if the current platform has saved group
  5755. * ID functionality.
  5756. *
  5757. */
  5758. static VALUE
  5759. p_gid_have_saved_id(void)
  5760. {
  5761. #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
  5762. return Qtrue;
  5763. #else
  5764. return Qfalse;
  5765. #endif
  5766. }
  5767. #if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
  5768. static VALUE
  5769. p_gid_sw_ensure(rb_gid_t id)
  5770. {
  5771. under_gid_switch = 0;
  5772. id = rb_setegid_core(id);
  5773. return GIDT2NUM(id);
  5774. }
  5775. /*
  5776. * call-seq:
  5777. * Process::GID.switch -> fixnum
  5778. * Process::GID.switch {|| block} -> object
  5779. *
  5780. * Switch the effective and real group IDs of the current process. If
  5781. * a <em>block</em> is given, the group IDs will be switched back
  5782. * after the block is executed. Returns the new effective group ID if
  5783. * called without a block, and the return value of the block if one
  5784. * is given.
  5785. *
  5786. */
  5787. static VALUE
  5788. p_gid_switch(VALUE obj)
  5789. {
  5790. rb_gid_t gid, egid;
  5791. check_gid_switch();
  5792. gid = getgid();
  5793. egid = getegid();
  5794. if (gid != egid) {
  5795. proc_setegid(obj, GIDT2NUM(gid));
  5796. if (rb_block_given_p()) {
  5797. under_gid_switch = 1;
  5798. return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
  5799. }
  5800. else {
  5801. return GIDT2NUM(egid);
  5802. }
  5803. }
  5804. else if (egid != SAVED_GROUP_ID) {
  5805. proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
  5806. if (rb_block_given_p()) {
  5807. under_gid_switch = 1;
  5808. return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
  5809. }
  5810. else {
  5811. return GIDT2NUM(gid);
  5812. }
  5813. }
  5814. else {
  5815. errno = EPERM;
  5816. rb_sys_fail(0);
  5817. }
  5818. UNREACHABLE;
  5819. }
  5820. #else
  5821. static VALUE
  5822. p_gid_sw_ensure(VALUE obj)
  5823. {
  5824. under_gid_switch = 0;
  5825. return p_gid_exchange(obj);
  5826. }
  5827. static VALUE
  5828. p_gid_switch(VALUE obj)
  5829. {
  5830. rb_gid_t gid, egid;
  5831. check_gid_switch();
  5832. gid = getgid();
  5833. egid = getegid();
  5834. if (gid == egid) {
  5835. errno = EPERM;
  5836. rb_sys_fail(0);
  5837. }
  5838. p_gid_exchange(obj);
  5839. if (rb_block_given_p()) {
  5840. under_gid_switch = 1;
  5841. return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
  5842. }
  5843. else {
  5844. return GIDT2NUM(egid);
  5845. }
  5846. }
  5847. #endif
  5848. #if defined(HAVE_TIMES)
  5849. /*
  5850. * call-seq:
  5851. * Process.times -> aStructTms
  5852. *
  5853. * Returns a <code>Tms</code> structure (see <code>Struct::Tms</code>)
  5854. * that contains user and system CPU times for this process,
  5855. * and also for children processes.
  5856. *
  5857. * t = Process.times
  5858. * [ t.utime, t.stime, t.cutime, t.cstime ] #=> [0.0, 0.02, 0.00, 0.00]
  5859. */
  5860. VALUE
  5861. rb_proc_times(VALUE obj)
  5862. {
  5863. const double hertz =
  5864. #ifdef HAVE__SC_CLK_TCK
  5865. (double)sysconf(_SC_CLK_TCK);
  5866. #else
  5867. #ifndef HZ
  5868. # ifdef CLK_TCK
  5869. # define HZ CLK_TCK
  5870. # else
  5871. # define HZ 60
  5872. # endif
  5873. #endif /* HZ */
  5874. HZ;
  5875. #endif
  5876. struct tms buf;
  5877. volatile VALUE utime, stime, cutime, sctime;
  5878. times(&buf);
  5879. return rb_struct_new(rb_cProcessTms,
  5880. utime = DBL2NUM(buf.tms_utime / hertz),
  5881. stime = DBL2NUM(buf.tms_stime / hertz),
  5882. cutime = DBL2NUM(buf.tms_cutime / hertz),
  5883. sctime = DBL2NUM(buf.tms_cstime / hertz));
  5884. }
  5885. #else
  5886. #define rb_proc_times rb_f_notimplement
  5887. #endif
  5888. VALUE rb_mProcess;
  5889. VALUE rb_mProcUID;
  5890. VALUE rb_mProcGID;
  5891. VALUE rb_mProcID_Syscall;
  5892. /*
  5893. * The <code>Process</code> module is a collection of methods used to
  5894. * manipulate processes.
  5895. */
  5896. void
  5897. Init_process(void)
  5898. {
  5899. rb_define_virtual_variable("$?", rb_last_status_get, 0);
  5900. rb_define_virtual_variable("$$", get_pid, 0);
  5901. rb_define_global_function("exec", rb_f_exec, -1);
  5902. rb_define_global_function("fork", rb_f_fork, 0);
  5903. rb_define_global_function("exit!", rb_f_exit_bang, -1);
  5904. rb_define_global_function("system", rb_f_system, -1);
  5905. rb_define_global_function("spawn", rb_f_spawn, -1);
  5906. rb_define_global_function("sleep", rb_f_sleep, -1);
  5907. rb_define_global_function("exit", rb_f_exit, -1);
  5908. rb_define_global_function("abort", rb_f_abort, -1);
  5909. rb_mProcess = rb_define_module("Process");
  5910. #ifdef WNOHANG
  5911. /* see Process.wait */
  5912. rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
  5913. #else
  5914. /* see Process.wait */
  5915. rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
  5916. #endif
  5917. #ifdef WUNTRACED
  5918. /* see Process.wait */
  5919. rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
  5920. #else
  5921. /* see Process.wait */
  5922. rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
  5923. #endif
  5924. rb_define_singleton_method(rb_mProcess, "exec", rb_f_exec, -1);
  5925. rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
  5926. rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
  5927. rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
  5928. rb_define_singleton_method(rb_mProcess, "exit", rb_f_exit, -1);
  5929. rb_define_singleton_method(rb_mProcess, "abort", rb_f_abort, -1);
  5930. rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1); /* in signal.c */
  5931. rb_define_module_function(rb_mProcess, "wait", proc_wait, -1);
  5932. rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
  5933. rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
  5934. rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
  5935. rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
  5936. rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
  5937. rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
  5938. rb_undef_method(CLASS_OF(rb_cProcessStatus), "new");
  5939. rb_define_method(rb_cProcessStatus, "==", pst_equal, 1);
  5940. rb_define_method(rb_cProcessStatus, "&", pst_bitand, 1);
  5941. rb_define_method(rb_cProcessStatus, ">>", pst_rshift, 1);
  5942. rb_define_method(rb_cProcessStatus, "to_i", pst_to_i, 0);
  5943. rb_define_method(rb_cProcessStatus, "to_s", pst_to_s, 0);
  5944. rb_define_method(rb_cProcessStatus, "inspect", pst_inspect, 0);
  5945. rb_define_method(rb_cProcessStatus, "pid", pst_pid, 0);
  5946. rb_define_method(rb_cProcessStatus, "stopped?", pst_wifstopped, 0);
  5947. rb_define_method(rb_cProcessStatus, "stopsig", pst_wstopsig, 0);
  5948. rb_define_method(rb_cProcessStatus, "signaled?", pst_wifsignaled, 0);
  5949. rb_define_method(rb_cProcessStatus, "termsig", pst_wtermsig, 0);
  5950. rb_define_method(rb_cProcessStatus, "exited?", pst_wifexited, 0);
  5951. rb_define_method(rb_cProcessStatus, "exitstatus", pst_wexitstatus, 0);
  5952. rb_define_method(rb_cProcessStatus, "success?", pst_success_p, 0);
  5953. rb_define_method(rb_cProcessStatus, "coredump?", pst_wcoredump, 0);
  5954. rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
  5955. rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
  5956. rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, 0);
  5957. rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, 0);
  5958. rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
  5959. rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
  5960. rb_define_module_function(rb_mProcess, "getsid", proc_getsid, -1);
  5961. rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
  5962. rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
  5963. rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
  5964. #ifdef HAVE_GETPRIORITY
  5965. /* see Process.setpriority */
  5966. rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
  5967. /* see Process.setpriority */
  5968. rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
  5969. /* see Process.setpriority */
  5970. rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
  5971. #endif
  5972. rb_define_module_function(rb_mProcess, "getrlimit", proc_getrlimit, 1);
  5973. rb_define_module_function(rb_mProcess, "setrlimit", proc_setrlimit, -1);
  5974. #if defined(RLIM2NUM) && defined(RLIM_INFINITY)
  5975. {
  5976. VALUE inf = RLIM2NUM(RLIM_INFINITY);
  5977. #ifdef RLIM_SAVED_MAX
  5978. {
  5979. VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
  5980. /* see Process.setrlimit */
  5981. rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
  5982. }
  5983. #endif
  5984. /* see Process.setrlimit */
  5985. rb_define_const(rb_mProcess, "RLIM_INFINITY", inf);
  5986. #ifdef RLIM_SAVED_CUR
  5987. {
  5988. VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
  5989. /* see Process.setrlimit */
  5990. rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
  5991. }
  5992. #endif
  5993. }
  5994. #ifdef RLIMIT_AS
  5995. /* Maximum size of the process's virtual memory (address space) in bytes.
  5996. *
  5997. * see the system getrlimit(2) manual for details.
  5998. */
  5999. rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
  6000. #endif
  6001. #ifdef RLIMIT_CORE
  6002. /* Maximum size of the core file.
  6003. *
  6004. * see the system getrlimit(2) manual for details.
  6005. */
  6006. rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
  6007. #endif
  6008. #ifdef RLIMIT_CPU
  6009. /* CPU time limit in seconds.
  6010. *
  6011. * see the system getrlimit(2) manual for details.
  6012. */
  6013. rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
  6014. #endif
  6015. #ifdef RLIMIT_DATA
  6016. /* Maximum size of the process's data segment.
  6017. *
  6018. * see the system getrlimit(2) manual for details.
  6019. */
  6020. rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
  6021. #endif
  6022. #ifdef RLIMIT_FSIZE
  6023. /* Maximum size of files that the process may create.
  6024. *
  6025. * see the system getrlimit(2) manual for details.
  6026. */
  6027. rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
  6028. #endif
  6029. #ifdef RLIMIT_MEMLOCK
  6030. /* Maximum number of bytes of memory that may be locked into RAM.
  6031. *
  6032. * see the system getrlimit(2) manual for details.
  6033. */
  6034. rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
  6035. #endif
  6036. #ifdef RLIMIT_MSGQUEUE
  6037. /* Specifies the limit on the number of bytes that can be allocated
  6038. * for POSIX message queues for the real user ID of the calling process.
  6039. *
  6040. * see the system getrlimit(2) manual for details.
  6041. */
  6042. rb_define_const(rb_mProcess, "RLIMIT_MSGQUEUE", INT2FIX(RLIMIT_MSGQUEUE));
  6043. #endif
  6044. #ifdef RLIMIT_NICE
  6045. /* Specifies a ceiling to which the process's nice value can be raised.
  6046. *
  6047. * see the system getrlimit(2) manual for details.
  6048. */
  6049. rb_define_const(rb_mProcess, "RLIMIT_NICE", INT2FIX(RLIMIT_NICE));
  6050. #endif
  6051. #ifdef RLIMIT_NOFILE
  6052. /* Specifies a value one greater than the maximum file descriptor
  6053. * number that can be opened by this process.
  6054. *
  6055. * see the system getrlimit(2) manual for details.
  6056. */
  6057. rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
  6058. #endif
  6059. #ifdef RLIMIT_NPROC
  6060. /* The maximum number of processes that can be created for the
  6061. * real user ID of the calling process.
  6062. *
  6063. * see the system getrlimit(2) manual for details.
  6064. */
  6065. rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
  6066. #endif
  6067. #ifdef RLIMIT_RSS
  6068. /* Specifies the limit (in pages) of the process's resident set.
  6069. *
  6070. * see the system getrlimit(2) manual for details.
  6071. */
  6072. rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
  6073. #endif
  6074. #ifdef RLIMIT_RTPRIO
  6075. /* Specifies a ceiling on the real-time priority that may be set for this process.
  6076. *
  6077. * see the system getrlimit(2) manual for details.
  6078. */
  6079. rb_define_const(rb_mProcess, "RLIMIT_RTPRIO", INT2FIX(RLIMIT_RTPRIO));
  6080. #endif
  6081. #ifdef RLIMIT_RTTIME
  6082. /* Specifies limit on CPU time this process scheduled under a real-time
  6083. * scheduling policy can consume.
  6084. *
  6085. * see the system getrlimit(2) manual for details.
  6086. */
  6087. rb_define_const(rb_mProcess, "RLIMIT_RTTIME", INT2FIX(RLIMIT_RTTIME));
  6088. #endif
  6089. #ifdef RLIMIT_SBSIZE
  6090. /* Maximum size of the socket buffer.
  6091. */
  6092. rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
  6093. #endif
  6094. #ifdef RLIMIT_SIGPENDING
  6095. /* Specifies a limit on the number of signals that may be queued for
  6096. * the real user ID of the calling process.
  6097. *
  6098. * see the system getrlimit(2) manual for details.
  6099. */
  6100. rb_define_const(rb_mProcess, "RLIMIT_SIGPENDING", INT2FIX(RLIMIT_SIGPENDING));
  6101. #endif
  6102. #ifdef RLIMIT_STACK
  6103. /* Maximum size of the stack, in bytes.
  6104. *
  6105. * see the system getrlimit(2) manual for details.
  6106. */
  6107. rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
  6108. #endif
  6109. #endif
  6110. rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
  6111. rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
  6112. rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
  6113. rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
  6114. rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
  6115. rb_define_module_function(rb_mProcess, "euid=", proc_seteuid_m, 1);
  6116. rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
  6117. rb_define_module_function(rb_mProcess, "egid=", proc_setegid_m, 1);
  6118. rb_define_module_function(rb_mProcess, "initgroups", proc_initgroups, 2);
  6119. rb_define_module_function(rb_mProcess, "groups", proc_getgroups, 0);
  6120. rb_define_module_function(rb_mProcess, "groups=", proc_setgroups, 1);
  6121. rb_define_module_function(rb_mProcess, "maxgroups", proc_getmaxgroups, 0);
  6122. rb_define_module_function(rb_mProcess, "maxgroups=", proc_setmaxgroups, 1);
  6123. rb_define_module_function(rb_mProcess, "daemon", proc_daemon, -1);
  6124. rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
  6125. #if defined(HAVE_TIMES) || defined(_WIN32)
  6126. rb_cProcessTms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", NULL);
  6127. #endif
  6128. SAVED_USER_ID = geteuid();
  6129. SAVED_GROUP_ID = getegid();
  6130. rb_mProcUID = rb_define_module_under(rb_mProcess, "UID");
  6131. rb_mProcGID = rb_define_module_under(rb_mProcess, "GID");
  6132. rb_define_module_function(rb_mProcUID, "rid", proc_getuid, 0);
  6133. rb_define_module_function(rb_mProcGID, "rid", proc_getgid, 0);
  6134. rb_define_module_function(rb_mProcUID, "eid", proc_geteuid, 0);
  6135. rb_define_module_function(rb_mProcGID, "eid", proc_getegid, 0);
  6136. rb_define_module_function(rb_mProcUID, "change_privilege", p_uid_change_privilege, 1);
  6137. rb_define_module_function(rb_mProcGID, "change_privilege", p_gid_change_privilege, 1);
  6138. rb_define_module_function(rb_mProcUID, "grant_privilege", p_uid_grant_privilege, 1);
  6139. rb_define_module_function(rb_mProcGID, "grant_privilege", p_gid_grant_privilege, 1);
  6140. rb_define_alias(rb_singleton_class(rb_mProcUID), "eid=", "grant_privilege");
  6141. rb_define_alias(rb_singleton_class(rb_mProcGID), "eid=", "grant_privilege");
  6142. rb_define_module_function(rb_mProcUID, "re_exchange", p_uid_exchange, 0);
  6143. rb_define_module_function(rb_mProcGID, "re_exchange", p_gid_exchange, 0);
  6144. rb_define_module_function(rb_mProcUID, "re_exchangeable?", p_uid_exchangeable, 0);
  6145. rb_define_module_function(rb_mProcGID, "re_exchangeable?", p_gid_exchangeable, 0);
  6146. rb_define_module_function(rb_mProcUID, "sid_available?", p_uid_have_saved_id, 0);
  6147. rb_define_module_function(rb_mProcGID, "sid_available?", p_gid_have_saved_id, 0);
  6148. rb_define_module_function(rb_mProcUID, "switch", p_uid_switch, 0);
  6149. rb_define_module_function(rb_mProcGID, "switch", p_gid_switch, 0);
  6150. #ifdef p_uid_from_name
  6151. rb_define_module_function(rb_mProcUID, "from_name", p_uid_from_name, 1);
  6152. #endif
  6153. #ifdef p_gid_from_name
  6154. rb_define_module_function(rb_mProcGID, "from_name", p_gid_from_name, 1);
  6155. #endif
  6156. rb_mProcID_Syscall = rb_define_module_under(rb_mProcess, "Sys");
  6157. rb_define_module_function(rb_mProcID_Syscall, "getuid", proc_getuid, 0);
  6158. rb_define_module_function(rb_mProcID_Syscall, "geteuid", proc_geteuid, 0);
  6159. rb_define_module_function(rb_mProcID_Syscall, "getgid", proc_getgid, 0);
  6160. rb_define_module_function(rb_mProcID_Syscall, "getegid", proc_getegid, 0);
  6161. rb_define_module_function(rb_mProcID_Syscall, "setuid", p_sys_setuid, 1);
  6162. rb_define_module_function(rb_mProcID_Syscall, "setgid", p_sys_setgid, 1);
  6163. rb_define_module_function(rb_mProcID_Syscall, "setruid", p_sys_setruid, 1);
  6164. rb_define_module_function(rb_mProcID_Syscall, "setrgid", p_sys_setrgid, 1);
  6165. rb_define_module_function(rb_mProcID_Syscall, "seteuid", p_sys_seteuid, 1);
  6166. rb_define_module_function(rb_mProcID_Syscall, "setegid", p_sys_setegid, 1);
  6167. rb_define_module_function(rb_mProcID_Syscall, "setreuid", p_sys_setreuid, 2);
  6168. rb_define_module_function(rb_mProcID_Syscall, "setregid", p_sys_setregid, 2);
  6169. rb_define_module_function(rb_mProcID_Syscall, "setresuid", p_sys_setresuid, 3);
  6170. rb_define_module_function(rb_mProcID_Syscall, "setresgid", p_sys_setresgid, 3);
  6171. rb_define_module_function(rb_mProcID_Syscall, "issetugid", p_sys_issetugid, 0);
  6172. }