00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "ruby.h"
00016 #include "rubysig.h"
00017 #include <stdio.h>
00018 #include <errno.h>
00019 #include <signal.h>
00020 #ifdef HAVE_STDLIB_H
00021 #include <stdlib.h>
00022 #endif
00023 #ifdef HAVE_UNISTD_H
00024 #include <unistd.h>
00025 #endif
00026 #ifdef __DJGPP__
00027 #include <process.h>
00028 #endif
00029
00030 #include <time.h>
00031 #include <ctype.h>
00032
00033 #ifndef EXIT_SUCCESS
00034 #define EXIT_SUCCESS 0
00035 #endif
00036 #ifndef EXIT_FAILURE
00037 #define EXIT_FAILURE 1
00038 #endif
00039
00040 struct timeval rb_time_interval (VALUE);
00041
00042 #ifdef HAVE_SYS_WAIT_H
00043 # include <sys/wait.h>
00044 #endif
00045 #ifdef HAVE_GETPRIORITY
00046 # include <sys/resource.h>
00047 #endif
00048 #include "st.h"
00049
00050 #ifdef __EMX__
00051 #undef HAVE_GETPGRP
00052 #endif
00053
00054 #ifdef HAVE_SYS_TIMES_H
00055 #include <sys/times.h>
00056 #endif
00057
00058 #ifdef HAVE_GRP_H
00059 #include <grp.h>
00060 #endif
00061
00062 #if defined(HAVE_TIMES) || defined(_WIN32)
00063 static VALUE S_Tms;
00064 #endif
00065
00066 #ifndef WIFEXITED
00067 #define WIFEXITED(w) (((w) & 0xff) == 0)
00068 #endif
00069 #ifndef WIFSIGNALED
00070 #define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
00071 #endif
00072 #ifndef WIFSTOPPED
00073 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
00074 #endif
00075 #ifndef WEXITSTATUS
00076 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
00077 #endif
00078 #ifndef WTERMSIG
00079 #define WTERMSIG(w) ((w) & 0x7f)
00080 #endif
00081 #ifndef WSTOPSIG
00082 #define WSTOPSIG WEXITSTATUS
00083 #endif
00084
00085 #if defined(__APPLE__) && ( defined(__MACH__) || defined(__DARWIN__) ) && !defined(__MacOS_X__)
00086 #define __MacOS_X__ 1
00087 #endif
00088
00089 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
00090 #define HAVE_44BSD_SETUID 1
00091 #define HAVE_44BSD_SETGID 1
00092 #endif
00093
00094 #ifdef __NetBSD__
00095 #undef HAVE_SETRUID
00096 #undef HAVE_SETRGID
00097 #endif
00098
00099 #if defined(__MacOS_X__) || defined(__bsdi__)
00100 #define BROKEN_SETREUID 1
00101 #define BROKEN_SETREGID 1
00102 #endif
00103
00104 #if defined(HAVE_44BSD_SETUID) || defined(__MacOS_X__)
00105 #if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
00106 #define OBSOLETE_SETREUID 1
00107 #endif
00108 #if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
00109 #define OBSOLETE_SETREGID 1
00110 #endif
00111 #endif
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 static VALUE
00125 get_pid()
00126 {
00127 rb_secure(2);
00128 return INT2FIX(getpid());
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 static VALUE
00149 get_ppid()
00150 {
00151 rb_secure(2);
00152 #ifdef _WIN32
00153 return INT2FIX(0);
00154 #else
00155 return INT2FIX(getppid());
00156 #endif
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 static VALUE rb_cProcStatus;
00191 VALUE rb_last_status = Qnil;
00192
00193 static void
00194 last_status_set(status, pid)
00195 int status, pid;
00196 {
00197 rb_last_status = rb_obj_alloc(rb_cProcStatus);
00198 rb_iv_set(rb_last_status, "status", INT2FIX(status));
00199 rb_iv_set(rb_last_status, "pid", INT2FIX(pid));
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 static VALUE
00217 pst_to_i(st)
00218 VALUE st;
00219 {
00220 return rb_iv_get(st, "status");
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 static VALUE
00232 pst_to_s(st)
00233 VALUE st;
00234 {
00235 return rb_fix2str(pst_to_i(st), 10);
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 static VALUE
00251 pst_pid(st)
00252 VALUE st;
00253 {
00254 return rb_iv_get(st, "pid");
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 static VALUE
00266 pst_inspect(st)
00267 VALUE st;
00268 {
00269 VALUE pid;
00270 int status;
00271 VALUE str;
00272 char buf[256];
00273
00274 pid = pst_pid(st);
00275 status = NUM2INT(st);
00276
00277 snprintf(buf, sizeof(buf), "#<%s: pid=%ld", rb_class2name(CLASS_OF(st)), NUM2LONG(pid));
00278 str = rb_str_new2(buf);
00279 if (WIFSTOPPED(status)) {
00280 int stopsig = WSTOPSIG(status);
00281 const char *signame = ruby_signal_name(stopsig);
00282 if (signame) {
00283 snprintf(buf, sizeof(buf), ",stopped(SIG%s=%d)", signame, stopsig);
00284 }
00285 else {
00286 snprintf(buf, sizeof(buf), ",stopped(%d)", stopsig);
00287 }
00288 rb_str_cat2(str, buf);
00289 }
00290 if (WIFSIGNALED(status)) {
00291 int termsig = WTERMSIG(status);
00292 const char *signame = ruby_signal_name(termsig);
00293 if (signame) {
00294 snprintf(buf, sizeof(buf), ",signaled(SIG%s=%d)", signame, termsig);
00295 }
00296 else {
00297 snprintf(buf, sizeof(buf), ",signaled(%d)", termsig);
00298 }
00299 rb_str_cat2(str, buf);
00300 }
00301 if (WIFEXITED(status)) {
00302 snprintf(buf, sizeof(buf), ",exited(%d)", WEXITSTATUS(status));
00303 rb_str_cat2(str, buf);
00304 }
00305 #ifdef WCOREDUMP
00306 if (WCOREDUMP(status)) {
00307 rb_str_cat2(str, ",coredumped");
00308 }
00309 #endif
00310 rb_str_cat2(str, ">");
00311 return str;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 static VALUE
00324 pst_equal(st1, st2)
00325 VALUE st1, st2;
00326 {
00327 if (st1 == st2) return Qtrue;
00328 return rb_equal(pst_to_i(st1), st2);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 static VALUE
00345 pst_bitand(st1, st2)
00346 VALUE st1, st2;
00347 {
00348 int status = NUM2INT(st1) & NUM2INT(st2);
00349
00350 return INT2NUM(status);
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 static VALUE
00367 pst_rshift(st1, st2)
00368 VALUE st1, st2;
00369 {
00370 int status = NUM2INT(st1) >> NUM2INT(st2);
00371
00372 return INT2NUM(status);
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 static VALUE
00386 pst_wifstopped(st)
00387 VALUE st;
00388 {
00389 int status = NUM2INT(st);
00390
00391 if (WIFSTOPPED(status))
00392 return Qtrue;
00393 else
00394 return Qfalse;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 static VALUE
00407 pst_wstopsig(st)
00408 VALUE st;
00409 {
00410 int status = NUM2INT(st);
00411
00412 if (WIFSTOPPED(status))
00413 return INT2NUM(WSTOPSIG(status));
00414 return Qnil;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 static VALUE
00427 pst_wifsignaled(st)
00428 VALUE st;
00429 {
00430 int status = NUM2INT(st);
00431
00432 if (WIFSIGNALED(status))
00433 return Qtrue;
00434 else
00435 return Qfalse;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 static VALUE
00449 pst_wtermsig(st)
00450 VALUE st;
00451 {
00452 int status = NUM2INT(st);
00453
00454 if (WIFSIGNALED(status))
00455 return INT2NUM(WTERMSIG(status));
00456 return Qnil;
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 static VALUE
00470 pst_wifexited(st)
00471 VALUE st;
00472 {
00473 int status = NUM2INT(st);
00474
00475 if (WIFEXITED(status))
00476 return Qtrue;
00477 else
00478 return Qfalse;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 static VALUE
00502 pst_wexitstatus(st)
00503 VALUE st;
00504 {
00505 int status = NUM2INT(st);
00506
00507 if (WIFEXITED(status))
00508 return INT2NUM(WEXITSTATUS(status));
00509 return Qnil;
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 static VALUE
00522 pst_success_p(st)
00523 VALUE st;
00524 {
00525 int status = NUM2INT(st);
00526
00527 if (!WIFEXITED(status))
00528 return Qnil;
00529 return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 static VALUE
00542 pst_wcoredump(st)
00543 VALUE st;
00544 {
00545 #ifdef WCOREDUMP
00546 int status = NUM2INT(st);
00547
00548 if (WCOREDUMP(status))
00549 return Qtrue;
00550 else
00551 return Qfalse;
00552 #else
00553 return Qfalse;
00554 #endif
00555 }
00556
00557 #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
00558 #define NO_WAITPID
00559 static st_table *pid_tbl;
00560 #endif
00561
00562 int
00563 rb_waitpid(pid, st, flags)
00564 int pid;
00565 int *st;
00566 int flags;
00567 {
00568 int result;
00569 #ifndef NO_WAITPID
00570 int oflags = flags;
00571 if (!rb_thread_alone()) {
00572 flags |= WNOHANG;
00573 }
00574
00575 retry:
00576 TRAP_BEG;
00577 #ifdef HAVE_WAITPID
00578 result = waitpid(pid, st, flags);
00579 #else
00580 result = wait4(pid, st, flags, NULL);
00581 #endif
00582 TRAP_END;
00583 if (result < 0) {
00584 if (errno == EINTR) {
00585 rb_thread_polling();
00586 goto retry;
00587 }
00588 return -1;
00589 }
00590 if (result == 0) {
00591 if (oflags & WNOHANG) return 0;
00592 rb_thread_polling();
00593 if (rb_thread_alone()) flags = oflags;
00594 goto retry;
00595 }
00596 #else
00597 if (pid_tbl && st_lookup(pid_tbl, pid, st)) {
00598 last_status_set(*st, pid);
00599 st_delete(pid_tbl, (st_data_t*)&pid, NULL);
00600 return pid;
00601 }
00602
00603 if (flags) {
00604 rb_raise(rb_eArgError, "can't do waitpid with flags");
00605 }
00606
00607 for (;;) {
00608 TRAP_BEG;
00609 result = wait(st);
00610 TRAP_END;
00611 if (result < 0) {
00612 if (errno == EINTR) {
00613 rb_thread_schedule();
00614 continue;
00615 }
00616 return -1;
00617 }
00618 if (result == pid) {
00619 break;
00620 }
00621 if (!pid_tbl)
00622 pid_tbl = st_init_numtable();
00623 st_insert(pid_tbl, pid, st);
00624 if (!rb_thread_alone()) rb_thread_schedule();
00625 }
00626 #endif
00627 if (result > 0) {
00628 last_status_set(*st, result);
00629 }
00630 return result;
00631 }
00632
00633 #ifdef NO_WAITPID
00634 struct wait_data {
00635 int pid;
00636 int status;
00637 };
00638
00639 static int
00640 wait_each(pid, status, data)
00641 int pid, status;
00642 struct wait_data *data;
00643 {
00644 if (data->status != -1) return ST_STOP;
00645
00646 data->pid = pid;
00647 data->status = status;
00648 return ST_DELETE;
00649 }
00650
00651 static int
00652 waitall_each(pid, status, ary)
00653 int pid, status;
00654 VALUE ary;
00655 {
00656 last_status_set(status, pid);
00657 rb_ary_push(ary, rb_assoc_new(INT2NUM(pid), rb_last_status));
00658 return ST_DELETE;
00659 }
00660 #endif
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721 static VALUE
00722 proc_wait(argc, argv)
00723 int argc;
00724 VALUE *argv;
00725 {
00726 VALUE vpid, vflags;
00727 int pid, flags, status;
00728
00729 rb_secure(2);
00730 flags = 0;
00731 rb_scan_args(argc, argv, "02", &vpid, &vflags);
00732 if (argc == 0) {
00733 pid = -1;
00734 }
00735 else {
00736 pid = NUM2INT(vpid);
00737 if (argc == 2 && !NIL_P(vflags)) {
00738 flags = NUM2UINT(vflags);
00739 }
00740 }
00741 if ((pid = rb_waitpid(pid, &status, flags)) < 0)
00742 rb_sys_fail(0);
00743 if (pid == 0) {
00744 return rb_last_status = Qnil;
00745 }
00746 return INT2FIX(pid);
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 static VALUE
00768 proc_wait2(argc, argv)
00769 int argc;
00770 VALUE *argv;
00771 {
00772 VALUE pid = proc_wait(argc, argv);
00773 if (NIL_P(pid)) return Qnil;
00774 return rb_assoc_new(pid, rb_last_status);
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 static VALUE
00799 proc_waitall()
00800 {
00801 VALUE result;
00802 int pid, status;
00803
00804 rb_secure(2);
00805 result = rb_ary_new();
00806 #ifdef NO_WAITPID
00807 if (pid_tbl) {
00808 st_foreach(pid_tbl, waitall_each, result);
00809 }
00810
00811 for (pid = -1;;) {
00812 pid = wait(&status);
00813 if (pid == -1) {
00814 if (errno == ECHILD)
00815 break;
00816 if (errno == EINTR) {
00817 rb_thread_schedule();
00818 continue;
00819 }
00820 rb_sys_fail(0);
00821 }
00822 last_status_set(status, pid);
00823 rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status));
00824 }
00825 #else
00826 rb_last_status = Qnil;
00827 for (pid = -1;;) {
00828 pid = rb_waitpid(-1, &status, 0);
00829 if (pid == -1) {
00830 if (errno == ECHILD)
00831 break;
00832 rb_sys_fail(0);
00833 }
00834 rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status));
00835 }
00836 #endif
00837 return result;
00838 }
00839
00840 static VALUE
00841 detach_process_watcher(pid_p)
00842 int *pid_p;
00843 {
00844 int cpid, status;
00845
00846 for (;;) {
00847 cpid = rb_waitpid(*pid_p, &status, WNOHANG);
00848 if (cpid != 0) return Qnil;
00849 rb_thread_sleep(1);
00850 }
00851 }
00852
00853 VALUE
00854 rb_detach_process(pid)
00855 int pid;
00856 {
00857 return rb_thread_create(detach_process_watcher, (void*)&pid);
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 static VALUE
00903 proc_detach(VALUE obj, VALUE pid)
00904 {
00905 rb_secure(2);
00906 return rb_detach_process(NUM2INT(pid));
00907 }
00908
00909 #ifndef HAVE_STRING_H
00910 char *strtok();
00911 #endif
00912
00913 #ifdef HAVE_SETITIMER
00914 #define before_exec() rb_thread_stop_timer()
00915 #define after_exec() rb_thread_start_timer()
00916 #else
00917 #define before_exec()
00918 #define after_exec()
00919 #endif
00920
00921 extern char *dln_find_exe();
00922
00923 static void
00924 security(str)
00925 char *str;
00926 {
00927 if (rb_env_path_tainted()) {
00928 if (rb_safe_level() > 0) {
00929 rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
00930 }
00931 }
00932 }
00933
00934 static int
00935 proc_exec_v(argv, prog)
00936 char **argv;
00937 char *prog;
00938 {
00939 if (!prog)
00940 prog = argv[0];
00941 security(prog);
00942 prog = dln_find_exe(prog, 0);
00943 if (!prog)
00944 return -1;
00945
00946 #if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__) || defined(__EMX__) || defined(OS2)
00947 {
00948 #if defined(__human68k__)
00949 #define COMMAND "command.x"
00950 #endif
00951 #if defined(__EMX__) || defined(OS2)
00952 #define COMMAND "cmd.exe"
00953 #endif
00954 #if (defined(MSDOS) && !defined(DJGPP))
00955 #define COMMAND "command.com"
00956 #endif
00957 char *extension;
00958
00959 if ((extension = strrchr(prog, '.')) != NULL && strcasecmp(extension, ".bat") == 0) {
00960 char **new_argv;
00961 char *p;
00962 int n;
00963
00964 for (n = 0; argv[n]; n++)
00965 ;
00966 new_argv = ALLOCA_N(char*, n + 2);
00967 for (; n > 0; n--)
00968 new_argv[n + 1] = argv[n];
00969 new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
00970 for (p = new_argv[1]; *p != '\0'; p++)
00971 if (*p == '/')
00972 *p = '\\';
00973 new_argv[0] = COMMAND;
00974 argv = new_argv;
00975 prog = dln_find_exe(argv[0], 0);
00976 if (!prog) {
00977 errno = ENOENT;
00978 return -1;
00979 }
00980 }
00981 }
00982 #endif
00983 before_exec();
00984 execv(prog, argv);
00985 after_exec();
00986 return -1;
00987 }
00988
00989 static int
00990 proc_exec_n(argc, argv, progv)
00991 int argc;
00992 VALUE *argv;
00993 VALUE progv;
00994 {
00995 char *prog = 0;
00996 char **args;
00997 int i;
00998
00999 if (progv) {
01000 prog = RSTRING(progv)->ptr;
01001 }
01002 args = ALLOCA_N(char*, argc+1);
01003 for (i=0; i<argc; i++) {
01004 SafeStringValue(argv[i]);
01005 args[i] = RSTRING(argv[i])->ptr;
01006 }
01007 args[i] = 0;
01008 if (args[0]) {
01009 return proc_exec_v(args, prog);
01010 }
01011 return -1;
01012 }
01013
01014 int
01015 rb_proc_exec(str)
01016 const char *str;
01017 {
01018 const char *s = str;
01019 char *ss, *t;
01020 char **argv, **a;
01021
01022 while (*str && ISSPACE(*str))
01023 str++;
01024
01025 #ifdef _WIN32
01026 before_exec();
01027 do_spawn(P_OVERLAY, (char *)str);
01028 after_exec();
01029 #else
01030 for (s=str; *s; s++) {
01031 if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
01032 #if defined(MSDOS)
01033 int status;
01034 before_exec();
01035 status = system(str);
01036 after_exec();
01037 if (status != -1)
01038 exit(status);
01039 #else
01040 #if defined(__human68k__) || defined(__CYGWIN32__) || defined(__EMX__)
01041 char *shell = dln_find_exe("sh", 0);
01042 int status = -1;
01043 before_exec();
01044 if (shell)
01045 execl(shell, "sh", "-c", str, (char *) NULL);
01046 else
01047 status = system(str);
01048 after_exec();
01049 if (status != -1)
01050 exit(status);
01051 #else
01052 before_exec();
01053 execl("/bin/sh", "sh", "-c", str, (char *)NULL);
01054 after_exec();
01055 #endif
01056 #endif
01057 return -1;
01058 }
01059 }
01060 a = argv = ALLOCA_N(char*, (s-str)/2+2);
01061 ss = ALLOCA_N(char, s-str+1);
01062 strcpy(ss, str);
01063 if (*a++ = strtok(ss, " \t")) {
01064 while (t = strtok(NULL, " \t")) {
01065 *a++ = t;
01066 }
01067 *a = NULL;
01068 }
01069 if (argv[0]) {
01070 return proc_exec_v(argv, 0);
01071 }
01072 errno = ENOENT;
01073 #endif
01074 return -1;
01075 }
01076
01077 #if defined(__human68k__) || defined(__DJGPP__) || defined(_WIN32)
01078 static int
01079 proc_spawn_v(argv, prog)
01080 char **argv;
01081 char *prog;
01082 {
01083 char *extension;
01084 int status;
01085
01086 if (!prog)
01087 prog = argv[0];
01088 security(prog);
01089 prog = dln_find_exe(prog, 0);
01090 if (!prog)
01091 return -1;
01092
01093 #if defined(__human68k__)
01094 if ((extension = strrchr(prog, '.')) != NULL && strcasecmp(extension, ".bat") == 0) {
01095 char **new_argv;
01096 char *p;
01097 int n;
01098
01099 for (n = 0; argv[n]; n++)
01100 ;
01101 new_argv = ALLOCA_N(char*, n + 2);
01102 for (; n > 0; n--)
01103 new_argv[n + 1] = argv[n];
01104 new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
01105 for (p = new_argv[1]; *p != '\0'; p++)
01106 if (*p == '/')
01107 *p = '\\';
01108 new_argv[0] = COMMAND;
01109 argv = new_argv;
01110 prog = dln_find_exe(argv[0], 0);
01111 if (!prog) {
01112 errno = ENOENT;
01113 return -1;
01114 }
01115 }
01116 #endif
01117 before_exec();
01118 #if defined(_WIN32)
01119 status = do_aspawn(P_WAIT, prog, argv);
01120 #else
01121 status = spawnv(P_WAIT, prog, argv);
01122 #endif
01123 after_exec();
01124 return status;
01125 }
01126
01127 static int
01128 proc_spawn_n(argc, argv, prog)
01129 int argc;
01130 VALUE *argv;
01131 VALUE prog;
01132 {
01133 char **args;
01134 int i;
01135
01136 args = ALLOCA_N(char*, argc + 1);
01137 for (i = 0; i < argc; i++) {
01138 SafeStringValue(argv[i]);
01139 args[i] = RSTRING(argv[i])->ptr;
01140 }
01141 if (prog)
01142 SafeStringValue(prog);
01143 args[i] = (char*) 0;
01144 if (args[0])
01145 return proc_spawn_v(args, prog ? RSTRING(prog)->ptr : 0);
01146 return -1;
01147 }
01148
01149 #if !defined(_WIN32)
01150 static int
01151 proc_spawn(sv)
01152 VALUE sv;
01153 {
01154 char *str;
01155 char *s, *t;
01156 char **argv, **a;
01157 int status;
01158
01159 SafeStringValue(sv);
01160 str = s = RSTRING(sv)->ptr;
01161 for (s = str; *s; s++) {
01162 if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
01163 char *shell = dln_find_exe("sh", 0);
01164 before_exec();
01165 status = shell?spawnl(P_WAIT,shell,"sh","-c",str,(char*)NULL):system(str);
01166 after_exec();
01167 return status;
01168 }
01169 }
01170 a = argv = ALLOCA_N(char*, (s - str) / 2 + 2);
01171 s = ALLOCA_N(char, s - str + 1);
01172 strcpy(s, str);
01173 if (*a++ = strtok(s, " \t")) {
01174 while (t = strtok(NULL, " \t"))
01175 *a++ = t;
01176 *a = NULL;
01177 }
01178 return argv[0] ? proc_spawn_v(argv, 0) : -1;
01179 }
01180 #endif
01181 #endif
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 VALUE
01209 rb_f_exec(argc, argv)
01210 int argc;
01211 VALUE *argv;
01212 {
01213 VALUE prog = 0;
01214 VALUE tmp;
01215
01216 if (argc == 0) {
01217 rb_raise(rb_eArgError, "wrong number of arguments");
01218 }
01219
01220 tmp = rb_check_array_type(argv[0]);
01221 if (!NIL_P(tmp)) {
01222 if (RARRAY(tmp)->len != 2) {
01223 rb_raise(rb_eArgError, "wrong first argument");
01224 }
01225 prog = RARRAY(tmp)->ptr[0];
01226 argv[0] = RARRAY(tmp)->ptr[1];
01227 SafeStringValue(prog);
01228 }
01229 if (argc == 1 && prog == 0) {
01230 VALUE cmd = argv[0];
01231
01232 SafeStringValue(cmd);
01233 rb_proc_exec(RSTRING(cmd)->ptr);
01234 }
01235 else {
01236 proc_exec_n(argc, argv, prog);
01237 }
01238 rb_sys_fail(RSTRING(argv[0])->ptr);
01239 return Qnil;
01240 }
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 static VALUE
01265 rb_f_fork(obj)
01266 VALUE obj;
01267 {
01268 #if !defined(__human68k__) && !defined(_WIN32) && !defined(__MACOS__) && !defined(__EMX__) && !defined(__VMS)
01269 int pid;
01270
01271 rb_secure(2);
01272
01273 #ifndef __VMS
01274 fflush(stdout);
01275 fflush(stderr);
01276 #endif
01277
01278 switch (pid = fork()) {
01279 case 0:
01280 #ifdef linux
01281 after_exec();
01282 #endif
01283 rb_thread_atfork();
01284 if (rb_block_given_p()) {
01285 int status;
01286
01287 rb_protect(rb_yield, Qundef, &status);
01288 ruby_stop(status);
01289 }
01290 return Qnil;
01291
01292 case -1:
01293 rb_sys_fail("fork(2)");
01294 return Qnil;
01295
01296 default:
01297 return INT2FIX(pid);
01298 }
01299 #else
01300 rb_notimplement();
01301 #endif
01302 }
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316 static VALUE
01317 rb_f_exit_bang(argc, argv, obj)
01318 int argc;
01319 VALUE *argv;
01320 VALUE obj;
01321 {
01322 VALUE status;
01323 int istatus;
01324
01325 rb_secure(4);
01326 if (rb_scan_args(argc, argv, "01", &status) == 1) {
01327 switch (status) {
01328 case Qtrue:
01329 istatus = EXIT_SUCCESS;
01330 break;
01331 case Qfalse:
01332 istatus = EXIT_FAILURE;
01333 break;
01334 default:
01335 istatus = NUM2INT(status);
01336 break;
01337 }
01338 }
01339 else {
01340 istatus = EXIT_FAILURE;
01341 }
01342 _exit(istatus);
01343
01344 return Qnil;
01345 }
01346
01347 #if defined(sun)
01348 #define signal(a,b) sigset(a,b)
01349 #endif
01350
01351 void
01352 rb_syswait(pid)
01353 int pid;
01354 {
01355 static int overriding;
01356 #ifdef SIGHUP
01357 RETSIGTYPE (*hfunc)(int);
01358 #endif
01359 #ifdef SIGQUIT
01360 RETSIGTYPE (*qfunc)(int);
01361 #endif
01362 RETSIGTYPE (*ifunc)(int);
01363 int status;
01364 int i, hooked = Qfalse;
01365
01366 if (!overriding) {
01367 #ifdef SIGHUP
01368 hfunc = signal(SIGHUP, SIG_IGN);
01369 #endif
01370 #ifdef SIGQUIT
01371 qfunc = signal(SIGQUIT, SIG_IGN);
01372 #endif
01373 ifunc = signal(SIGINT, SIG_IGN);
01374 overriding = Qtrue;
01375 hooked = Qtrue;
01376 }
01377
01378 do {
01379 i = rb_waitpid(pid, &status, 0);
01380 } while (i == -1 && errno == EINTR);
01381
01382 if (hooked) {
01383 #ifdef SIGHUP
01384 signal(SIGHUP, hfunc);
01385 #endif
01386 #ifdef SIGQUIT
01387 signal(SIGQUIT, qfunc);
01388 #endif
01389 signal(SIGINT, ifunc);
01390 overriding = Qfalse;
01391 }
01392 }
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 static VALUE
01414 rb_f_system(argc, argv)
01415 int argc;
01416 VALUE *argv;
01417 {
01418 int status;
01419 #if defined(__EMX__)
01420 VALUE cmd;
01421
01422 fflush(stdout);
01423 fflush(stderr);
01424 if (argc == 0) {
01425 rb_last_status = Qnil;
01426 rb_raise(rb_eArgError, "wrong number of arguments");
01427 }
01428
01429 if (TYPE(argv[0]) == T_ARRAY) {
01430 if (RARRAY(argv[0])->len != 2) {
01431 rb_raise(rb_eArgError, "wrong first argument");
01432 }
01433 argv[0] = RARRAY(argv[0])->ptr[0];
01434 }
01435 cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
01436
01437 SafeStringValue(cmd);
01438 status = do_spawn(RSTRING(cmd)->ptr);
01439 last_status_set(status, 0);
01440 #elif defined(__human68k__) || defined(__DJGPP__) || defined(_WIN32)
01441 volatile VALUE prog = 0;
01442
01443 fflush(stdout);
01444 fflush(stderr);
01445 if (argc == 0) {
01446 rb_last_status = Qnil;
01447 rb_raise(rb_eArgError, "wrong number of arguments");
01448 }
01449
01450 if (TYPE(argv[0]) == T_ARRAY) {
01451 if (RARRAY(argv[0])->len != 2) {
01452 rb_raise(rb_eArgError, "wrong first argument");
01453 }
01454 prog = RARRAY(argv[0])->ptr[0];
01455 argv[0] = RARRAY(argv[0])->ptr[1];
01456 }
01457
01458 if (argc == 1 && prog == 0) {
01459 #if defined(_WIN32)
01460 SafeStringValue(argv[0]);
01461 status = do_spawn(P_WAIT, RSTRING(argv[0])->ptr);
01462 #else
01463 status = proc_spawn(argv[0]);
01464 #endif
01465 }
01466 else {
01467 status = proc_spawn_n(argc, argv, prog);
01468 }
01469 #if !defined(_WIN32)
01470 last_status_set(status == -1 ? 127 : status, 0);
01471 #endif
01472 #elif defined(__VMS)
01473 VALUE cmd;
01474
01475 if (argc == 0) {
01476 rb_last_status = Qnil;
01477 rb_raise(rb_eArgError, "wrong number of arguments");
01478 }
01479
01480 if (TYPE(argv[0]) == T_ARRAY) {
01481 if (RARRAY(argv[0])->len != 2) {
01482 rb_raise(rb_eArgError, "wrong first argument");
01483 }
01484 argv[0] = RARRAY(argv[0])->ptr[0];
01485 }
01486 cmd = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
01487
01488 SafeStringValue(cmd);
01489 status = system(RSTRING(cmd)->ptr);
01490 last_status_set((status & 0xff) << 8, 0);
01491 #else
01492 volatile VALUE prog = 0;
01493 int pid;
01494 int i;
01495
01496 fflush(stdout);
01497 fflush(stderr);
01498 if (argc == 0) {
01499 rb_last_status = Qnil;
01500 rb_raise(rb_eArgError, "wrong number of arguments");
01501 }
01502
01503 if (TYPE(argv[0]) == T_ARRAY) {
01504 if (RARRAY(argv[0])->len != 2) {
01505 rb_raise(rb_eArgError, "wrong first argument");
01506 }
01507 prog = RARRAY(argv[0])->ptr[0];
01508 argv[0] = RARRAY(argv[0])->ptr[1];
01509 }
01510
01511 if (prog) {
01512 SafeStringValue(prog);
01513 }
01514 for (i = 0; i < argc; i++) {
01515 SafeStringValue(argv[i]);
01516 }
01517 retry:
01518 switch (pid = fork()) {
01519 case 0:
01520 if (argc == 1 && prog == 0) {
01521 rb_proc_exec(RSTRING(argv[0])->ptr);
01522 }
01523 else {
01524 proc_exec_n(argc, argv, prog);
01525 }
01526 _exit(127);
01527 break;
01528
01529 case -1:
01530 if (errno == EAGAIN) {
01531 rb_thread_sleep(1);
01532 goto retry;
01533 }
01534 rb_sys_fail(0);
01535 break;
01536
01537 default:
01538 rb_syswait(pid);
01539 }
01540
01541 status = NUM2INT(rb_last_status);
01542 #endif
01543
01544 if (status == EXIT_SUCCESS) return Qtrue;
01545 return Qfalse;
01546 }
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566 static VALUE
01567 rb_f_sleep(argc, argv)
01568 int argc;
01569 VALUE *argv;
01570 {
01571 int beg, end;
01572
01573 beg = time(0);
01574 if (argc == 0) {
01575 rb_thread_sleep_forever();
01576 }
01577 else if (argc == 1) {
01578 rb_thread_wait_for(rb_time_interval(argv[0]));
01579 }
01580 else {
01581 rb_raise(rb_eArgError, "wrong number of arguments");
01582 }
01583
01584 end = time(0) - beg;
01585
01586 return INT2FIX(end);
01587 }
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601 static VALUE
01602 proc_getpgrp()
01603 {
01604 int pgrp;
01605
01606 rb_secure(2);
01607 #if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
01608 pgrp = getpgrp();
01609 if (pgrp < 0) rb_sys_fail(0);
01610 return INT2FIX(pgrp);
01611 #else
01612 # ifdef HAVE_GETPGID
01613 pgrp = getpgid(0);
01614 if (pgrp < 0) rb_sys_fail(0);
01615 return INT2FIX(pgrp);
01616 # else
01617 rb_notimplement();
01618 # endif
01619 #endif
01620 }
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631 static VALUE
01632 proc_setpgrp()
01633 {
01634 rb_secure(2);
01635
01636
01637
01638
01639 #ifdef HAVE_SETPGID
01640 if (setpgid(0,0) < 0) rb_sys_fail(0);
01641 #elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
01642 if (setpgrp() < 0) rb_sys_fail(0);
01643 #else
01644 rb_notimplement();
01645 #endif
01646 return INT2FIX(0);
01647 }
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660 static VALUE
01661 proc_getpgid(obj, pid)
01662 VALUE obj, pid;
01663 {
01664 #if defined(HAVE_GETPGID) && !defined(__CHECKER__)
01665 int i;
01666
01667 rb_secure(2);
01668 i = getpgid(NUM2INT(pid));
01669 if (i < 0) rb_sys_fail(0);
01670 return INT2NUM(i);
01671 #else
01672 rb_notimplement();
01673 #endif
01674 }
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685 static VALUE
01686 proc_setpgid(obj, pid, pgrp)
01687 VALUE obj, pid, pgrp;
01688 {
01689 #ifdef HAVE_SETPGID
01690 int ipid, ipgrp;
01691
01692 rb_secure(2);
01693 ipid = NUM2INT(pid);
01694 ipgrp = NUM2INT(pgrp);
01695
01696 if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
01697 return INT2FIX(0);
01698 #else
01699 rb_notimplement();
01700 #endif
01701 }
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 static VALUE
01716 proc_setsid()
01717 {
01718 #if defined(HAVE_SETSID)
01719 int pid;
01720
01721 rb_secure(2);
01722 pid = setsid();
01723 if (pid < 0) rb_sys_fail(0);
01724 return INT2FIX(pid);
01725 #elif defined(HAVE_SETPGRP) && defined(TIOCNOTTY)
01726 rb_pid_t pid;
01727 int ret;
01728
01729 rb_secure(2);
01730 pid = getpid();
01731 #if defined(SETPGRP_VOID)
01732 ret = setpgrp();
01733
01734
01735
01736 #else
01737 ret = setpgrp(0, pid);
01738 #endif
01739 if (ret == -1) rb_sys_fail(0);
01740
01741 if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
01742 ioctl(fd, TIOCNOTTY, NULL);
01743 close(fd);
01744 }
01745 return INT2FIX(pid);
01746 #else
01747 rb_notimplement();
01748 #endif
01749 }
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769 static VALUE
01770 proc_getpriority(obj, which, who)
01771 VALUE obj, which, who;
01772 {
01773 #ifdef HAVE_GETPRIORITY
01774 int prio, iwhich, iwho;
01775
01776 rb_secure(2);
01777 iwhich = NUM2INT(which);
01778 iwho = NUM2INT(who);
01779
01780 errno = 0;
01781 prio = getpriority(iwhich, iwho);
01782 if (errno) rb_sys_fail(0);
01783 return INT2FIX(prio);
01784 #else
01785 rb_notimplement();
01786 #endif
01787 }
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802 static VALUE
01803 proc_setpriority(obj, which, who, prio)
01804 VALUE obj, which, who, prio;
01805 {
01806 #ifdef HAVE_GETPRIORITY
01807 int iwhich, iwho, iprio;
01808
01809 rb_secure(2);
01810 iwhich = NUM2INT(which);
01811 iwho = NUM2INT(who);
01812 iprio = NUM2INT(prio);
01813
01814 if (setpriority(iwhich, iwho, iprio) < 0)
01815 rb_sys_fail(0);
01816 return INT2FIX(0);
01817 #else
01818 rb_notimplement();
01819 #endif
01820 }
01821
01822 static int under_uid_switch = 0;
01823 static void
01824 check_uid_switch()
01825 {
01826 rb_secure(2);
01827 if (under_uid_switch) {
01828 rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
01829 }
01830 }
01831
01832 static int under_gid_switch = 0;
01833 static void
01834