process.c


DEFINITIONS

This source file includes following functions.
  1. get_pid
  2. get_ppid
  3. last_status_set
  4. pst_to_i
  5. pst_to_s
  6. pst_equal
  7. pst_bitand
  8. pst_rshift
  9. pst_wifstopped
  10. pst_wstopsig
  11. pst_wifsignaled
  12. pst_wtermsig
  13. pst_wifexited
  14. pst_wexitstatus
  15. pst_wcoredump
  16. rb_waitpid
  17. wait_each
  18. waitall_each
  19. proc_wait
  20. proc_wait2
  21. proc_waitall
  22. security
  23. proc_exec_v
  24. proc_exec_n
  25. rb_proc_exec
  26. proc_spawn_v
  27. proc_spawn_n
  28. proc_spawn
  29. rb_f_exec
  30. rb_f_fork
  31. rb_f_exit_bang
  32. rb_syswait
  33. rb_f_system
  34. rb_f_sleep
  35. proc_getpgrp
  36. proc_setpgrp
  37. proc_getpgid
  38. proc_setpgid
  39. proc_setsid
  40. proc_getpriority
  41. proc_setpriority
  42. proc_getuid
  43. proc_setuid
  44. proc_getgid
  45. proc_setgid
  46. proc_geteuid
  47. proc_seteuid
  48. proc_getegid
  49. proc_setegid
  50. rb_proc_times
  51. Init_process


   1  /**********************************************************************
   2  
   3    process.c -
   4  
   5    $Author: michal $
   6    $Date: 2002/08/28 08:05:23 $
   7    created at: Tue Aug 10 14:30:50 JST 1993
   8  
   9    Copyright (C) 1993-2002 Yukihiro Matsumoto
  10    Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
  11    Copyright (C) 2000  Information-technology Promotion Agency, Japan
  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;         /* seconds */
  31          long    tv_usec;        /* and microseconds */
  32  };
  33  #endif
  34  #endif /* NT */
  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()) {   /* there're other threads to run */
 245          flags |= WNOHANG;
 246      }
 247  
 248    retry:
 249      TRAP_BEG;
 250  #ifdef HAVE_WAITPID
 251      result = waitpid(pid, st, flags);
 252  #else  /* HAVE_WAIT4 */
 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  /* NO_WAITPID */
 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) /* OS/2 emx */
 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                  /* no-op */;
 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 /* MSDOS or __human68k__ or __EMX__ */
 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              /* no-op */;
 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 /* __human68k__ */
 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;                /* dummy */
 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;                /* not reached */
 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;                  /* not reached */
 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    /* check for posix setpgid() first; this matches the posix */
1011    /* getpgrp() above.  It appears that configure will set SETPGRP_VOID */
1012    /* even though setpgrp(0,0) would be prefered. The posix call avoids */
1013    /* this confusion. */
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    /* If `pid_t setpgrp(void)' is equivalent to setsid(),
1075       `ret' will be the same value as `pid', and following open() will fail.
1076       In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
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 /* HZ */
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  }