process.c
DEFINITIONS
This source file includes following functions.
- get_pid
- get_ppid
- last_status_set
- pst_to_i
- pst_to_s
- pst_equal
- pst_bitand
- pst_rshift
- pst_wifstopped
- pst_wstopsig
- pst_wifsignaled
- pst_wtermsig
- pst_wifexited
- pst_wexitstatus
- pst_wcoredump
- rb_waitpid
- wait_each
- waitall_each
- proc_wait
- proc_wait2
- proc_waitall
- security
- proc_exec_v
- proc_exec_n
- rb_proc_exec
- proc_spawn_v
- proc_spawn_n
- proc_spawn
- rb_f_exec
- rb_f_fork
- rb_f_exit_bang
- rb_syswait
- rb_f_system
- rb_f_sleep
- proc_getpgrp
- proc_setpgrp
- proc_getpgid
- proc_setpgid
- proc_setsid
- proc_getpriority
- proc_setpriority
- proc_getuid
- proc_setuid
- proc_getgid
- proc_setgid
- proc_geteuid
- proc_seteuid
- proc_getegid
- proc_setegid
- rb_proc_times
- Init_process
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include "ruby.h"
16 #include "rubysig.h"
17 #include <stdio.h>
18 #include <errno.h>
19 #include <signal.h>
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23
24 #include <time.h>
25 #ifndef NT
26 #ifdef HAVE_SYS_TIME_H
27 # include <sys/time.h>
28 #else
29 struct timeval {
30 long tv_sec;
31 long tv_usec;
32 };
33 #endif
34 #endif
35 #include <ctype.h>
36
37 struct timeval rb_time_interval _((VALUE));
38
39 #ifdef HAVE_SYS_WAIT_H
40 # include <sys/wait.h>
41 #endif
42 #ifdef HAVE_GETPRIORITY
43 # include <sys/resource.h>
44 #endif
45 #include "st.h"
46
47 #ifdef __EMX__
48 #undef HAVE_GETPGRP
49 #endif
50
51 #ifdef HAVE_SYS_TIMES_H
52 #include <sys/times.h>
53 #endif
54
55 #if defined(HAVE_TIMES) || defined(NT)
56 static VALUE S_Tms;
57 #endif
58
59 #ifndef WIFEXITED
60 #define WIFEXITED(w) (((w) & 0xff) == 0)
61 #endif
62 #ifndef WIFSIGNALED
63 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
64 #endif
65 #ifndef WIFSTOPPED
66 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
67 #endif
68 #ifndef WEXITSTATUS
69 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
70 #endif
71 #ifndef WTERMSIG
72 #define WTERMSIG(w) ((w) & 0x7f)
73 #endif
74 #ifndef WSTOPSIG
75 #define WSTOPSIG WEXITSTATUS
76 #endif
77
78 static VALUE
79 get_pid()
80 {
81 return INT2FIX(getpid());
82 }
83
84 static VALUE
85 get_ppid()
86 {
87 #ifdef NT
88 return INT2FIX(0);
89 #else
90 return INT2FIX(getppid());
91 #endif
92 }
93
94 static VALUE rb_cProcStatus;
95 VALUE rb_last_status = Qnil;
96
97 static void
98 last_status_set(status)
99 int status;
100 {
101 rb_last_status = rb_obj_alloc(rb_cProcStatus);
102 rb_iv_set(rb_last_status, "status", INT2FIX(status));
103 }
104
105 static VALUE
106 pst_to_i(st)
107 VALUE st;
108 {
109 return rb_iv_get(st, "status");
110 }
111
112 static VALUE
113 pst_to_s(st)
114 VALUE st;
115 {
116 return rb_fix2str(pst_to_i(st), 10);
117 }
118
119 static VALUE
120 pst_equal(st1, st2)
121 VALUE st1, st2;
122 {
123 if (st1 == st2) return Qtrue;
124 return rb_equal(pst_to_i(st1), st2);
125 }
126
127 static VALUE
128 pst_bitand(st1, st2)
129 VALUE st1, st2;
130 {
131 int status = NUM2INT(st1) & NUM2INT(st2);
132
133 return INT2NUM(status);
134 }
135
136 static VALUE
137 pst_rshift(st1, st2)
138 VALUE st1, st2;
139 {
140 int status = NUM2INT(st1) >> NUM2INT(st2);
141
142 return INT2NUM(status);
143 }
144
145 static VALUE
146 pst_wifstopped(st)
147 VALUE st;
148 {
149 int status = NUM2INT(st);
150
151 if (WIFSTOPPED(status))
152 return Qtrue;
153 else
154 return Qfalse;
155 }
156
157 static VALUE
158 pst_wstopsig(st)
159 VALUE st;
160 {
161 int status = NUM2INT(st);
162
163 if (WIFSTOPPED(status))
164 return INT2NUM(WSTOPSIG(status));
165 return Qnil;
166 }
167
168 static VALUE
169 pst_wifsignaled(st)
170 VALUE st;
171 {
172 int status = NUM2INT(st);
173
174 if (WIFSIGNALED(status))
175 return Qtrue;
176 else
177 return Qfalse;
178 }
179
180 static VALUE
181 pst_wtermsig(st)
182 VALUE st;
183 {
184 int status = NUM2INT(st);
185
186 if (WIFSIGNALED(status))
187 return INT2NUM(WTERMSIG(status));
188 return Qnil;
189 }
190
191 static VALUE
192 pst_wifexited(st)
193 VALUE st;
194 {
195 int status = NUM2INT(st);
196
197 if (WIFEXITED(status))
198 return Qtrue;
199 else
200 return Qfalse;
201 }
202
203 static VALUE
204 pst_wexitstatus(st)
205 VALUE st;
206 {
207 int status = NUM2INT(st);
208
209 if (WIFEXITED(status))
210 return INT2NUM(WEXITSTATUS(status));
211 return Qnil;
212 }
213
214 static VALUE
215 pst_wcoredump(st)
216 VALUE st;
217 {
218 #ifdef WCOREDUMP
219 int status = NUM2INT(st);
220
221 if (WCOREDUMP(status))
222 return Qtrue;
223 else
224 return Qfalse;
225 #else
226 return Qfalse;
227 #endif
228 }
229
230 #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
231 #define NO_WAITPID
232 static st_table *pid_tbl;
233 #endif
234
235 int
236 rb_waitpid(pid, st, flags)
237 int pid;
238 int *st;
239 int flags;
240 {
241 int result;
242 #ifndef NO_WAITPID
243 int oflags = flags;
244 if (!rb_thread_alone()) {
245 flags |= WNOHANG;
246 }
247
248 retry:
249 TRAP_BEG;
250 #ifdef HAVE_WAITPID
251 result = waitpid(pid, st, flags);
252 #else
253 result = wait4(pid, st, flags, NULL);
254 #endif
255 TRAP_END;
256 if (result < 0) {
257 if (errno == EINTR) {
258 rb_thread_polling();
259 goto retry;
260 }
261 return -1;
262 }
263 if (result == 0) {
264 if (oflags & WNOHANG) return 0;
265 rb_thread_polling();
266 if (rb_thread_alone()) flags = oflags;
267 goto retry;
268 }
269 #else
270 if (pid_tbl && st_lookup(pid_tbl, pid, st)) {
271 last_status_set(*st);
272 st_delete(pid_tbl, &pid, NULL);
273 return pid;
274 }
275
276 if (flags) {
277 rb_raise(rb_eArgError, "can't do waitpid with flags");
278 }
279
280 for (;;) {
281 TRAP_BEG;
282 result = wait(st);
283 TRAP_END;
284 if (result < 0) {
285 if (errno == EINTR) {
286 rb_thread_schedule();
287 continue;
288 }
289 return -1;
290 }
291 if (result == pid) {
292 break;
293 }
294 if (!pid_tbl)
295 pid_tbl = st_init_numtable();
296 st_insert(pid_tbl, pid, st);
297 if (!rb_thread_alone()) rb_thread_schedule();
298 }
299 #endif
300 last_status_set(*st);
301 return result;
302 }
303
304 #ifdef NO_WAITPID
305 struct wait_data {
306 int pid;
307 int status;
308 };
309
310 static int
311 wait_each(key, value, data)
312 int key, value;
313 struct wait_data *data;
314 {
315 if (data->status != -1) return ST_STOP;
316
317 data->pid = key;
318 data->status = value;
319 return ST_DELETE;
320 }
321
322 static int
323 waitall_each(key, value, data)
324 int key, value;
325 VALUE data;
326 {
327 last_status_set(value);
328 rb_ary_push(data, rb_assoc_new(INT2NUM(key), rb_last_status));
329 return ST_DELETE;
330 }
331 #endif
332
333 static VALUE
334 proc_wait(argc, argv)
335 int argc;
336 VALUE *argv;
337 {
338 VALUE vpid, vflags;
339 int pid, flags, status;
340
341 flags = 0;
342 rb_scan_args(argc, argv, "02", &vpid, &vflags);
343 if (argc == 0) {
344 pid = -1;
345 }
346 else {
347 pid = NUM2INT(vpid);
348 if (argc == 2 && !NIL_P(vflags)) {
349 flags = NUM2UINT(vflags);
350 }
351 }
352 if ((pid = rb_waitpid(pid, &status, flags)) < 0)
353 rb_sys_fail(0);
354 if (pid == 0) {
355 rb_last_status = Qnil;
356 return Qnil;
357 }
358 return INT2FIX(pid);
359 }
360
361 static VALUE
362 proc_wait2(argc, argv)
363 int argc;
364 VALUE *argv;
365 {
366 VALUE pid = proc_wait(argc, argv);
367 if (NIL_P(pid)) return Qnil;
368 return rb_assoc_new(pid, rb_last_status);
369 }
370
371 static VALUE
372 proc_waitall()
373 {
374 VALUE result;
375 int pid, status;
376
377 result = rb_ary_new();
378 #ifdef NO_WAITPID
379 if (pid_tbl) {
380 st_foreach(pid_tbl, waitall_each, result);
381 }
382
383 for (pid = -1;;) {
384 pid = wait(&status);
385 if (pid == -1) {
386 if (errno == ECHILD)
387 break;
388 if (errno == EINTR) {
389 rb_thread_schedule();
390 continue;
391 }
392 rb_sys_fail(0);
393 }
394 last_status_set(status);
395 rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status));
396 }
397 #else
398 rb_last_status = Qnil;
399 for (pid = -1;;) {
400 pid = rb_waitpid(-1, &status, 0);
401 if (pid == -1) {
402 if (errno == ECHILD)
403 break;
404 rb_sys_fail(0);
405 }
406 rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status));
407 }
408 #endif
409 return result;
410 }
411
412 #ifndef HAVE_STRING_H
413 char *strtok();
414 #endif
415
416 #ifdef HAVE_SETITIMER
417 #define before_exec() rb_thread_stop_timer()
418 #define after_exec() rb_thread_start_timer()
419 #else
420 #define before_exec()
421 #define after_exec()
422 #endif
423
424 extern char *dln_find_exe();
425
426 static void
427 security(str)
428 char *str;
429 {
430 if (rb_env_path_tainted()) {
431 if (rb_safe_level() > 0) {
432 rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
433 }
434 }
435 }
436
437 static int
438 proc_exec_v(argv, prog)
439 char **argv;
440 char *prog;
441 {
442 if (prog) {
443 security(prog);
444 }
445 else {
446 security(argv[0]);
447 prog = dln_find_exe(argv[0], 0);
448 if (!prog) {
449 errno = ENOENT;
450 return -1;
451 }
452 }
453 #if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__) || defined(__EMX__) || defined(OS2)
454 {
455 #if defined(__human68k__)
456 #define COMMAND "command.x"
457 #endif
458 #if defined(__EMX__) || defined(OS2)
459 #define COMMAND "cmd.exe"
460 #endif
461 #if (defined(MSDOS) && !defined(DJGPP))
462 #define COMMAND "command.com"
463 #endif
464 char *extension;
465
466 if ((extension = strrchr(prog, '.')) != NULL && strcasecmp(extension, ".bat") == 0) {
467 char **new_argv;
468 char *p;
469 int n;
470
471 for (n = 0; argv[n]; n++)
472 ;
473 new_argv = ALLOCA_N(char*, n + 2);
474 for (; n > 0; n--)
475 new_argv[n + 1] = argv[n];
476 new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
477 for (p = new_argv[1]; *p != '\0'; p++)
478 if (*p == '/')
479 *p = '\\';
480 new_argv[0] = COMMAND;
481 argv = new_argv;
482 prog = dln_find_exe(argv[0], 0);
483 if (!prog) {
484 errno = ENOENT;
485 return -1;
486 }
487 }
488 }
489 #endif
490 before_exec();
491 execv(prog, argv);
492 after_exec();
493 return -1;
494 }
495
496 static int
497 proc_exec_n(argc, argv, progv)
498 int argc;
499 VALUE *argv;
500 VALUE progv;
501 {
502 char *prog = 0;
503 char **args;
504 int i;
505
506 if (progv) {
507 prog = RSTRING(progv)->ptr;
508 }
509 args = ALLOCA_N(char*, argc+1);
510 for (i=0; i<argc; i++) {
511 SafeStringValue(argv[i]);
512 args[i] = RSTRING(argv[i])->ptr;
513 }
514 args[i] = 0;
515 if (args[0]) {
516 return proc_exec_v(args, prog);
517 }
518 return -1;
519 }
520
521 int
522 rb_proc_exec(str)
523 const char *str;
524 {
525 const char *s = str;
526 char *ss, *t;
527 char **argv, **a;
528
529 while (*str && ISSPACE(*str))
530 str++;
531
532 for (s=str; *s; s++) {
533 if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
534 #if defined(MSDOS)
535 int status;
536 before_exec();
537 status = system(str);
538 after_exec();
539 if (status != -1)
540 exit(status);
541 #else
542 #if defined(__human68k__) || defined(__CYGWIN32__) || defined(__EMX__)
543 char *shell = dln_find_exe("sh", 0);
544 int status = -1;
545 before_exec();
546 if (shell)
547 execl(shell, "sh", "-c", str, (char *) NULL);
548 else
549 status = system(str);
550 after_exec();
551 if (status != -1)
552 exit(status);
553 #else
554 before_exec();
555 execl("/bin/sh", "sh", "-c", str, (char *)NULL);
556 after_exec();
557 #endif
558 #endif
559 return -1;
560 }
561 }
562 a = argv = ALLOCA_N(char*, (s-str)/2+2);
563 ss = ALLOCA_N(char, s-str+1);
564 strcpy(ss, str);
565 if (*a++ = strtok(ss, " \t")) {
566 while (t = strtok(NULL, " \t")) {
567 *a++ = t;
568 }
569 *a = NULL;
570 }
571 if (argv[0]) {
572 return proc_exec_v(argv, 0);
573 }
574 errno = ENOENT;
575 return -1;
576 }
577
578 #if defined(__human68k__)
579 static int
580 proc_spawn_v(argv, prog)
581 char **argv;
582 char *prog;
583 {
584 char *extension;
585 int status;
586
587 if (prog) {
588 security(prog);
589 }
590 else {
591 security(argv[0]);
592 prog = dln_find_exe(argv[0], 0);
593 if (!prog)
594 return -1;
595 }
596
597 if ((extension = strrchr(prog, '.')) != NULL && strcasecmp(extension, ".bat") == 0) {
598 char **new_argv;
599 char *p;
600 int n;
601
602 for (n = 0; argv[n]; n++)
603 ;
604 new_argv = ALLOCA_N(char*, n + 2);
605 for (; n > 0; n--)
606 new_argv[n + 1] = argv[n];
607 new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
608 for (p = new_argv[1]; *p != '\0'; p++)
609 if (*p == '/')
610 *p = '\\';
611 new_argv[0] = COMMAND;
612 argv = new_argv;
613 prog = dln_find_exe(argv[0], 0);
614 if (!prog) {
615 errno = ENOENT;
616 return -1;
617 }
618 }
619 before_exec();
620 status = spawnv(P_WAIT, prog, argv);
621 after_exec();
622 return status;
623 }
624
625 static int
626 proc_spawn_n(argc, argv, prog)
627 int argc;
628 VALUE *argv;
629 VALUE prog;
630 {
631 char **args;
632 int i;
633
634 args = ALLOCA_N(char*, argc + 1);
635 for (i = 0; i < argc; i++) {
636 SafeStr(argv[i]);
637 args[i] = RSTRING(argv[i])->ptr;
638 }
639 SafeStringValue(prog);
640 args[i] = (char*) 0;
641 if (args[0])
642 return proc_spawn_v(args, RSTRING(prog)->ptr);
643 return -1;
644 }
645
646 static int
647 proc_spawn(sv)
648 VALUE sv;
649 {
650 char *str;
651 char *s, *t;
652 char **argv, **a;
653 int status;
654
655 SafeStringValue(sv);
656 str = s = RSTRING(sv)->ptr;
657 for (s = str; *s; s++) {
658 if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
659 char *shell = dln_find_exe("sh", 0);
660 before_exec();
661 status = shell?spawnl(P_WAIT,shell,"sh","-c",str,(char*)NULL):system(str);
662 after_exec();
663 return status;
664 }
665 }
666 a = argv = ALLOCA_N(char*, (s - str) / 2 + 2);
667 s = ALLOCA_N(char, s - str + 1);
668 strcpy(s, str);
669 if (*a++ = strtok(s, " \t")) {
670 while (t = strtok(NULL, " \t"))
671 *a++ = t;
672 *a = NULL;
673 }
674 return argv[0] ? proc_spawn_v(argv, 0) : -1;
675 }
676 #endif
677
678 VALUE
679 rb_f_exec(argc, argv)
680 int argc;
681 VALUE *argv;
682 {
683 VALUE prog = 0;
684
685 if (argc == 0) {
686 rb_raise(rb_eArgError, "wrong number of arguments");
687 }
688
689 if (TYPE(argv[0]) == T_ARRAY) {
690 if (RARRAY(argv[0])->len != 2) {
691 rb_raise(rb_eArgError, "wrong first argument");
692 }
693 prog = RARRAY(argv[0])->ptr[0];
694 argv[0] = RARRAY(argv[0])->ptr[1];
695 }
696 if (prog) {
697 SafeStringValue(prog);
698 }
699 if (argc == 1 && prog == 0) {
700 VALUE cmd = argv[0];
701
702 SafeStringValue(cmd);
703 rb_proc_exec(RSTRING(cmd)->ptr);
704 }
705 else {
706 proc_exec_n(argc, argv, prog);
707 }
708 rb_sys_fail(RSTRING(argv[0])->ptr);
709 return Qnil;
710 }
711
712 static VALUE
713 rb_f_fork(obj)
714 VALUE obj;
715 {
716 #if !defined(__human68k__) && !defined(NT) && !defined(__MACOS__) && !defined(__EMX__) && !defined(__VMS)
717 int pid;
718
719 rb_secure(2);
720 switch (pid = fork()) {
721 case 0:
722 #ifdef linux
723 after_exec();
724 #endif
725 rb_thread_atfork();
726 if (rb_block_given_p()) {
727 int status;
728
729 rb_protect(rb_yield, Qundef, &status);
730 ruby_stop(status);
731 }
732 return Qnil;
733
734 case -1:
735 rb_sys_fail("fork(2)");
736 return Qnil;
737
738 default:
739 return INT2FIX(pid);
740 }
741 #else
742 rb_notimplement();
743 #endif
744 }
745
746 static VALUE
747 rb_f_exit_bang(argc, argv, obj)
748 int argc;
749 VALUE *argv;
750 VALUE obj;
751 {
752 VALUE status;
753 int istatus;
754
755 rb_secure(4);
756 if (rb_scan_args(argc, argv, "01", &status) == 1) {
757 istatus = NUM2INT(status);
758 }
759 else {
760 istatus = -1;
761 }
762 _exit(istatus);
763
764 return Qnil;
765 }
766
767 void
768 rb_syswait(pid)
769 int pid;
770 {
771 static int overriding;
772 RETSIGTYPE (*hfunc)_((int)), (*qfunc)_((int)), (*ifunc)_((int));
773 int status;
774 int i, hooked = Qfalse;
775
776 if (!overriding) {
777 #ifdef SIGHUP
778 hfunc = signal(SIGHUP, SIG_IGN);
779 #endif
780 #ifdef SIGQUIT
781 qfunc = signal(SIGQUIT, SIG_IGN);
782 #endif
783 ifunc = signal(SIGINT, SIG_IGN);
784 overriding = Qtrue;
785 hooked = Qtrue;
786 }
787
788 do {
789 i = rb_waitpid(pid, &status, 0);
790 } while (i == -1 && errno == EINTR);
791
792 if (hooked) {
793 #ifdef SIGHUP
794 signal(SIGHUP, hfunc);
795 #endif
796 #ifdef SIGQUIT
797 signal(SIGQUIT, qfunc);
798 #endif
799 signal(SIGINT, ifunc);
800 overriding = Qfalse;
801 }
802 }
803
804 static VALUE
805 rb_f_system(argc, argv)
806 int argc;
807 VALUE *argv;
808 {
809 #if defined(NT) || defined(__EMX__)
810 VALUE cmd;
811 int status;
812
813 fflush(stdout);
814 fflush(stderr);
815 if (argc == 0) {
816 rb_last_status = Qnil;
817 rb_raise(rb_eArgError, "wrong number of arguments");
818 }
819
820 if (TYPE(argv[0]) == T_ARRAY) {
821 if (RARRAY(argv[0])->len != 2) {
822 rb_raise(rb_eArgError, "wrong first argument");
823 }
824 argv[0] = RARRAY(argv[0])->ptr[0];
825 }
826 cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
827
828 SafeStringValue(cmd);
829 status = do_spawn(RSTRING(cmd)->ptr);
830 last_status_set(status);
831
832 if (status == 0) return Qtrue;
833 return Qfalse;
834 #elif defined(DJGPP)
835 VALUE cmd;
836 int status;
837
838 if (argc == 0) {
839 rb_last_status = Qnil;
840 rb_raise(rb_eArgError, "wrong number of arguments");
841 }
842
843 if (TYPE(argv[0]) == T_ARRAY) {
844 if (RARRAY(argv[0])->len != 2) {
845 rb_raise(rb_eArgError, "wrong first argument");
846 }
847 argv[0] = RARRAY(argv[0])->ptr[0];
848 }
849 cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
850
851 SafeStringValue(cmd);
852 status = system(RSTRING(cmd)->ptr);
853 last_status_set((status & 0xff) << 8);
854
855 if (status == 0) return Qtrue;
856 return Qfalse;
857 #elif defined(__human68k__)
858 VALUE prog = 0;
859 int status;
860
861 fflush(stdin);
862 fflush(stdout);
863 fflush(stderr);
864 if (argc == 0) {
865 rb_last_status = Qnil;
866 rb_raise(rb_eArgError, "wrong number of arguments");
867 }
868
869 if (TYPE(argv[0]) == T_ARRAY) {
870 if (RARRAY(argv[0])->len != 2) {
871 rb_raise(rb_eArgError, "wrong first argument");
872 }
873 prog = RARRAY(argv[0])->ptr[0];
874 argv[0] = RARRAY(argv[0])->ptr[1];
875 }
876
877 if (argc == 1 && prog == 0) {
878 status = proc_spawn(argv[0]);
879 }
880 else {
881 status = proc_spawn_n(argc, argv, prog);
882 }
883 last_status_set(status == -1 ? 127 : status);
884 return status == 0 ? Qtrue : Qfalse;
885 #elif defined(__VMS)
886 VALUE cmd;
887 int status;
888
889 if (argc == 0) {
890 rb_last_status = Qnil;
891 rb_raise(rb_eArgError, "wrong number of arguments");
892 }
893
894 if (TYPE(argv[0]) == T_ARRAY) {
895 if (RARRAY(argv[0])->len != 2) {
896 rb_raise(rb_eArgError, "wrong first argument");
897 }
898 argv[0] = RARRAY(argv[0])->ptr[0];
899 }
900 cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
901
902 SafeStringValue(cmd);
903 status = system(RSTRING(cmd)->ptr);
904 last_status_set((status & 0xff) << 8);
905
906 if (status == 0) return Qtrue;
907 return Qfalse;
908 #else
909 volatile VALUE prog = 0;
910 int pid;
911 int i;
912
913 fflush(stdout);
914 fflush(stderr);
915 if (argc == 0) {
916 rb_last_status = Qnil;
917 rb_raise(rb_eArgError, "wrong number of arguments");
918 }
919
920 if (TYPE(argv[0]) == T_ARRAY) {
921 if (RARRAY(argv[0])->len != 2) {
922 rb_raise(rb_eArgError, "wrong first argument");
923 }
924 prog = RARRAY(argv[0])->ptr[0];
925 argv[0] = RARRAY(argv[0])->ptr[1];
926 }
927
928 if (prog) {
929 SafeStringValue(prog);
930 }
931 for (i = 0; i < argc; i++) {
932 SafeStringValue(argv[i]);
933 }
934 retry:
935 switch (pid = fork()) {
936 case 0:
937 if (argc == 1 && prog == 0) {
938 rb_proc_exec(RSTRING(argv[0])->ptr);
939 }
940 else {
941 proc_exec_n(argc, argv, prog);
942 }
943 _exit(127);
944 break;
945
946 case -1:
947 if (errno == EAGAIN) {
948 rb_thread_sleep(1);
949 goto retry;
950 }
951 rb_sys_fail(0);
952 break;
953
954 default:
955 rb_syswait(pid);
956 }
957
958 if (NUM2INT(rb_last_status) == 0)
959 return Qtrue;
960 return Qfalse;
961 #endif
962 }
963
964 static VALUE
965 rb_f_sleep(argc, argv)
966 int argc;
967 VALUE *argv;
968 {
969 int beg, end;
970
971 beg = time(0);
972 if (argc == 0) {
973 rb_thread_sleep_forever();
974 }
975 else if (argc == 1) {
976 rb_thread_wait_for(rb_time_interval(argv[0]));
977 }
978 else {
979 rb_raise(rb_eArgError, "wrong number of arguments");
980 }
981
982 end = time(0) - beg;
983
984 return INT2FIX(end);
985 }
986
987 static VALUE
988 proc_getpgrp()
989 {
990 int pgrp;
991
992 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
993 pgrp = getpgrp();
994 if (pgrp < 0) rb_sys_fail(0);
995 return INT2FIX(pgrp);
996 #else
997 # ifdef HAVE_GETPGID
998 pgrp = getpgid(0);
999 if (pgrp < 0) rb_sys_fail(0);
1000 return INT2FIX(pgrp);
1001 # else
1002 rb_notimplement();
1003 # endif
1004 #endif
1005 }
1006
1007 static VALUE
1008 proc_setpgrp()
1009 {
1010
1011
1012
1013
1014 #ifdef HAVE_SETPGID
1015 if (setpgid(0,0) < 0) rb_sys_fail(0);
1016 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
1017 if (setpgrp() < 0) rb_sys_fail(0);
1018 #else
1019 rb_notimplement();
1020 #endif
1021 return INT2FIX(0);
1022 }
1023
1024 static VALUE
1025 proc_getpgid(obj, pid)
1026 VALUE obj, pid;
1027 {
1028 #if defined(HAVE_GETPGID) && !defined(__CHECKER__)
1029 int i = getpgid(NUM2INT(pid));
1030
1031 if (i < 0) rb_sys_fail(0);
1032 return INT2NUM(i);
1033 #else
1034 rb_notimplement();
1035 #endif
1036 }
1037
1038 static VALUE
1039 proc_setpgid(obj, pid, pgrp)
1040 VALUE obj, pid, pgrp;
1041 {
1042 #ifdef HAVE_SETPGID
1043 int ipid, ipgrp;
1044
1045 rb_secure(2);
1046 ipid = NUM2INT(pid);
1047 ipgrp = NUM2INT(pgrp);
1048
1049 if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
1050 return INT2FIX(0);
1051 #else
1052 rb_notimplement();
1053 #endif
1054 }
1055
1056 static VALUE
1057 proc_setsid()
1058 {
1059 #if defined(HAVE_SETSID)
1060 int pid;
1061
1062 rb_secure(2);
1063 pid = setsid();
1064 if (pid < 0) rb_sys_fail(0);
1065 return INT2FIX(pid);
1066 #elif defined(HAVE_SETPGRP) && defined(TIOCNOTTY)
1067 pid_t pid;
1068 int ret;
1069
1070 rb_secure(2);
1071 pid = getpid();
1072 #if defined(SETPGRP_VOID)
1073 ret = setpgrp();
1074
1075
1076
1077 #else
1078 ret = setpgrp(0, pid);
1079 #endif
1080 if (ret == -1) rb_sys_fail(0);
1081
1082 if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
1083 ioctl(fd, TIOCNOTTY, NULL);
1084 close(fd);
1085 }
1086 return INT2FIX(pid);
1087 #else
1088 rb_notimplement();
1089 #endif
1090 }
1091
1092 static VALUE
1093 proc_getpriority(obj, which, who)
1094 VALUE obj, which, who;
1095 {
1096 #ifdef HAVE_GETPRIORITY
1097 int prio, iwhich, iwho;
1098
1099 iwhich = NUM2INT(which);
1100 iwho = NUM2INT(who);
1101
1102 errno = 0;
1103 prio = getpriority(iwhich, iwho);
1104 if (errno) rb_sys_fail(0);
1105 return INT2FIX(prio);
1106 #else
1107 rb_notimplement();
1108 #endif
1109 }
1110
1111 static VALUE
1112 proc_setpriority(obj, which, who, prio)
1113 VALUE obj, which, who, prio;
1114 {
1115 #ifdef HAVE_GETPRIORITY
1116 int iwhich, iwho, iprio;
1117
1118 rb_secure(2);
1119 iwhich = NUM2INT(which);
1120 iwho = NUM2INT(who);
1121 iprio = NUM2INT(prio);
1122
1123 if (setpriority(iwhich, iwho, iprio) < 0)
1124 rb_sys_fail(0);
1125 return INT2FIX(0);
1126 #else
1127 rb_notimplement();
1128 #endif
1129 }
1130
1131 static VALUE
1132 proc_getuid(obj)
1133 VALUE obj;
1134 {
1135 int uid = getuid();
1136 return INT2FIX(uid);
1137 }
1138
1139 static VALUE
1140 proc_setuid(obj, id)
1141 VALUE obj, id;
1142 {
1143 int uid = NUM2INT(id);
1144
1145 #if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
1146 if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
1147 #elif defined HAVE_SETREUID
1148 if (setreuid(uid, -1) < 0) rb_sys_fail(0);
1149 #elif defined HAVE_SETRUID
1150 if (setruid(uid) < 0) rb_sys_fail(0);
1151 #else
1152 {
1153 if (geteuid() == uid) {
1154 if (setuid(uid) < 0) rb_sys_fail(0);
1155 }
1156 else {
1157 rb_notimplement();
1158 }
1159 }
1160 #endif
1161 return INT2FIX(uid);
1162 }
1163
1164 static VALUE
1165 proc_getgid(obj)
1166 VALUE obj;
1167 {
1168 int gid = getgid();
1169 return INT2FIX(gid);
1170 }
1171
1172 static VALUE
1173 proc_setgid(obj, id)
1174 VALUE obj, id;
1175 {
1176 int gid = NUM2INT(id);
1177
1178 #if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
1179 if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
1180 #elif defined HAVE_SETREGID
1181 if (setregid(gid, -1) < 0) rb_sys_fail(0);
1182 #elif defined HAS_SETRGID
1183 if (setrgid((GIDTYPE)gid) < 0) rb_sys_fail(0);
1184 #else
1185 {
1186 if (getegid() == gid) {
1187 if (setgid(gid) < 0) rb_sys_fail(0);
1188 }
1189 else {
1190 rb_notimplement();
1191 }
1192 }
1193 #endif
1194 return INT2FIX(gid);
1195 }
1196
1197 static VALUE
1198 proc_geteuid(obj)
1199 VALUE obj;
1200 {
1201 int euid = geteuid();
1202 return INT2FIX(euid);
1203 }
1204
1205 static VALUE
1206 proc_seteuid(obj, euid)
1207 VALUE obj, euid;
1208 {
1209 #if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
1210 if (setresuid(-1, NUM2INT(euid), -1) < 0) rb_sys_fail(0);
1211 #elif defined HAVE_SETREUID
1212 if (setreuid(-1, NUM2INT(euid)) < 0) rb_sys_fail(0);
1213 #elif defined HAVE_SETEUID
1214 if (seteuid(NUM2INT(euid)) < 0) rb_sys_fail(0);
1215 #else
1216 euid = NUM2INT(euid);
1217 if (euid == getuid()) {
1218 if (setuid(euid) < 0) rb_sys_fail(0);
1219 }
1220 else {
1221 rb_notimplement();
1222 }
1223 #endif
1224 return euid;
1225 }
1226
1227 static VALUE
1228 proc_getegid(obj)
1229 VALUE obj;
1230 {
1231 int egid = getegid();
1232
1233 return INT2FIX(egid);
1234 }
1235
1236 static VALUE
1237 proc_setegid(obj, egid)
1238 VALUE obj, egid;
1239 {
1240 rb_secure(2);
1241 #if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
1242 if (setresgid(-1, NUM2INT(egid), -1) < 0) rb_sys_fail(0);
1243 #elif defined HAVE_SETREGID
1244 if (setregid(-1, NUM2INT(egid)) < 0) rb_sys_fail(0);
1245 #elif defined HAVE_SETEGID
1246 if (setegid(NUM2INT(egid)) < 0) rb_sys_fail(0);
1247 #else
1248 egid = NUM2INT(egid);
1249 if (egid == getgid()) {
1250 if (setgid(egid) < 0) rb_sys_fail(0);
1251 }
1252 else {
1253 rb_notimplement();
1254 }
1255 #endif
1256 return egid;
1257 }
1258
1259 VALUE
1260 rb_proc_times(obj)
1261 VALUE obj;
1262 {
1263 #if defined(HAVE_TIMES) && !defined(__CHECKER__)
1264 #ifndef HZ
1265 # ifdef CLK_TCK
1266 # define HZ CLK_TCK
1267 # else
1268 # define HZ 60
1269 # endif
1270 #endif
1271 struct tms buf;
1272
1273 times(&buf);
1274 return rb_struct_new(S_Tms,
1275 rb_float_new((double)buf.tms_utime / HZ),
1276 rb_float_new((double)buf.tms_stime / HZ),
1277 rb_float_new((double)buf.tms_cutime / HZ),
1278 rb_float_new((double)buf.tms_cstime / HZ));
1279 #else
1280 rb_notimplement();
1281 #endif
1282 }
1283
1284 VALUE rb_mProcess;
1285
1286 void
1287 Init_process()
1288 {
1289 rb_define_virtual_variable("$$", get_pid, 0);
1290 rb_define_readonly_variable("$?", &rb_last_status);
1291 rb_define_global_function("exec", rb_f_exec, -1);
1292 rb_define_global_function("fork", rb_f_fork, 0);
1293 rb_define_global_function("exit!", rb_f_exit_bang, -1);
1294 rb_define_global_function("system", rb_f_system, -1);
1295 rb_define_global_function("sleep", rb_f_sleep, -1);
1296
1297 rb_mProcess = rb_define_module("Process");
1298
1299 #if !defined(NT) && !defined(DJGPP)
1300 #ifdef WNOHANG
1301 rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
1302 #else
1303 rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
1304 #endif
1305 #ifdef WUNTRACED
1306 rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
1307 #else
1308 rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
1309 #endif
1310 #endif
1311
1312 rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
1313 rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
1314
1315 rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1);
1316 rb_define_module_function(rb_mProcess, "wait", proc_wait, -1);
1317 rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
1318 rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
1319 rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
1320 rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
1321
1322 rb_cProcStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
1323 rb_undef_method(CLASS_OF(rb_cProcStatus), "new");
1324
1325 rb_define_method(rb_cProcStatus, "==", pst_equal, 1);
1326 rb_define_method(rb_cProcStatus, "&", pst_bitand, 1);
1327 rb_define_method(rb_cProcStatus, ">>", pst_rshift, 1);
1328 rb_define_method(rb_cProcStatus, "to_i", pst_to_i, 0);
1329 rb_define_method(rb_cProcStatus, "to_int", pst_to_i, 0);
1330 rb_define_method(rb_cProcStatus, "to_s", pst_to_s, 0);
1331 rb_define_method(rb_cProcStatus, "inspect", pst_to_s, 0);
1332
1333 rb_define_method(rb_cProcStatus, "stopped?", pst_wifstopped, 0);
1334 rb_define_method(rb_cProcStatus, "stopsig", pst_wstopsig, 0);
1335 rb_define_method(rb_cProcStatus, "signaled?", pst_wifsignaled, 0);
1336 rb_define_method(rb_cProcStatus, "termsig", pst_wtermsig, 0);
1337 rb_define_method(rb_cProcStatus, "exited?", pst_wifexited, 0);
1338 rb_define_method(rb_cProcStatus, "exitstatus", pst_wexitstatus, 0);
1339 rb_define_method(rb_cProcStatus, "coredump?", pst_wcoredump, 0);
1340
1341 rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
1342 rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
1343
1344 rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, 0);
1345 rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, 0);
1346 rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
1347 rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
1348
1349 rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
1350
1351 rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
1352 rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
1353
1354 #ifdef HAVE_GETPRIORITY
1355 rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
1356 rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
1357 rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
1358 #endif
1359
1360 rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
1361 rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
1362 rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
1363 rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
1364 rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
1365 rb_define_module_function(rb_mProcess, "euid=", proc_seteuid, 1);
1366 rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
1367 rb_define_module_function(rb_mProcess, "egid=", proc_setegid, 1);
1368
1369 rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
1370
1371 #if defined(HAVE_TIMES) || defined(NT)
1372 S_Tms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", 0);
1373 #endif
1374 }