io.c


DEFINITIONS

This source file includes following functions.
  1. READ_DATA_PENDING
  2. READ_DATA_PENDING_COUNT
  3. READ_DATA_PENDING_PTR
  4. READ_DATA_PENDING
  5. READ_DATA_PENDING_COUNT
  6. READ_DATA_PENDING_PTR
  7. READ_DATA_PENDING
  8. READ_DATA_PENDING_COUNT
  9. READ_DATA_PENDING
  10. READ_DATA_PENDING_COUNT
  11. READ_DATA_PENDING
  12. READ_DATA_PENDING
  13. READ_DATA_PENDING
  14. READ_DATA_PENDING_PTR
  15. rb_eof_error
  16. rb_io_taint_check
  17. rb_io_check_closed
  18. rb_io_check_readable
  19. rb_io_check_writable
  20. rb_read_pending
  21. rb_read_check
  22. ruby_dup
  23. io_fflush
  24. rb_io_wait_readable
  25. rb_io_wait_writable
  26. io_write
  27. rb_io_write
  28. rb_io_addstr
  29. rb_io_flush
  30. rb_io_tell
  31. rb_io_seek
  32. rb_io_seek_m
  33. rb_io_set_pos
  34. rb_io_rewind
  35. rb_io_eof
  36. rb_io_sync
  37. rb_io_set_sync
  38. rb_io_fsync
  39. rb_io_fileno
  40. rb_io_pid
  41. rb_io_inspect
  42. rb_io_to_io
  43. io_read_retryable
  44. rb_io_fread
  45. S_ISREG
  46. remain_size
  47. read_all
  48. io_read
  49. appendline
  50. swallow
  51. rb_io_getline_fast
  52. rb_io_getline
  53. rb_io_gets
  54. rb_io_gets_m
  55. rb_io_lineno
  56. rb_io_set_lineno
  57. lineno_setter
  58. argf_set_lineno
  59. argf_lineno
  60. rb_io_readline
  61. rb_io_readlines
  62. rb_io_each_line
  63. rb_io_each_byte
  64. rb_io_getc
  65. rb_getc
  66. rb_io_readchar
  67. rb_io_ungetc
  68. rb_io_isatty
  69. fptr_finalize
  70. rb_io_fptr_cleanup
  71. rb_io_fptr_finalize
  72. rb_io_close
  73. rb_io_close_m
  74. rb_io_closed
  75. rb_io_close_read
  76. rb_io_close_write
  77. rb_io_sysseek
  78. rb_io_syswrite
  79. rb_io_sysread
  80. rb_io_binmode
  81. rb_io_mode_flags
  82. rb_io_modenum_flags
  83. rb_io_mode_modenum
  84. rb_io_modenum_mode
  85. rb_sysopen
  86. rb_fopen
  87. rb_fdopen
  88. rb_file_open_internal
  89. rb_file_open
  90. rb_file_sysopen_internal
  91. rb_file_sysopen
  92. pipe_add_fptr
  93. pipe_del_fptr
  94. _
  95. pipe_finalize
  96. rb_io_synchronized
  97. rb_io_unbuffered
  98. pipe_open
  99. rb_io_popen
  100. rb_io_s_popen
  101. rb_open_file
  102. rb_io_s_open
  103. rb_io_s_sysopen
  104. rb_f_open
  105. rb_io_open
  106. rb_io_get_io
  107. rb_io_mode_string
  108. io_reopen
  109. rb_io_reopen
  110. rb_io_become
  111. rb_io_printf
  112. rb_f_printf
  113. rb_io_print
  114. rb_f_print
  115. rb_io_putc
  116. rb_f_putc
  117. io_puts_ary
  118. rb_io_puts
  119. rb_f_puts
  120. rb_p
  121. rb_f_p
  122. rb_obj_display
  123. rb_io_defset
  124. set_stdin
  125. set_outfile
  126. set_stdout
  127. set_stderr
  128. prep_stdio
  129. prep_path
  130. rb_io_s_alloc
  131. rb_io_initialize
  132. rb_file_initialize
  133. rb_io_s_new
  134. argf_forward
  135. next_argv
  136. any_close
  137. argf_getline
  138. rb_f_gets
  139. rb_gets
  140. rb_f_readline
  141. rb_f_getc
  142. rb_f_readlines
  143. rb_f_backquote
  144. rb_f_select
  145. io_cntl
  146. rb_io_ctl
  147. rb_io_ioctl
  148. rb_io_fcntl
  149. rb_f_syscall
  150. rb_io_s_pipe
  151. io_s_foreach
  152. rb_io_s_foreach
  153. io_s_readlines
  154. rb_io_s_readlines
  155. io_s_read
  156. rb_io_s_read
  157. argf_tell
  158. argf_seek_m
  159. argf_set_pos
  160. argf_rewind
  161. argf_fileno
  162. argf_to_io
  163. argf_read
  164. argf_getc
  165. argf_readchar
  166. argf_eof
  167. argf_each_line
  168. argf_each_byte
  169. argf_filename
  170. argf_file
  171. argf_binmode
  172. argf_skip
  173. argf_close
  174. argf_closed
  175. opt_i_get
  176. opt_i_set
  177. Init_IO


   1  /**********************************************************************
   2  
   3    io.c -
   4  
   5    $Author: nobu $
   6    $Date: 2002/09/11 01:09:04 $
   7    created at: Fri Oct 15 18:08:59 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  #if defined(__VMS)
  16  #define _XOPEN_SOURCE
  17  #define _POSIX_C_SOURCE 2
  18  #endif
  19  
  20  #include "ruby.h"
  21  #include "rubyio.h"
  22  #include "rubysig.h"
  23  #include "env.h"
  24  #include <ctype.h>
  25  #include <errno.h>
  26  
  27  #if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN__) || defined(NT) || defined(__human68k__) || defined(__EMX__) || defined(__BEOS__)
  28  # define NO_SAFE_RENAME
  29  #endif
  30  
  31  #if defined(MSDOS) || defined(__CYGWIN__) || defined(NT)
  32  # define NO_LONG_FNAME
  33  #endif
  34  
  35  #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(sun) || defined(_nec_ews)
  36  # define USE_SETVBUF
  37  #endif
  38  
  39  #ifdef __QNXNTO__
  40  #include "unix.h"
  41  #endif
  42  
  43  #include <sys/types.h>
  44  #if !defined(DJGPP) && !defined(NT) && !defined(__human68k__)
  45  #include <sys/ioctl.h>
  46  #endif
  47  #if defined(HAVE_FCNTL_H) || defined(NT)
  48  #include <fcntl.h>
  49  #elif defined(HAVE_SYS_FCNTL_H)
  50  #include <sys/fcntl.h>
  51  #endif
  52  
  53  #if !HAVE_OFF_T && !defined(off_t)
  54  # define off_t  long
  55  #endif
  56  #if !HAVE_FSEEKO && !defined(fseeko)
  57  # define fseeko  fseek
  58  #endif
  59  #if !HAVE_FTELLO && !defined(ftello)
  60  # define ftello  ftell
  61  #endif
  62  
  63  #ifdef HAVE_SYS_TIME_H
  64  # include <sys/time.h>
  65  #else
  66  #ifndef NT
  67  struct timeval {
  68          long    tv_sec;         /* seconds */
  69          long    tv_usec;        /* and microseconds */
  70  };
  71  #endif
  72  #endif
  73  
  74  #include <sys/stat.h>
  75  
  76  /* EMX has sys/param.h, but.. */
  77  #if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
  78  # include <sys/param.h>
  79  #endif
  80  
  81  #if !defined NOFILE
  82  # define NOFILE 64
  83  #endif
  84  
  85  #ifdef HAVE_UNISTD_H
  86  #include <unistd.h>
  87  #endif
  88  
  89  extern void Init_File _((void));
  90  
  91  #ifdef __BEOS__
  92  # ifndef NOFILE
  93  #  define NOFILE (OPEN_MAX)
  94  # endif
  95  #include <net/socket.h>
  96  #endif
  97  
  98  #include "util.h"
  99  
 100  #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
 101  # error off_t is bigger than long, but you have no long long...
 102  #endif
 103  
 104  VALUE rb_cIO;
 105  VALUE rb_eEOFError;
 106  VALUE rb_eIOError;
 107  
 108  VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout;
 109  static VALUE orig_stdin, orig_stdout, orig_stderr;
 110  static int saved_fd[3] = {0, 1, 2};
 111  
 112  VALUE rb_output_fs;
 113  VALUE rb_rs;
 114  VALUE rb_output_rs;
 115  VALUE rb_default_rs;
 116  
 117  static VALUE argf;
 118  
 119  static ID id_write;
 120  
 121  extern char *ruby_inplace_mode;
 122  
 123  struct timeval rb_time_interval _((VALUE));
 124  
 125  static VALUE filename, current_file;
 126  static int gets_lineno;
 127  static int init_p = 0, next_p = 0, first_p = 1;
 128  static VALUE lineno;
 129  
 130  #ifdef _STDIO_USES_IOSTREAM  /* GNU libc */
 131  #  ifdef _IO_fpos_t
 132  #    define READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
 133  #    define READ_DATA_PENDING_COUNT(fp) ((fp)->_IO_read_end - (fp)->_IO_read_ptr)
 134  #    define READ_DATA_PENDING_PTR(fp) ((fp)->_IO_read_ptr)
 135  #  else
 136  #    define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
 137  #    define READ_DATA_PENDING_COUNT(fp) ((fp)->_egptr - (fp)->_gptr)
 138  #    define READ_DATA_PENDING_PTR(fp) ((fp)->_gptr)
 139  #  endif
 140  #elif defined(FILE_COUNT)
 141  #  define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
 142  #  define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_COUNT)
 143  #elif defined(FILE_READEND)
 144  #  define READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
 145  #  define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_READEND - (fp)->FILE_READPTR)
 146  #elif defined(__BEOS__)
 147  #  define READ_DATA_PENDING(fp) (fp->_state._eof == 0)
 148  #elif defined(__VMS)
 149  #  define READ_DATA_PENDING(fp) (((unsigned int)((*(fp))->_flag) & _IOEOF) == 0)
 150  #else
 151  /* requires systems own version of the ReadDataPending() */
 152  extern int ReadDataPending();
 153  #  define READ_DATA_PENDING(fp) (!feof(fp))
 154  #endif
 155  #ifndef READ_DATA_PENDING_PTR
 156  # ifdef FILE_READPTR
 157  #  define READ_DATA_PENDING_PTR(fp) ((fp)->FILE_READPTR)
 158  # endif
 159  #endif
 160  
 161  #define READ_CHECK(fp) do {\
 162      if (!READ_DATA_PENDING(fp)) {\
 163          rb_thread_wait_fd(fileno(fp));\
 164          rb_io_check_closed(fptr);\
 165       }\
 166  } while(0)
 167  
 168  void
 169  rb_eof_error()
 170  {
 171      rb_raise(rb_eEOFError, "End of file reached");
 172  }
 173  
 174  VALUE
 175  rb_io_taint_check(io)
 176      VALUE io;
 177  {
 178      if (!OBJ_TAINTED(io) && rb_safe_level() >= 4)
 179          rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
 180      rb_check_frozen(io);
 181      return io;
 182  }
 183  
 184  void
 185  rb_io_check_closed(fptr)
 186      OpenFile *fptr;
 187  {
 188      if (!fptr) {
 189          rb_raise(rb_eIOError, "uninitialized stream");
 190      }
 191      if (!fptr->f && !fptr->f2) {
 192          rb_raise(rb_eIOError, "closed stream");
 193      }
 194  }
 195  
 196  void
 197  rb_io_check_readable(fptr)
 198      OpenFile *fptr;
 199  {
 200      if (!(fptr->mode & FMODE_READABLE)) {
 201          rb_raise(rb_eIOError, "not opened for reading");
 202      }
 203  }
 204  
 205  void
 206  rb_io_check_writable(fptr)
 207      OpenFile *fptr;
 208  {
 209      if (!(fptr->mode & FMODE_WRITABLE)) {
 210          rb_raise(rb_eIOError, "not opened for writing");
 211      }
 212  }
 213  
 214  int
 215  rb_read_pending(fp)
 216      FILE *fp;
 217  {
 218      return READ_DATA_PENDING(fp);
 219  }
 220  
 221  void
 222  rb_read_check(fp)
 223      FILE *fp;
 224  {
 225      if (!READ_DATA_PENDING(fp)) {
 226          rb_thread_wait_fd(fileno(fp));
 227      }
 228  }
 229  
 230  static int
 231  ruby_dup(orig)
 232      int orig;
 233  {
 234      int fd;
 235  
 236      fd = dup(orig);
 237      if (fd < 0) {
 238          if (errno == EMFILE || errno == ENFILE) {
 239              rb_gc();
 240              fd = dup(orig);
 241          }
 242          if (fd < 0) {
 243              rb_sys_fail(0);
 244          }
 245      }
 246      return fd;
 247  }
 248  
 249  static void
 250  io_fflush(f, fptr)
 251      FILE *f;
 252      OpenFile *fptr;
 253  {
 254      int n;
 255  
 256      rb_thread_fd_writable(fileno(f));
 257      TRAP_BEG;
 258      n = fflush(f);
 259      TRAP_END;
 260      if (n == EOF) rb_sys_fail(fptr->path);
 261      fptr->mode &= ~FMODE_WBUF;
 262  }
 263  
 264  void
 265  rb_io_wait_readable(f)
 266      int f;
 267  {
 268      fd_set rfds;
 269      FD_ZERO(&rfds);
 270      FD_SET(f, &rfds);
 271      rb_thread_select(f + 1, &rfds, NULL, NULL, NULL);
 272  }
 273  
 274  void
 275  rb_io_wait_writable(f)
 276      int f;
 277  {
 278      fd_set wfds;
 279      FD_ZERO(&wfds);
 280      FD_SET(f, &wfds);
 281      rb_thread_select(f + 1, NULL, &wfds, NULL, NULL);
 282  }
 283  
 284  /* writing functions */
 285  static VALUE
 286  io_write(io, str)
 287      VALUE io, str;
 288  {
 289      OpenFile *fptr;
 290      FILE *f;
 291      long n, r;
 292      register char *ptr;
 293  
 294      rb_secure(4);
 295      if (TYPE(str) != T_STRING)
 296          str = rb_obj_as_string(str);
 297      if (RSTRING(str)->len == 0) return INT2FIX(0);
 298  
 299      if (TYPE(io) != T_FILE) {
 300          /* port is not IO, call write method for it. */
 301          return rb_funcall(io, id_write, 1, str);
 302      }
 303  
 304      GetOpenFile(io, fptr);
 305      rb_io_check_writable(fptr);
 306      f = GetWriteFile(fptr);
 307  
 308      ptr = RSTRING(str)->ptr;
 309      n = RSTRING(str)->len;
 310      do {
 311  #ifdef __human68k__
 312          if (fputc(*ptr++, f) == EOF) {
 313              if (ferror(f)) rb_sys_fail(fptr->path);
 314              break;
 315          }
 316          --n;
 317  #else
 318          r = fwrite(ptr, 1, n, f);
 319          ptr += r;
 320          n -= r;
 321          if (ferror(f)) {
 322              switch (errno) {
 323                case EINTR:
 324  #if defined(ERESTART)
 325                case ERESTART:
 326  #endif
 327                  clearerr(f);
 328                  continue;
 329                case EAGAIN:
 330  #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
 331                case EWOULDBLOCK:
 332  #endif
 333                  clearerr(f);
 334                  rb_io_wait_writable(fileno(f));
 335                  continue;
 336              }
 337              rb_sys_fail(fptr->path);
 338          }
 339  #endif
 340      } while (n > 0);
 341      n = ptr - RSTRING(str)->ptr;
 342      if (fptr->mode & FMODE_SYNC) {
 343          io_fflush(f, fptr);
 344      }
 345      else {
 346          fptr->mode |= FMODE_WBUF;
 347      }
 348  
 349      return LONG2FIX(n);
 350  }
 351  
 352  VALUE
 353  rb_io_write(io, str)
 354      VALUE io, str;
 355  {
 356      return rb_funcall(io, id_write, 1, str);
 357  }
 358  
 359  VALUE
 360  rb_io_addstr(io, str)
 361      VALUE io, str;
 362  {
 363      rb_io_write(io, str);
 364      return io;
 365  }
 366  
 367  static VALUE
 368  rb_io_flush(io)
 369      VALUE io;
 370  {
 371      OpenFile *fptr;
 372      FILE *f;
 373  
 374      GetOpenFile(io, fptr);
 375      rb_io_check_writable(fptr);
 376      f = GetWriteFile(fptr);
 377  
 378      io_fflush(f, fptr);
 379  
 380      return io;
 381  }
 382  
 383  static VALUE
 384  rb_io_tell(io)
 385       VALUE io;
 386  {
 387      OpenFile *fptr;
 388      off_t pos;
 389  
 390      GetOpenFile(io, fptr);
 391      pos = ftello(fptr->f);
 392      if (ferror(fptr->f)) rb_sys_fail(fptr->path);
 393      return OFFT2NUM(pos);
 394  }
 395  
 396  #ifndef SEEK_CUR
 397  # define SEEK_SET 0
 398  # define SEEK_CUR 1
 399  # define SEEK_END 2
 400  #endif
 401  
 402  static VALUE
 403  rb_io_seek(io, offset, whence)
 404      VALUE io, offset;
 405      int whence;
 406  {
 407      OpenFile *fptr;
 408      off_t pos;
 409  
 410      GetOpenFile(io, fptr);
 411      pos = fseeko(fptr->f, NUM2OFFT(offset), whence);
 412      if (pos != 0) rb_sys_fail(fptr->path);
 413      clearerr(fptr->f);
 414  
 415      return INT2FIX(0);
 416  }
 417  
 418  static VALUE
 419  rb_io_seek_m(argc, argv, io)
 420      int argc;
 421      VALUE *argv;
 422      VALUE io;
 423  {
 424      VALUE offset, ptrname;
 425      int whence = SEEK_SET;
 426  
 427      if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
 428          whence = NUM2INT(ptrname);
 429      }
 430  
 431      return rb_io_seek(io, offset, whence);
 432  }
 433  
 434  static VALUE
 435  rb_io_set_pos(io, offset)
 436       VALUE io, offset;
 437  {
 438      OpenFile *fptr;
 439      off_t pos;
 440  
 441      GetOpenFile(io, fptr);
 442      pos = fseeko(fptr->f, NUM2OFFT(offset), SEEK_SET);
 443      if (pos != 0) rb_sys_fail(fptr->path);
 444      clearerr(fptr->f);
 445  
 446      return OFFT2NUM(pos);
 447  }
 448  
 449  static VALUE
 450  rb_io_rewind(io)
 451      VALUE io;
 452  {
 453      OpenFile *fptr;
 454  
 455      GetOpenFile(io, fptr);
 456      if (fseeko(fptr->f, 0L, 0) != 0) rb_sys_fail(fptr->path);
 457      clearerr(fptr->f);
 458      if (io == current_file) {
 459          gets_lineno -= fptr->lineno;
 460      }
 461      fptr->lineno = 0;
 462  
 463      return INT2FIX(0);
 464  }
 465  
 466  VALUE
 467  rb_io_eof(io)
 468      VALUE io;
 469  {
 470      OpenFile *fptr;
 471      int ch;
 472  
 473      GetOpenFile(io, fptr);
 474      rb_io_check_readable(fptr);
 475  
 476      if (feof(fptr->f)) return Qtrue;
 477      if (READ_DATA_PENDING(fptr->f)) return Qfalse;
 478      READ_CHECK(fptr->f);
 479      TRAP_BEG;
 480      ch = getc(fptr->f);
 481      TRAP_END;
 482  
 483      if (ch != EOF) {
 484          ungetc(ch, fptr->f);
 485          return Qfalse;
 486      }
 487      return Qtrue;
 488  }
 489  
 490  static VALUE
 491  rb_io_sync(io)
 492      VALUE io;
 493  {
 494      OpenFile *fptr;
 495  
 496      GetOpenFile(io, fptr);
 497      return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
 498  }
 499  
 500  static VALUE
 501  rb_io_set_sync(io, mode)
 502      VALUE io, mode;
 503  {
 504      OpenFile *fptr;
 505  
 506      GetOpenFile(io, fptr);
 507      if (RTEST(mode)) {
 508          fptr->mode |= FMODE_SYNC;
 509      }
 510      else {
 511          fptr->mode &= ~FMODE_SYNC;
 512      }
 513      return mode;
 514  }
 515  
 516  static VALUE
 517  rb_io_fsync(io)
 518      VALUE io;
 519  {
 520  #ifdef HAVE_FSYNC
 521      OpenFile *fptr;
 522      FILE *f;
 523  
 524      GetOpenFile(io, fptr);
 525      rb_io_check_writable(fptr);
 526      f = GetWriteFile(fptr);
 527  
 528      io_fflush(f, fptr);
 529      if (fsync(fileno(f)) < 0)
 530          rb_sys_fail(fptr->path);
 531      return INT2FIX(0);
 532  #else
 533      rb_notimplement();
 534      return Qnil;                /* not reached */
 535  #endif
 536  }
 537  
 538  static VALUE
 539  rb_io_fileno(io)
 540      VALUE io;
 541  {
 542      OpenFile *fptr;
 543      int fd;
 544  
 545      GetOpenFile(io, fptr);
 546      fd = fileno(fptr->f);
 547      return INT2FIX(fd);
 548  }
 549  
 550  static VALUE
 551  rb_io_pid(io)
 552      VALUE io;
 553  {
 554      OpenFile *fptr;
 555  
 556      GetOpenFile(io, fptr);
 557      if (!fptr->pid)
 558          return Qnil;
 559      return INT2FIX(fptr->pid);
 560  }
 561  
 562  static VALUE
 563  rb_io_inspect(obj)
 564      VALUE obj;
 565  {
 566      OpenFile *fptr;
 567      char *buf, *cname;
 568  
 569      GetOpenFile(obj, fptr);
 570      if (!fptr->path) return rb_any_to_s(obj);
 571      cname = rb_class2name(CLASS_OF(obj));
 572      buf = ALLOCA_N(char, strlen(cname) + strlen(fptr->path) + 5);
 573      sprintf(buf, "#<%s:%s>", cname, fptr->path);
 574      return rb_str_new2(buf);
 575  }
 576  
 577  static VALUE
 578  rb_io_to_io(io)
 579      VALUE io;
 580  {
 581      return io;
 582  }
 583  
 584  /* reading functions */
 585  static void
 586  io_read_retryable(f, path)
 587      FILE *f;
 588      const char *path;
 589  {
 590      switch (errno) {
 591        case EINTR:
 592  #if defined(ERESTART)
 593        case ERESTART:
 594  #endif
 595          clearerr(f);
 596          break;
 597        case EAGAIN:
 598  #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
 599        case EWOULDBLOCK:
 600  #endif
 601          clearerr(f);
 602          rb_io_wait_readable(fileno(f));
 603          break;
 604        default:
 605          rb_sys_fail(path);
 606          break;
 607      }
 608  }
 609  
 610  long
 611  rb_io_fread(ptr, len, f)
 612      char *ptr;
 613      long len;
 614      FILE *f;
 615  {
 616      long n = len;
 617      int c;
 618  
 619      while (n > 0) {
 620  #ifdef READ_DATA_PENDING_COUNT
 621          long i = READ_DATA_PENDING_COUNT(f);
 622          if (i <= 0) {
 623              rb_thread_wait_fd(fileno(f));
 624              i = READ_DATA_PENDING_COUNT(f);
 625          }
 626          if (i > 0) {
 627              if (i > n) i = n;
 628              TRAP_BEG;
 629              c = fread(ptr, 1, i, f);
 630              TRAP_END;
 631              if (c < 0) goto eof;
 632              ptr += c;
 633              n -= c;
 634              if (c < i) goto eof;
 635              continue;
 636          }
 637  #else
 638          if (!READ_DATA_PENDING(f)) {
 639              rb_thread_wait_fd(fileno(f));
 640          }
 641  #endif
 642          TRAP_BEG;
 643          c = getc(f);
 644          TRAP_END;
 645          if (c == EOF) {
 646            eof:
 647              if (ferror(f)) {
 648                  switch (errno) {
 649                    case EINTR:
 650                      clearerr(f);
 651                      continue;
 652                    case EAGAIN:
 653  #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
 654                    case EWOULDBLOCK:
 655  #endif
 656                      clearerr(f);
 657                      return len - n;
 658                  }
 659                  return 0;
 660              }
 661              *ptr = '\0';
 662              break;
 663          }
 664          *ptr++ = c;
 665          n--;
 666      }
 667      return len - n;
 668  }
 669  
 670  #ifndef S_ISREG
 671  #   define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
 672  #endif
 673  
 674  #define SMALLBUF 100
 675  
 676  static long
 677  remain_size(fptr)
 678      OpenFile *fptr;
 679  {
 680      struct stat st;
 681      off_t siz = BUFSIZ;
 682      off_t pos;
 683  
 684      if (feof(fptr->f)) return 0;
 685      if (fstat(fileno(fptr->f), &st) == 0  && S_ISREG(st.st_mode)
 686  #ifdef __BEOS__
 687          && (st.st_dev > 3)
 688  #endif
 689          )
 690      {
 691          pos = ftello(fptr->f);
 692          if (st.st_size > pos && pos >= 0) {
 693              siz = st.st_size - pos + 1;
 694              if (siz > LONG_MAX) {
 695                  rb_raise(rb_eIOError, "file too big for single read");
 696              }
 697          }
 698      }
 699      return (long)siz;
 700  }
 701  
 702  static VALUE
 703  read_all(fptr, siz)
 704      OpenFile *fptr;
 705      long siz;
 706  {
 707      VALUE str;
 708      long bytes = 0;
 709      long n;
 710      off_t pos = 0;
 711  
 712      if (feof(fptr->f)) return Qnil;
 713      READ_CHECK(fptr->f);
 714      if (!siz) siz = BUFSIZ;
 715      str = rb_tainted_str_new(0, siz);
 716      pos = ftello(fptr->f);
 717      for (;;) {
 718          n = rb_io_fread(RSTRING(str)->ptr+bytes, siz-bytes, fptr->f);
 719          if (pos > 0 && n == 0 && bytes == 0) {
 720              if (feof(fptr->f)) return Qnil;
 721              if (!ferror(fptr->f)) return rb_str_new(0, 0);
 722              rb_sys_fail(fptr->path);
 723          }
 724          bytes += n;
 725          if (bytes < siz) break;
 726          siz += BUFSIZ;
 727          rb_str_resize(str, siz);
 728      }
 729      if (bytes == 0) return rb_str_new(0,0);
 730      if (bytes != siz) rb_str_resize(str, bytes);
 731  
 732      return str;
 733  }
 734  
 735  static VALUE
 736  io_read(argc, argv, io)
 737      int argc;
 738      VALUE *argv;
 739      VALUE io;
 740  {
 741      OpenFile *fptr;
 742      long n, len;
 743      VALUE length, str;
 744  
 745      rb_scan_args(argc, argv, "01", &length);
 746  
 747      GetOpenFile(io, fptr);
 748      rb_io_check_readable(fptr);
 749      if (NIL_P(length)) {
 750          return read_all(fptr, remain_size(fptr));
 751      }
 752  
 753      len = NUM2LONG(length);
 754      if (len < 0) {
 755          rb_raise(rb_eArgError, "negative length %d given", len);
 756      }
 757  
 758      if (feof(fptr->f)) return Qnil;
 759      str = rb_str_new(0, len);
 760      if (len == 0) return str;
 761  
 762      READ_CHECK(fptr->f);
 763      n = rb_io_fread(RSTRING(str)->ptr, len, fptr->f);
 764      if (n == 0) {
 765          if (feof(fptr->f)) return Qnil;
 766          rb_sys_fail(fptr->path);
 767      }
 768      RSTRING(str)->len = n;
 769      RSTRING(str)->ptr[n] = '\0';
 770      OBJ_TAINT(str);
 771  
 772      return str;
 773  }
 774  
 775  static int
 776  appendline(fptr, delim, strp)
 777      OpenFile *fptr;
 778      int delim;
 779      VALUE *strp;
 780  {
 781      FILE *f = fptr->f;
 782      VALUE str = *strp;
 783      int c = EOF;
 784  #ifndef READ_DATA_PENDING_PTR
 785      char buf[8192];
 786      char *bp = buf, *bpe = buf + sizeof buf - 3;
 787      int cnt;
 788  #endif
 789  
 790      do {
 791  #ifdef READ_DATA_PENDING_PTR
 792          long pending = READ_DATA_PENDING_COUNT(f);
 793          if (pending > 0) {
 794              const char *p = READ_DATA_PENDING_PTR(f);
 795              const char *e = memchr(p, delim, pending);
 796              long last = 0, len = (c != EOF);
 797              if (e) pending = e - p + 1;
 798              len += pending;
 799              if (!NIL_P(str)) {
 800                  last = RSTRING(str)->len;
 801                  rb_str_resize(str, last + len);
 802              }
 803              else {
 804                  *strp = str = rb_str_buf_new(len);
 805                  RSTRING(str)->len = len;
 806              }
 807              if (c != EOF) {
 808                  RSTRING(str)->ptr[last++] = c;
 809              }
 810              fread(RSTRING(str)->ptr + last, 1, pending, f); /* must not fail */
 811              if (e) return delim;
 812          }
 813          else if (c != EOF) {
 814              if (!NIL_P(str)) {
 815                  char ch = c;
 816                  rb_str_buf_cat(str, &ch, 1);
 817              }
 818              else {
 819                  *strp = str = rb_str_buf_new(1);
 820                  RSTRING(str)->ptr[RSTRING(str)->len++] = c;
 821              }
 822          }
 823          rb_thread_wait_fd(fileno(f));
 824          rb_io_check_closed(fptr);
 825  #else
 826          READ_CHECK(f);
 827  #endif
 828          TRAP_BEG;
 829          c = getc(f);
 830          TRAP_END;
 831          if (c == EOF) {
 832              if (ferror(f)) {
 833                  io_read_retryable(f, fptr->path);
 834                  continue;
 835              }
 836              return c;
 837          }
 838  #ifndef READ_DATA_PENDING_PTR
 839          if ((*bp++ = c) == delim || bp == bpe) {
 840              cnt = bp - buf;
 841  
 842              if (cnt > 0) {
 843                  if (!NIL_P(str))
 844                      rb_str_cat(str, buf, cnt);
 845                  else
 846                      *strp = str = rb_str_new(buf, cnt);
 847              }
 848              bp = buf;
 849          }
 850  #endif
 851      } while (c != delim);
 852  
 853  #ifdef READ_DATA_PENDING_PTR
 854      {
 855          char ch = c;
 856          if (!NIL_P(str)) {
 857              rb_str_cat(str, &ch, 1);
 858          }
 859          else {
 860              *strp = str = rb_str_new(&ch, 1);
 861          }
 862      }
 863  #endif
 864  
 865      return c;
 866  }
 867  
 868  static inline int
 869  swallow(fptr, term)
 870      OpenFile *fptr;
 871      int term;
 872  {
 873      FILE *f = fptr->f;
 874      int c;
 875  
 876      do {
 877  #ifdef READ_DATA_PENDING_PTR
 878          long cnt;
 879          while ((cnt = READ_DATA_PENDING_COUNT(f)) > 0) {
 880              char buf[1024];
 881              const char *p = READ_DATA_PENDING_PTR(f);
 882              int i;
 883              if (cnt > sizeof buf) cnt = sizeof buf;
 884              if (*p != term) return Qtrue;
 885              i = cnt;
 886              while (--i && *++p == term);
 887              if (!fread(buf, 1, cnt - i, f)) /* must not fail */
 888                  rb_sys_fail(fptr->path);
 889          }
 890          rb_thread_wait_fd(fileno(f));
 891          rb_io_check_closed(fptr);
 892  #else
 893          READ_CHECK(f);
 894  #endif
 895          TRAP_BEG;
 896          c = getc(f);
 897          TRAP_END;
 898          if (c != term) {
 899              ungetc(c, f);
 900              return Qtrue;
 901          }
 902      } while (c != EOF);
 903      return Qfalse;
 904  }
 905  
 906  static VALUE
 907  rb_io_getline_fast(fptr, delim)
 908      OpenFile *fptr;
 909      int delim;
 910  {
 911      VALUE str = Qnil;
 912      int c;
 913  
 914      while ((c = appendline(fptr, delim, &str)) != EOF && c != delim);
 915  
 916      if (!NIL_P(str)) {
 917          fptr->lineno++;
 918          lineno = INT2FIX(fptr->lineno);
 919          OBJ_TAINT(str);
 920      }
 921  
 922      return str;
 923  }
 924  
 925  static VALUE
 926  rb_io_getline(rs, fptr)
 927      VALUE rs;
 928      OpenFile *fptr;
 929  {
 930      VALUE str = Qnil;
 931  
 932      if (NIL_P(rs)) {
 933          str = read_all(fptr, 0);
 934      }
 935      else if (rs == rb_default_rs) {
 936          return rb_io_getline_fast(fptr, '\n');
 937      }
 938      else {
 939          int c, newline;
 940          char *rsptr;
 941          long rslen;
 942          int rspara = 0;
 943  
 944          StringValue(rs);
 945          rslen = RSTRING(rs)->len;
 946          if (rslen == 0) {
 947              rsptr = "\n\n";
 948              rslen = 2;
 949              rspara = 1;
 950              swallow(fptr, '\n');
 951          }
 952          else if (rslen == 1) {
 953              return rb_io_getline_fast(fptr, RSTRING(rs)->ptr[0]);
 954          }
 955          else {
 956              rsptr = RSTRING(rs)->ptr;
 957          }
 958          newline = rsptr[rslen - 1];
 959  
 960          while ((c = appendline(fptr, newline, &str)) != EOF &&
 961                 (c != newline || RSTRING(str)->len < rslen ||
 962                  memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen,rsptr,rslen)));
 963  
 964          if (rspara) {
 965              if (c != EOF) {
 966                  swallow(fptr, '\n');
 967              }
 968          }
 969      }
 970  
 971      if (!NIL_P(str)) {
 972          fptr->lineno++;
 973          lineno = INT2FIX(fptr->lineno);
 974          OBJ_TAINT(str);
 975      }
 976  
 977      return str;
 978  }
 979  
 980  VALUE
 981  rb_io_gets(io)
 982      VALUE io;
 983  {
 984      OpenFile *fptr;
 985  
 986      GetOpenFile(io, fptr);
 987      rb_io_check_readable(fptr);
 988      return rb_io_getline_fast(fptr, '\n');
 989  }
 990  
 991  static VALUE
 992  rb_io_gets_m(argc, argv, io)
 993      int argc;
 994      VALUE *argv;
 995      VALUE io;
 996  {
 997      VALUE rs, str;
 998      OpenFile *fptr;
 999  
1000      if (argc == 0) {
1001          rs = rb_rs;
1002      }
1003      else {
1004          rb_scan_args(argc, argv, "1", &rs);
1005      }
1006      GetOpenFile(io, fptr);
1007      rb_io_check_readable(fptr);
1008      str = rb_io_getline(rs, fptr);
1009  
1010      if (!NIL_P(str)) {
1011          rb_lastline_set(str);
1012      }
1013      return str;
1014  }
1015  
1016  static VALUE
1017  rb_io_lineno(io)
1018      VALUE io;
1019  {
1020      OpenFile *fptr;
1021  
1022      GetOpenFile(io, fptr);
1023      rb_io_check_readable(fptr);
1024      return INT2NUM(fptr->lineno);
1025  }
1026  
1027  static VALUE
1028  rb_io_set_lineno(io, lineno)
1029      VALUE io, lineno;
1030  {
1031      OpenFile *fptr;
1032  
1033      GetOpenFile(io, fptr);
1034      rb_io_check_readable(fptr);
1035      fptr->lineno = NUM2INT(lineno);
1036      return lineno;
1037  }
1038  
1039  static void
1040  lineno_setter(val, id, var)
1041      VALUE val;
1042      ID id;
1043      VALUE *var;
1044  {
1045      gets_lineno = NUM2INT(val);
1046      *var = INT2FIX(gets_lineno);
1047  }
1048  
1049  static VALUE
1050  argf_set_lineno(argf, val)
1051      VALUE argf, val;
1052  {
1053      gets_lineno = NUM2INT(val);
1054      lineno = INT2FIX(gets_lineno);
1055      return Qnil;
1056  }
1057  
1058  static VALUE
1059  argf_lineno()
1060  {
1061      return lineno;
1062  }
1063  
1064  static VALUE
1065  rb_io_readline(argc, argv, io)
1066      int argc;
1067      VALUE *argv;
1068      VALUE io;
1069  {
1070      VALUE line = rb_io_gets_m(argc, argv, io);
1071  
1072      if (NIL_P(line)) {
1073          rb_eof_error();
1074      }
1075      return line;
1076  }
1077  
1078  static VALUE
1079  rb_io_readlines(argc, argv, io)
1080      int argc;
1081      VALUE *argv;
1082      VALUE io;
1083  {
1084      VALUE line, ary;
1085      VALUE rs;
1086      OpenFile *fptr;
1087  
1088      if (argc == 0) {
1089          rs = rb_rs;
1090      }
1091      else {
1092          rb_scan_args(argc, argv, "1", &rs);
1093      }
1094      GetOpenFile(io, fptr);
1095      rb_io_check_readable(fptr);
1096      ary = rb_ary_new();
1097      while (!NIL_P(line = rb_io_getline(rs, fptr))) {
1098          rb_ary_push(ary, line);
1099      }
1100      return ary;
1101  }
1102  
1103  static VALUE
1104  rb_io_each_line(argc, argv, io)
1105      int argc;
1106      VALUE *argv;
1107      VALUE io;
1108  {
1109      VALUE str;
1110      OpenFile *fptr;
1111      VALUE rs;
1112  
1113      if (argc == 0) {
1114          rs = rb_rs;
1115      }
1116      else {
1117          rb_scan_args(argc, argv, "1", &rs);
1118      }
1119      GetOpenFile(io, fptr);
1120      rb_io_check_readable(fptr);
1121      while (!NIL_P(str = rb_io_getline(rs, fptr))) {
1122          rb_yield(str);
1123      }
1124      return io;
1125  }
1126  
1127  static VALUE
1128  rb_io_each_byte(io)
1129      VALUE io;
1130  {
1131      OpenFile *fptr;
1132      FILE *f;
1133      int c;
1134  
1135      GetOpenFile(io, fptr);
1136      rb_io_check_readable(fptr);
1137      f = fptr->f;
1138  
1139      for (;;) {
1140          READ_CHECK(f);
1141          TRAP_BEG;
1142          c = getc(f);
1143          TRAP_END;
1144          if (c == EOF) {
1145              if (ferror(f)) {
1146                  io_read_retryable(f, fptr->path);
1147                  continue;
1148              }
1149              break;
1150          }
1151          rb_yield(INT2FIX(c & 0xff));
1152      }
1153      if (ferror(f)) rb_sys_fail(fptr->path);
1154      return io;
1155  }
1156  
1157  VALUE
1158  rb_io_getc(io)
1159      VALUE io;
1160  {
1161      OpenFile *fptr;
1162      FILE *f;
1163      int c;
1164  
1165      GetOpenFile(io, fptr);
1166      rb_io_check_readable(fptr);
1167      f = fptr->f;
1168  
1169    retry:
1170      READ_CHECK(f);
1171      TRAP_BEG;
1172      c = getc(f);
1173      TRAP_END;
1174  
1175      if (c == EOF) {
1176          if (ferror(f)) {
1177              io_read_retryable(f, fptr->path);
1178              goto retry;
1179          }
1180          return Qnil;
1181      }
1182      return INT2FIX(c & 0xff);
1183  }
1184  
1185  int
1186  rb_getc(f)
1187      FILE *f;
1188  {
1189      int c;
1190  
1191      if (!READ_DATA_PENDING(f)) {
1192          rb_thread_wait_fd(fileno(f));
1193      }
1194      TRAP_BEG;
1195      c = getc(f);
1196      TRAP_END;
1197  
1198      return c;
1199  }
1200  
1201  static VALUE
1202  rb_io_readchar(io)
1203      VALUE io;
1204  {
1205      VALUE c = rb_io_getc(io);
1206  
1207      if (NIL_P(c)) {
1208          rb_eof_error();
1209      }
1210      return c;
1211  }
1212  
1213  VALUE
1214  rb_io_ungetc(io, c)
1215      VALUE io, c;
1216  {
1217      OpenFile *fptr;
1218      int cc = NUM2INT(c);
1219  
1220      GetOpenFile(io, fptr);
1221      rb_io_check_readable(fptr);
1222  
1223      if (ungetc(cc, fptr->f) == EOF && cc != EOF)
1224          rb_sys_fail(fptr->path);
1225      return Qnil;
1226  }
1227  
1228  static VALUE
1229  rb_io_isatty(io)
1230      VALUE io;
1231  {
1232      OpenFile *fptr;
1233  
1234      GetOpenFile(io, fptr);
1235      if (isatty(fileno(fptr->f)) == 0)
1236          return Qfalse;
1237      return Qtrue;
1238  }
1239  
1240  static void
1241  fptr_finalize(fptr, fin)
1242      OpenFile *fptr;
1243      int fin;
1244  {
1245      int n1 = 0, n2 = 0, e = 0, f1, f2 = -1;
1246  
1247      if (fptr->f2) {
1248          f2 = fileno(fptr->f2);
1249          n2 = fclose(fptr->f2);
1250          fptr->f2 = 0;
1251          if (n2 < 0) e = errno;
1252      }
1253      if (fptr->f) {
1254          f1 = fileno(fptr->f);
1255          n1 = fclose(fptr->f);
1256          fptr->f = 0;
1257          if (n1 < 0 && errno == EBADF) {
1258              if (f1 == f2 || !(fptr->mode & FMODE_WBUF)) {
1259                  n1 = 0;
1260              }
1261          }
1262      }
1263      if (!fin && (n1 < 0 || n2 < 0)) {
1264          if (n1 == 0) errno = e;
1265          rb_sys_fail(fptr->path);
1266      }
1267  }
1268  
1269  static void
1270  rb_io_fptr_cleanup(fptr, fin)
1271      OpenFile *fptr;
1272      int fin;
1273  {
1274      if (fptr->finalize) {
1275          (*fptr->finalize)(fptr);
1276      }
1277      else {
1278          fptr_finalize(fptr, fin);
1279      }
1280  
1281      if (fptr->path) {
1282          free(fptr->path);
1283          fptr->path = 0;
1284      }
1285  }
1286  
1287  void
1288  rb_io_fptr_finalize(fptr)
1289      OpenFile *fptr;
1290  {
1291      if (!fptr) return;
1292      if (!fptr->f && !fptr->f2) return;
1293      if (fileno(fptr->f) < 3) return;
1294  
1295      rb_io_fptr_cleanup(fptr, Qtrue);
1296  }
1297  
1298  VALUE
1299  rb_io_close(io)
1300      VALUE io;
1301  {
1302      OpenFile *fptr;
1303      int fd;
1304  
1305      fptr = RFILE(io)->fptr;
1306      if (!fptr) return Qnil;
1307      if (!fptr->f && !fptr->f2) return Qnil;
1308  
1309      fd = fileno(fptr->f);
1310      rb_io_fptr_cleanup(fptr, Qfalse);
1311      rb_thread_fd_close(fd);
1312  
1313      if (fptr->pid) {
1314          rb_syswait(fptr->pid);
1315          fptr->pid = 0;
1316      }
1317  
1318      return Qnil;
1319  }
1320  
1321  static VALUE
1322  rb_io_close_m(io)
1323      VALUE io;
1324  {
1325      if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
1326          rb_raise(rb_eSecurityError, "Insecure: can't close");
1327      }
1328      rb_io_check_closed(RFILE(io)->fptr);
1329      rb_io_close(io);
1330      return Qnil;
1331  }
1332  
1333  static VALUE
1334  rb_io_closed(io)
1335      VALUE io;
1336  {
1337      OpenFile *fptr;
1338  
1339      fptr = RFILE(io)->fptr;
1340      return (fptr->f || fptr->f2)?Qfalse:Qtrue;
1341  }
1342  
1343  static VALUE
1344  rb_io_close_read(io)
1345      VALUE io;
1346  {
1347      OpenFile *fptr;
1348      int n;
1349  
1350      if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
1351          rb_raise(rb_eSecurityError, "Insecure: can't close");
1352      }
1353      GetOpenFile(io, fptr);
1354      if (fptr->f2 == 0 && (fptr->mode & FMODE_WRITABLE)) {
1355          rb_raise(rb_eIOError, "closing non-duplex IO for reading");
1356      }
1357      if (fptr->f2 == 0) {
1358          return rb_io_close(io);
1359      }
1360      n = fclose(fptr->f);
1361      fptr->mode &= ~FMODE_READABLE;
1362      fptr->f = fptr->f2;
1363      fptr->f2 = 0;
1364      if (n != 0) rb_sys_fail(fptr->path);
1365  
1366      return Qnil;
1367  }
1368  
1369  static VALUE
1370  rb_io_close_write(io)
1371      VALUE io;
1372  {
1373      OpenFile *fptr;
1374      int n;
1375  
1376      if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
1377          rb_raise(rb_eSecurityError, "Insecure: can't close");
1378      }
1379      GetOpenFile(io, fptr);
1380      if (fptr->f2 == 0 && (fptr->mode & FMODE_READABLE)) {
1381          rb_raise(rb_eIOError, "closing non-duplex IO for writing");
1382      }
1383      if (fptr->f2 == 0) {
1384          return rb_io_close(io);
1385      }
1386      n = fclose(fptr->f2);
1387      fptr->f2 = 0;
1388      fptr->mode &= ~FMODE_WRITABLE;
1389      if (n != 0) rb_sys_fail(fptr->path);
1390  
1391      return Qnil;
1392  }
1393  
1394  static VALUE
1395  rb_io_sysseek(argc, argv, io)
1396      int argc;
1397      VALUE *argv;
1398      VALUE io;
1399  {
1400      VALUE offset, ptrname;
1401      int whence = SEEK_SET;
1402      OpenFile *fptr;
1403      off_t pos;
1404  
1405      if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
1406          whence = NUM2INT(ptrname);
1407      }
1408  
1409      GetOpenFile(io, fptr);
1410      if ((fptr->mode & FMODE_READABLE) && READ_DATA_PENDING(fptr->f)) {
1411          rb_raise(rb_eIOError, "sysseek for buffered IO");
1412      }
1413      if ((fptr->mode & FMODE_WRITABLE) && (fptr->mode & FMODE_WBUF)) {
1414          rb_warn("sysseek for buffered IO");
1415      }
1416      pos = lseek(fileno(fptr->f), NUM2OFFT(offset), whence);
1417      if (pos == -1) rb_sys_fail(fptr->path);
1418      clearerr(fptr->f);
1419  
1420      return OFFT2NUM(pos);
1421  }
1422  
1423  static VALUE
1424  rb_io_syswrite(io, str)
1425      VALUE io, str;
1426  {
1427      OpenFile *fptr;
1428      FILE *f;
1429      long n;
1430  
1431      rb_secure(4);
1432      if (TYPE(str) != T_STRING)
1433          str = rb_obj_as_string(str);
1434  
1435      GetOpenFile(io, fptr);
1436      rb_io_check_writable(fptr);
1437      f = GetWriteFile(fptr);
1438  
1439      if (fptr->mode & FMODE_WBUF) {
1440          rb_warn("syswrite for buffered IO");
1441      }
1442      if (!rb_thread_fd_writable(fileno(f))) {
1443          rb_io_check_closed(fptr);
1444      }
1445      n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len);
1446  
1447      if (n == -1) rb_sys_fail(fptr->path);
1448  
1449      return LONG2FIX(n);
1450  }
1451  
1452  static VALUE
1453  rb_io_sysread(io, len)
1454      VALUE io, len;
1455  {
1456      OpenFile *fptr;
1457      long n, ilen;
1458      VALUE str;
1459  
1460      ilen = NUM2LONG(len);
1461      GetOpenFile(io, fptr);
1462      rb_io_check_readable(fptr);
1463  
1464      if (READ_DATA_PENDING(fptr->f)) {
1465          rb_raise(rb_eIOError, "sysread for buffered IO");
1466      }
1467      str = rb_str_new(0, ilen);
1468  
1469      n = fileno(fptr->f);
1470      rb_thread_wait_fd(fileno(fptr->f));
1471      TRAP_BEG;
1472      n = read(fileno(fptr->f), RSTRING(str)->ptr, RSTRING(str)->len);
1473      TRAP_END;
1474  
1475      if (n == -1) rb_sys_fail(fptr->path);
1476      if (n == 0 && ilen > 0) {
1477          rb_eof_error();
1478      }
1479  
1480      RSTRING(str)->len = n;
1481      RSTRING(str)->ptr[n] = '\0';
1482      OBJ_TAINT(str);
1483  
1484      return str;
1485  }
1486  
1487  VALUE
1488  rb_io_binmode(io)
1489      VALUE io;
1490  {
1491  #if defined(NT) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__)
1492      OpenFile *fptr;
1493  
1494      GetOpenFile(io, fptr);
1495  #ifdef __human68k__
1496      if (fptr->f)
1497          fmode(fptr->f, _IOBIN);
1498      if (fptr->f2)
1499          fmode(fptr->f2, _IOBIN);
1500  #else
1501      if (fptr->f && setmode(fileno(fptr->f), O_BINARY) == -1)
1502          rb_sys_fail(fptr->path);
1503      if (fptr->f2 && setmode(fileno(fptr->f2), O_BINARY) == -1)
1504          rb_sys_fail(fptr->path);
1505  #endif
1506  
1507      fptr->mode |= FMODE_BINMODE;
1508  #endif
1509      return io;
1510  }
1511  
1512  int
1513  rb_io_mode_flags(mode)
1514      const char *mode;
1515  {
1516      int flags = 0;
1517      const char *m = mode;
1518  
1519      switch (*m++) {
1520        case 'r':
1521          flags |= FMODE_READABLE;
1522          break;
1523        case 'w':
1524          flags |= FMODE_WRITABLE;
1525          break;
1526        case 'a':
1527          flags |= FMODE_WRITABLE;
1528          break;
1529        default:
1530        error:
1531          rb_raise(rb_eArgError, "illegal access mode %s", mode);
1532      }
1533  
1534      while (*m) {
1535          switch (*m++) {
1536          case 'b':
1537              flags |= FMODE_BINMODE;
1538              break;
1539          case '+':
1540              flags |= FMODE_READWRITE;
1541              break;
1542          default:
1543              goto error;
1544          }
1545      }
1546  
1547      return flags;
1548  }
1549  
1550  static int
1551  rb_io_modenum_flags(mode)
1552      int mode;
1553  {
1554      int flags = 0;
1555  
1556      switch (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
1557        case O_RDONLY:
1558          flags = FMODE_READABLE;
1559          break;
1560        case O_WRONLY:
1561          flags = FMODE_WRITABLE;
1562          break;
1563        case O_RDWR:
1564          flags = FMODE_WRITABLE|FMODE_READABLE;
1565          break;
1566      }
1567  
1568  #ifdef O_BINARY
1569      if (mode & O_BINARY) {
1570          flags |= FMODE_BINMODE;
1571      }
1572  #endif
1573  
1574      return flags;
1575  }
1576  
1577  static int
1578  rb_io_mode_modenum(mode)
1579      const char *mode;
1580  {
1581      int flags = 0;
1582      const char *m = mode;
1583  
1584      switch (*m++) {
1585        case 'r':
1586          flags |= O_RDONLY;
1587          break;
1588        case 'w':
1589          flags |= O_WRONLY | O_CREAT | O_TRUNC;
1590          break;
1591        case 'a':
1592          flags |= O_WRONLY | O_CREAT | O_APPEND;
1593          break;
1594        default:
1595        error:
1596          rb_raise(rb_eArgError, "illegal access mode %s", mode);
1597      }
1598  
1599      while (*m) {
1600          switch (*m++) {
1601          case 'b':
1602  #ifdef O_BINARY
1603              flags |= O_BINARY;
1604  #endif
1605              break;
1606          case '+':
1607              flags |= O_RDWR;
1608              break;
1609          default:
1610              goto error;
1611          }
1612      }
1613  
1614      return flags;
1615  }
1616  
1617  static char*
1618  rb_io_modenum_mode(flags, mode)
1619      int flags;
1620      char *mode;
1621  {
1622      char *p = mode;
1623  
1624      switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
1625        case O_RDONLY:
1626          *p++ = 'r';
1627          break;
1628        case O_WRONLY:
1629          *p++ = 'w';
1630          break;
1631        case O_RDWR:
1632          *p++ = 'r';
1633          *p++ = '+';
1634          break;
1635      }
1636      *p++ = '\0';
1637  #ifdef O_BINARY
1638      if (flags & O_BINARY) {
1639          if (mode[1] == '+') {
1640              mode[1] = 'b'; mode[2] = '+'; mode[3] = '\0';
1641          }
1642          else {
1643              mode[1] = 'b'; mode[2] = '\0';
1644          }
1645      }
1646  #endif
1647      return mode;
1648  }
1649  
1650  static int
1651  rb_sysopen(fname, flags, mode)
1652      char *fname;
1653      int flags;
1654      unsigned int mode;
1655  {
1656      int fd;
1657  
1658      fd = open(fname, flags, mode);
1659      if (fd < 0) {
1660          if (errno == EMFILE || errno == ENFILE) {
1661              rb_gc();
1662              fd = open(fname, flags, mode);
1663          }
1664          if (fd < 0) {
1665              rb_sys_fail(fname);
1666          }
1667      }
1668      return fd;
1669  }
1670  
1671  FILE *
1672  rb_fopen(fname, mode)
1673      const char *fname;
1674      const char *mode;
1675  {
1676      FILE *file;
1677  
1678      file = fopen(fname, mode);
1679      if (!file) {
1680          if (errno == EMFILE || errno == ENFILE) {
1681              rb_gc();
1682              file = fopen(fname, mode);
1683          }
1684          if (!file) {
1685              rb_sys_fail(fname);
1686          }
1687      }
1688  #ifdef USE_SETVBUF
1689      if (setvbuf(file, NULL, _IOFBF, 0) != 0)
1690          rb_warn("setvbuf() can't be honered for %s", fname);
1691  #endif
1692  #ifdef __human68k__
1693      fmode(file, _IOTEXT);
1694  #endif
1695      return file;
1696  }
1697  
1698  FILE *
1699  rb_fdopen(fd, mode)
1700      int fd;
1701      const char *mode;
1702  {
1703      FILE *file;
1704  
1705      file = fdopen(fd, mode);
1706      if (!file) {
1707          if (errno == EMFILE || errno == ENFILE) {
1708              rb_gc();
1709              file = fdopen(fd, mode);
1710          }
1711          if (!file) {
1712              rb_sys_fail(0);
1713          }
1714      }
1715  
1716  #ifdef USE_SETVBUF
1717      if (setvbuf(file, NULL, _IOFBF, 0) != 0)
1718          rb_warn("setvbuf() can't be honered (fd=%d)", fd);
1719  #endif
1720      return file;
1721  }
1722  
1723  static VALUE
1724  rb_file_open_internal(io, fname, mode)
1725      VALUE io;
1726      const char *fname, *mode;
1727  {
1728      OpenFile *fptr;
1729  
1730      MakeOpenFile(io, fptr);
1731  
1732      fptr->mode = rb_io_mode_flags(mode);
1733      fptr->f = rb_fopen(fname, mode);
1734      fptr->path = strdup(fname);
1735  
1736      return io;
1737  }
1738  
1739  VALUE
1740  rb_file_open(fname, mode)
1741      const char *fname, *mode;
1742  {
1743      VALUE io = rb_obj_alloc(rb_cFile);
1744  
1745      return rb_file_open_internal(io, fname, mode);
1746  }
1747  
1748  static VALUE
1749  rb_file_sysopen_internal(io, fname, flags, mode)
1750      VALUE io;
1751      char *fname;
1752      int flags, mode;
1753  {
1754      OpenFile *fptr;
1755      int fd;
1756      char *m;
1757      char mbuf[4];
1758  
1759      MakeOpenFile(io, fptr);
1760  
1761      fd = rb_sysopen(fname, flags, mode);
1762      m = rb_io_modenum_mode(flags, mbuf);
1763      fptr->mode = rb_io_modenum_flags(flags);
1764      fptr->f = rb_fdopen(fd, m);
1765      fptr->path = strdup(fname);
1766  
1767      return io;
1768  }
1769  
1770  VALUE
1771  rb_file_sysopen(fname, flags, mode)
1772      const char *fname;
1773      int flags, mode;
1774  {
1775      VALUE io = rb_obj_alloc(rb_cFile);
1776  
1777      return rb_file_sysopen_internal(io, fname, flags, mode);
1778  }
1779  
1780  #if defined (NT) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__VMS)
1781  static struct pipe_list {
1782      OpenFile *fptr;
1783      struct pipe_list *next;
1784  } *pipe_list;
1785  
1786  static void
1787  pipe_add_fptr(fptr)
1788      OpenFile *fptr;
1789  {
1790      struct pipe_list *list;
1791  
1792      list = ALLOC(struct pipe_list);
1793      list->fptr = fptr;
1794      list->next = pipe_list;
1795      pipe_list = list;
1796  }
1797  
1798  static void
1799  pipe_del_fptr(fptr)
1800      OpenFile *fptr;
1801  {
1802      struct pipe_list *list = pipe_list;
1803      struct pipe_list *tmp;
1804  
1805      if (list->fptr == fptr) {
1806          pipe_list = list->next;
1807          free(list);
1808          return;
1809      }
1810  
1811      while (list->next) {
1812          if (list->next->fptr == fptr) {
1813              tmp = list->next;
1814              list->next = list->next->next;
1815              free(tmp);
1816              return;
1817          }
1818          list = list->next;
1819      }
1820  }
1821  
1822  #if defined (NT) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__VMS)
1823  static void
1824  pipe_atexit _((void))
1825  {
1826      struct pipe_list *list = pipe_list;
1827      struct pipe_list *tmp;
1828  
1829      while (list) {
1830          tmp = list->next;
1831          rb_io_fptr_finalize(list->fptr);
1832          list = tmp;
1833      }
1834  }
1835  #endif
1836  
1837  static void pipe_finalize _((OpenFile *fptr));
1838  
1839  static void
1840  pipe_finalize(fptr)
1841      OpenFile *fptr;
1842  {
1843  #if !defined (__CYGWIN__) && !defined(NT)
1844      extern VALUE rb_last_status;
1845      int status;
1846      if (fptr->f) {
1847          status = pclose(fptr->f);
1848      }
1849      if (fptr->f2) {
1850          status = pclose(fptr->f2);
1851      }
1852      fptr->f = fptr->f2 = 0;
1853  #if defined DJGPP
1854      status <<= 8;
1855  #endif
1856      rb_last_status = INT2FIX(status);
1857  #else
1858      fptr_finalize(fptr, Qtrue);
1859  #endif
1860      pipe_del_fptr(fptr);
1861  }
1862  #endif
1863  
1864  void
1865  rb_io_synchronized(fptr)
1866      OpenFile *fptr;
1867  {
1868      fptr->mode |= FMODE_SYNC;
1869  }
1870  
1871  void
1872  rb_io_unbuffered(fptr)
1873      OpenFile *fptr;
1874  {
1875      rb_io_synchronized(fptr);
1876  }
1877  
1878  static VALUE
1879  pipe_open(pname, mode)
1880      char *pname, *mode;
1881  {
1882      int modef = rb_io_mode_flags(mode);
1883      OpenFile *fptr;
1884  
1885  #if defined(DJGPP) || defined(__human68k__) || defined(__VMS)
1886      FILE *f = popen(pname, mode);
1887  
1888      if (!f) rb_sys_fail(pname);
1889      else {
1890          VALUE port = rb_obj_alloc(rb_cIO);
1891  
1892          MakeOpenFile(port, fptr);
1893          fptr->finalize = pipe_finalize;
1894          fptr->mode = modef;
1895  
1896          pipe_add_fptr(fptr);
1897          if (modef & FMODE_READABLE) fptr->f  = f;
1898          if (modef & FMODE_WRITABLE) {
1899              if (fptr->f) fptr->f2 = f;
1900              else fptr->f = f;
1901              rb_io_synchronized(fptr);
1902          }
1903          return (VALUE)port;
1904      }
1905  #else
1906  #if defined(NT)
1907      int pid;
1908      FILE *fpr, *fpw;
1909  
1910  retry:
1911      pid = pipe_exec(pname, rb_io_mode_modenum(mode), &fpr, &fpw);
1912      if (pid == -1) {            /* exec failed */
1913          if (errno == EAGAIN) {
1914              rb_thread_sleep(1);
1915              goto retry;
1916          }
1917          rb_sys_fail(pname);
1918      }
1919      else {
1920          VALUE port = rb_obj_alloc(rb_cIO);
1921  
1922          MakeOpenFile(port, fptr);
1923          fptr->mode = modef;
1924          fptr->mode |= FMODE_SYNC;
1925          fptr->pid = pid;
1926  
1927          if (modef & FMODE_READABLE) {
1928              fptr->f = fpr;
1929          }
1930          if (modef & FMODE_WRITABLE) {
1931              if (fptr->f) fptr->f2 = fpw;
1932              else fptr->f = fpw;
1933          }
1934          fptr->finalize = pipe_finalize;
1935          pipe_add_fptr(fptr);
1936          return (VALUE)port;
1937      }
1938  #else
1939      int pid, pr[2], pw[2];
1940      volatile int doexec;
1941  
1942      if (((modef & FMODE_READABLE) && pipe(pr) == -1) ||
1943          ((modef & FMODE_WRITABLE) && pipe(pw) == -1))
1944          rb_sys_fail(pname);
1945  
1946      doexec = (strcmp("-", pname) != 0);
1947      if (!doexec) {
1948          fflush(stdin);          /* is it really needed? */
1949          fflush(stdout);
1950          fflush(stderr);
1951      }
1952  
1953    retry:
1954      switch ((pid = fork())) {
1955        case 0:                   /* child */
1956          if (modef & FMODE_READABLE) {
1957              close(pr[0]);
1958              if (pr[1] != 1) {
1959                  dup2(pr[1], 1);
1960                  close(pr[1]);
1961              }
1962          }
1963          if (modef & FMODE_WRITABLE) {
1964              close(pw[1]);
1965              if (pw[0] != 0) {
1966                  dup2(pw[0], 0);
1967                  close(pw[0]);
1968              }
1969          }
1970  
1971          if (doexec) {
1972              int fd;
1973  
1974              for (fd = 3; fd < NOFILE; fd++)
1975                  close(fd);
1976              rb_proc_exec(pname);
1977              fprintf(stderr, "%s:%d: command not found: %s\n",
1978                      ruby_sourcefile, ruby_sourceline, pname);
1979              _exit(127);
1980          }
1981          rb_io_synchronized(RFILE(orig_stdout)->fptr);
1982          rb_io_synchronized(RFILE(orig_stderr)->fptr);
1983          return Qnil;
1984  
1985        case -1:                  /* fork failed */
1986          if (errno == EAGAIN) {
1987              rb_thread_sleep(1);
1988              goto retry;
1989          }
1990          close(pr[0]); close(pw[1]);
1991          rb_sys_fail(pname);
1992          break;
1993  
1994        default:                  /* parent */
1995          if (pid < 0) rb_sys_fail(pname);
1996          else {
1997              VALUE port = rb_obj_alloc(rb_cIO);
1998  
1999              MakeOpenFile(port, fptr);
2000              fptr->mode = modef;
2001              fptr->mode |= FMODE_SYNC;
2002              fptr->pid = pid;
2003  
2004              if (modef & FMODE_READABLE) {
2005                  close(pr[1]);
2006                  fptr->f  = rb_fdopen(pr[0], "r");
2007              }
2008              if (modef & FMODE_WRITABLE) {
2009                  FILE *f = rb_fdopen(pw[1], "w");
2010  
2011                  close(pw[0]);
2012                  if (fptr->f) fptr->f2 = f;
2013                  else fptr->f = f;
2014              }
2015  #if defined (__CYGWIN__)
2016              fptr->finalize = pipe_finalize;
2017              pipe_add_fptr(fptr);
2018  #endif
2019              return port;
2020          }
2021      }
2022  #endif
2023  #endif
2024  }
2025  
2026  static VALUE
2027  rb_io_popen(str, argc, argv, klass)
2028      char *str;
2029      int argc;
2030      VALUE *argv;
2031      VALUE klass;
2032  {
2033      char *mode;
2034      VALUE pname, pmode, port;
2035      char mbuf[4];
2036  
2037      if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) {
2038          mode = "r";
2039      }
2040      else if (FIXNUM_P(pmode)) {
2041          mode = rb_io_modenum_mode(FIX2INT(pmode), mbuf);
2042      }
2043      else {
2044          mode = StringValuePtr(pmode);
2045      }
2046      SafeStringValue(pname);
2047      port = pipe_open(str, mode);
2048      if (NIL_P(port)) {
2049          /* child */
2050          if (rb_block_given_p()) {
2051              rb_yield(Qnil);
2052              fflush(stdout);
2053              fflush(stderr);
2054              _exit(0);
2055          }
2056          return Qnil;
2057      }
2058      RBASIC(port)->klass = klass;
2059      if (rb_block_given_p()) {
2060          return rb_ensure(rb_yield, port, rb_io_close, port);
2061      }
2062      return port;
2063  }
2064  
2065  static VALUE
2066  rb_io_s_popen(argc, argv, klass)
2067      int argc;
2068      VALUE *argv;
2069      VALUE klass;
2070  {
2071      char *str = 0;
2072  
2073      if (argc >= 1) {
2074          str = StringValuePtr(argv[0]);
2075      }
2076      return rb_io_popen(str, argc, argv, klass);
2077  }
2078  
2079  static VALUE
2080  rb_open_file(argc, argv, io)
2081      int argc;
2082      VALUE *argv;
2083      VALUE io;
2084  {
2085      VALUE fname, vmode, perm;
2086      char *path, *mode;
2087      int flags, fmode;
2088  
2089      rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
2090      SafeStringValue(fname);
2091      path = RSTRING(fname)->ptr;
2092  
2093      if (FIXNUM_P(vmode) || !NIL_P(perm)) {
2094          flags = FIXNUM_P(vmode) ? NUM2INT(vmode) : rb_io_mode_modenum(StringValuePtr(vmode));
2095          fmode = NIL_P(perm) ? 0666 :  NUM2INT(perm);
2096  
2097          rb_file_sysopen_internal(io, path, flags, fmode);
2098      }
2099      else {
2100          mode = NIL_P(vmode) ? "r" : StringValuePtr(vmode);
2101          rb_file_open_internal(io, RSTRING(fname)->ptr, mode);
2102      }
2103      return io;
2104  }
2105  
2106  static VALUE
2107  rb_io_s_open(argc, argv, klass)
2108      int argc;
2109      VALUE *argv;
2110      VALUE klass;
2111  {
2112      VALUE io = rb_class_new_instance(argc, argv, klass);
2113  
2114      if (rb_block_given_p()) {
2115          return rb_ensure(rb_yield, io, rb_io_close, io);
2116      }
2117  
2118      return io;
2119  }
2120  
2121  static VALUE
2122  rb_io_s_sysopen(argc, argv)
2123      int argc;
2124      VALUE *argv;
2125  {
2126      VALUE fname, vmode, perm;
2127      int flags, fmode, fd;
2128  
2129      rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
2130      SafeStringValue(fname);
2131  
2132      if (NIL_P(vmode)) flags = O_RDONLY;
2133      else if (FIXNUM_P(vmode)) flags = NUM2INT(vmode);
2134      else {
2135          flags = rb_io_mode_modenum(StringValuePtr(vmode));
2136      }
2137      if (NIL_P(perm)) fmode = 0666;
2138      else             fmode = NUM2INT(perm);
2139  
2140      fd = rb_sysopen(RSTRING(fname)->ptr, flags, fmode);
2141      return INT2NUM(fd);
2142  }
2143  
2144  static VALUE
2145  rb_f_open(argc, argv)
2146      int argc;
2147      VALUE *argv;
2148  {
2149      if (argc >= 1) {
2150          char *str = StringValuePtr(argv[0]);
2151  
2152          if (str[0] == '|') {
2153              return rb_io_popen(str+1, argc, argv, rb_cIO);
2154          }
2155      }
2156      return rb_io_s_open(argc, argv, rb_cFile);
2157  }
2158  
2159  static VALUE
2160  rb_io_open(fname, mode)
2161      char *fname, *mode;
2162  {
2163      if (fname[0] == '|') {
2164          return pipe_open(fname+1, mode);
2165      }
2166      else {
2167          return rb_file_open(fname, mode);
2168      }
2169  }
2170  
2171  static VALUE
2172  rb_io_get_io(io)
2173      VALUE io;
2174  {
2175      return rb_convert_type(io, T_FILE, "IO", "to_io");
2176  }
2177  
2178  static char*
2179  rb_io_mode_string(fptr)
2180      OpenFile *fptr;
2181  {
2182      switch (fptr->mode & FMODE_READWRITE) {
2183        case FMODE_READABLE:
2184        default:
2185          return "r";
2186        case FMODE_WRITABLE:
2187          return "w";
2188        case FMODE_READWRITE:
2189          return "r+";
2190      }
2191  }
2192  
2193  static VALUE
2194  io_reopen(io, nfile)
2195      VALUE io, nfile;
2196  {
2197      OpenFile *fptr, *orig;
2198      char *mode;
2199      int fd;
2200      off_t pos = 0;
2201  
2202      nfile = rb_io_get_io(nfile);
2203      if (rb_safe_level() >= 4 && (!OBJ_TAINTED(io) || !OBJ_TAINTED(nfile))) {
2204          rb_raise(rb_eSecurityError, "Insecure: can't reopen");
2205      }
2206      GetOpenFile(io, fptr);
2207      GetOpenFile(nfile, orig);
2208  
2209      if (fptr == orig) return io;
2210      if (orig->mode & FMODE_READABLE) {
2211          pos = ftello(orig->f);
2212      }
2213      if (orig->f2) {
2214          io_fflush(orig->f2, orig);
2215      }
2216      else if (orig->mode & FMODE_WRITABLE) {
2217          io_fflush(orig->f, orig);
2218      }
2219      rb_thread_fd_close(fileno(fptr->f));
2220  
2221      /* copy OpenFile structure */
2222      fptr->mode = orig->mode;
2223      fptr->pid = orig->pid;
2224      fptr->lineno = orig->lineno;
2225      if (fptr->path) free(fptr->path);
2226      if (orig->path) fptr->path = strdup(orig->path);
2227      else fptr->path = 0;
2228      fptr->finalize = orig->finalize;
2229  
2230      mode = rb_io_mode_string(fptr);
2231      fd = fileno(fptr->f);
2232      if (fd < 3) {
2233          clearerr(fptr->f);
2234          /* need to keep stdio objects */
2235          if (dup2(fileno(orig->f), fd) < 0)
2236              rb_sys_fail(orig->path);
2237      }
2238      else {
2239          fclose(fptr->f);
2240          if (dup2(fileno(orig->f), fd) < 0)
2241              rb_sys_fail(orig->path);
2242          fptr->f = rb_fdopen(fd, mode);
2243      }
2244      if ((orig->mode & FMODE_READABLE) && pos >= 0) {
2245          fseeko(fptr->f, pos, SEEK_SET);
2246          fseeko(orig->f, pos, SEEK_SET);
2247      }
2248  
2249      if (fptr->f2) {
2250          fd = fileno(fptr->f2);
2251          fclose(fptr->f2);
2252          if (orig->f2) {
2253              if (dup2(fileno(orig->f2), fd) < 0)
2254                  rb_sys_fail(orig->path);
2255              fptr->f2 = rb_fdopen(fd, "w");
2256          }
2257          else {
2258              fptr->f2 = 0;
2259          }
2260      }
2261  
2262      if (fptr->mode & FMODE_BINMODE) {
2263          rb_io_binmode(io);
2264      }
2265  
2266      RBASIC(io)->klass = RBASIC(nfile)->klass;
2267      return io;
2268  }
2269  
2270  static VALUE
2271  rb_io_reopen(argc, argv, file)
2272      int argc;
2273      VALUE *argv;
2274      VALUE file;
2275  {
2276      VALUE fname, nmode;
2277      char *mode;
2278      OpenFile *fptr;
2279  
2280      rb_secure(4);
2281      if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
2282          if (TYPE(fname) != T_STRING) { /* fname must be IO */
2283              return io_reopen(file, fname);
2284          }
2285      }
2286  
2287      SafeStringValue(fname);
2288      if (!NIL_P(nmode)) {
2289          mode = StringValuePtr(nmode);
2290      }
2291      else {
2292          mode = "r";
2293      }
2294  
2295      GetOpenFile(file, fptr);
2296      if (fptr->path) {
2297          free(fptr->path);
2298          fptr->path = 0;
2299      }
2300  
2301      fptr->path = strdup(RSTRING(fname)->ptr);
2302      fptr->mode = rb_io_mode_flags(mode);
2303      if (!fptr->f) {
2304          fptr->f = rb_fopen(RSTRING(fname)->ptr, mode);
2305          if (fptr->f2) {
2306              fclose(fptr->f2);
2307              fptr->f2 = 0;
2308          }
2309  
2310          return file;
2311      }
2312  
2313      if (freopen(RSTRING(fname)->ptr, mode, fptr->f) == 0) {
2314          rb_sys_fail(fptr->path);
2315      }
2316  #ifdef USE_SETVBUF
2317      if (setvbuf(fptr->f, NULL, _IOFBF, 0) != 0)
2318          rb_warn("setvbuf() can't be honered for %s", RSTRING(fname)->ptr);
2319  #endif
2320  
2321      if (fptr->f2) {
2322          if (freopen(RSTRING(fname)->ptr, "w", fptr->f2) == 0) {
2323              rb_sys_fail(fptr->path);
2324          }
2325      }
2326  
2327      return file;
2328  }
2329  
2330  static VALUE
2331  rb_io_become(clone, io)
2332      VALUE clone, io;
2333  {
2334      OpenFile *fptr, *orig;
2335      int fd;
2336      char *mode;
2337  
2338      io = rb_io_get_io(io);
2339      if (clone == io) return clone;
2340      GetOpenFile(io, orig);
2341      MakeOpenFile(clone, fptr);
2342  
2343      if (orig->f2) {
2344          io_fflush(orig->f2, orig);
2345      }
2346      else if (orig->mode & FMODE_WRITABLE) {
2347          io_fflush(orig->f, orig);
2348      }
2349  
2350      /* copy OpenFile structure */
2351      fptr->mode = orig->mode;
2352      fptr->pid = orig->pid;
2353      fptr->lineno = orig->lineno;
2354      if (orig->path) fptr->path = strdup(orig->path);
2355      fptr->finalize = orig->finalize;
2356  
2357      switch (fptr->mode & FMODE_READWRITE) {
2358        case FMODE_READABLE:
2359        default:
2360          mode = "r"; break;
2361        case FMODE_WRITABLE:
2362          mode = "w"; break;
2363        case FMODE_READWRITE:
2364          if (orig->f2) mode = "r";
2365          else          mode = "r+";
2366          break;
2367      }
2368      fd = ruby_dup(fileno(orig->f));
2369      fptr->f = rb_fdopen(fd, mode);
2370      if (orig->f2) {
2371          if (fileno(orig->f) != fileno(orig->f2)) {
2372              fd = ruby_dup(fileno(orig->f2));
2373          }
2374          fptr->f2 = rb_fdopen(fd, "w");
2375      }
2376      if (fptr->mode & FMODE_BINMODE) {
2377          rb_io_binmode(clone);
2378      }
2379  
2380      return clone;
2381  }
2382  
2383  VALUE
2384  rb_io_printf(argc, argv, out)
2385      int argc;
2386      VALUE argv[];
2387      VALUE out;
2388  {
2389      rb_io_write(out, rb_f_sprintf(argc, argv));
2390      return Qnil;
2391  }
2392  
2393  static VALUE
2394  rb_f_printf(argc, argv)
2395      int argc;
2396      VALUE argv[];
2397  {
2398      VALUE out;
2399  
2400      if (argc == 0) return Qnil;
2401      if (TYPE(argv[0]) == T_STRING) {
2402          out = rb_defout;
2403      }
2404      else {
2405          out = argv[0];
2406          argv++;
2407          argc--;
2408      }
2409      rb_io_write(out, rb_f_sprintf(argc, argv));
2410  
2411      return Qnil;
2412  }
2413  
2414  VALUE
2415  rb_io_print(argc, argv, out)
2416      int argc;
2417      VALUE *argv;
2418      VALUE out;
2419  {
2420      int i;
2421      VALUE line;
2422  
2423      /* if no argument given, print `$_' */
2424      if (argc == 0) {
2425          argc = 1;
2426          line = rb_lastline_get();
2427          argv = &line;
2428      }
2429      for (i=0; i<argc; i++) {
2430          if (!NIL_P(rb_output_fs) && i>0) {
2431              rb_io_write(out, rb_output_fs);
2432          }
2433          switch (TYPE(argv[i])) {
2434            case T_NIL:
2435              rb_io_write(out, rb_str_new2("nil"));
2436              break;
2437            default:
2438              rb_io_write(out, argv[i]);
2439              break;
2440          }
2441      }
2442      if (!NIL_P(rb_output_rs)) {
2443          rb_io_write(out, rb_output_rs);
2444      }
2445  
2446      return Qnil;
2447  }
2448  
2449  static VALUE
2450  rb_f_print(argc, argv)
2451      int argc;
2452      VALUE *argv;
2453  {
2454      rb_io_print(argc, argv, rb_defout);
2455      return Qnil;
2456  }
2457  
2458  static VALUE
2459  rb_io_putc(io, ch)
2460      VALUE io, ch;
2461  {
2462      char c = NUM2CHR(ch);
2463  
2464      rb_io_write(io, rb_str_new(&c, 1));
2465      return ch;
2466  }
2467  
2468  static VALUE
2469  rb_f_putc(recv, ch)
2470      VALUE recv, ch;
2471  {
2472      return rb_io_putc(rb_defout, ch);
2473  }
2474  
2475  static VALUE
2476  io_puts_ary(ary, out)
2477      VALUE ary, out;
2478  {
2479      VALUE tmp;
2480      long i;
2481  
2482      for (i=0; i<RARRAY(ary)->len; i++) {
2483          tmp = RARRAY(ary)->ptr[i];
2484          if (rb_inspecting_p(tmp)) {
2485              tmp = rb_str_new2("[...]");
2486          }
2487          rb_io_puts(1, &tmp, out);
2488      }
2489      return Qnil;
2490  }
2491  
2492  VALUE
2493  rb_io_puts(argc, argv, out)
2494      int argc;
2495      VALUE *argv;
2496      VALUE out;
2497  {
2498      int i;
2499      VALUE line;
2500  
2501      /* if no argument given, print newline. */
2502      if (argc == 0) {
2503          rb_io_write(out, rb_default_rs);
2504          return Qnil;
2505      }
2506      for (i=0; i<argc; i++) {
2507          if (NIL_P(argv[i])) {
2508              line = rb_str_new2("nil");
2509          }
2510          else {
2511              line = rb_check_convert_type(argv[i], T_ARRAY, "Array", "to_ary");
2512              if (!NIL_P(line)) {
2513                  rb_protect_inspect(io_puts_ary, line, out);
2514                  continue;
2515              }
2516              line = rb_obj_as_string(argv[i]);
2517          }
2518          rb_io_write(out, line);
2519          if (RSTRING(line)->len == 0 ||
2520              RSTRING(line)->ptr[RSTRING(line)->len-1] != '\n') {
2521              rb_io_write(out, rb_default_rs);
2522          }
2523      }
2524  
2525      return Qnil;
2526  }
2527  
2528  static VALUE
2529  rb_f_puts(argc, argv)
2530      int argc;
2531      VALUE *argv;
2532  {
2533      rb_io_puts(argc, argv, rb_defout);
2534      return Qnil;
2535  }
2536  
2537  void
2538  rb_p(obj)                       /* for debug print within C code */
2539      VALUE obj;
2540  {
2541      rb_io_write(rb_defout, rb_obj_as_string(rb_inspect(obj)));
2542      rb_io_write(rb_defout, rb_default_rs);
2543  }
2544  
2545  static VALUE
2546  rb_f_p(argc, argv)
2547      int argc;
2548      VALUE *argv;
2549  {
2550      int i;
2551  
2552      for (i=0; i<argc; i++) {
2553          rb_p(argv[i]);
2554      }
2555      if (TYPE(rb_defout) == T_FILE) {
2556          rb_io_flush(rb_defout);
2557      }
2558      return Qnil;
2559  }
2560  
2561  static VALUE
2562  rb_obj_display(argc, argv, self)
2563      int argc;
2564      VALUE *argv;
2565      VALUE self;
2566  {
2567      VALUE out;
2568  
2569      if (rb_scan_args(argc, argv, "01", &out) == 0) {
2570          out = rb_defout;
2571      }
2572  
2573      rb_io_write(out, self);
2574  
2575      return Qnil;
2576  }
2577  
2578  static void
2579  rb_io_defset(val, id)
2580      VALUE val;
2581      ID id;
2582  {
2583      if (!rb_respond_to(val, id_write)) {
2584          rb_raise(rb_eTypeError, "$> must have write method, %s given",
2585                   rb_class2name(CLASS_OF(val)));
2586      }
2587      rb_defout = val;
2588  }
2589  
2590  static void
2591  set_stdin(val, id, var)
2592      VALUE val;
2593      ID id;
2594      VALUE *var;
2595  {
2596      OpenFile *fptr;
2597  
2598      if (val == *var) return;
2599      if (TYPE(val) != T_FILE) {
2600          *var = val;
2601          return;
2602      }
2603      if (TYPE(*var) != T_FILE) {
2604          *var = orig_stdin;
2605      }
2606  
2607      GetOpenFile(val, fptr);
2608      rb_io_check_readable(fptr);
2609      if (fileno(fptr->f) == 0 && saved_fd[0] != 0) {
2610          dup2(saved_fd[0], 0);
2611          close(saved_fd[0]);
2612          saved_fd[0] = 0;
2613      }
2614      else {
2615          saved_fd[0] = dup(0);
2616          dup2(fileno(fptr->f), 0);
2617      }
2618  
2619      *var = val;
2620  }
2621  
2622  static void
2623  set_outfile(val, var, orig, stdf)
2624      VALUE val;
2625      VALUE *var;
2626      VALUE orig;
2627      FILE *stdf;
2628  {
2629      OpenFile *fptr;
2630      FILE *f;
2631      int fd;
2632  
2633      if (val == *var) return;
2634  
2635      if (TYPE(*var) == T_FILE && !rb_io_closed(*var)) {
2636          rb_io_flush(*var);
2637      }
2638      if (TYPE(val) != T_FILE) {
2639          *var = val;
2640          return;
2641      }
2642      if (TYPE(*var) != T_FILE) {
2643          *var = orig;
2644      }
2645  
2646      GetOpenFile(val, fptr);
2647      rb_io_check_writable(fptr);
2648      f = GetWriteFile(fptr);
2649      fd = fileno(stdf);
2650      if (fileno(fptr->f) == fd && saved_fd[fd] != fd) {
2651          dup2(saved_fd[fd], fd);
2652          close(saved_fd[fd]);
2653          saved_fd[fd] = fd;
2654      }
2655      else {
2656          saved_fd[fd] = dup(fd);
2657          dup2(fileno(fptr->f), fd);
2658      }
2659  
2660      *var = val;
2661  }
2662  
2663  static void
2664  set_stdout(val, id, var)
2665      VALUE val;
2666      ID id;
2667      VALUE *var;
2668  {
2669      set_outfile(val, var, orig_stdout, stdout);
2670  }
2671  
2672  static void
2673  set_stderr(val, id, var)
2674      VALUE val;
2675      ID id;
2676      VALUE *var;
2677  {
2678      set_outfile(val, var, orig_stderr, stderr);
2679  }
2680  
2681  static VALUE
2682  prep_stdio(f, mode, klass)
2683      FILE *f;
2684      int mode;
2685      VALUE klass;
2686  {
2687      OpenFile *fp;
2688      VALUE io = rb_obj_alloc(klass);
2689  
2690      MakeOpenFile(io, fp);
2691      fp->f = f;
2692      fp->mode = mode;
2693  
2694      return io;
2695  }
2696  
2697  static void
2698  prep_path(io, path)
2699      VALUE io;
2700      char *path;
2701  {
2702      OpenFile *fptr;
2703  
2704      GetOpenFile(io, fptr);
2705      if (fptr->path) rb_bug("illegal prep_path() call");
2706      fptr->path = strdup(path);
2707  }
2708  
2709  static VALUE
2710  rb_io_s_alloc(klass)
2711      VALUE klass;
2712  {
2713      NEWOBJ(io, struct RFile);
2714      OBJSETUP(io, klass, T_FILE);
2715  
2716      io->fptr = 0;
2717  
2718      return (VALUE)io;
2719  }
2720  
2721  static VALUE
2722  rb_io_initialize(argc, argv, io)
2723      int argc;
2724      VALUE *argv;
2725      VALUE io;
2726  {
2727      VALUE fnum, mode;
2728      OpenFile *fp;
2729      int fd, flags;
2730      char mbuf[4];
2731  
2732      rb_scan_args(argc, argv, "11", &fnum, &mode);
2733      fd = NUM2INT(fnum);
2734      if (argc == 2) {
2735          SafeStringValue(mode);
2736          flags = rb_io_mode_modenum(RSTRING(mode)->ptr);
2737      }
2738      else {
2739  #if defined(HAVE_FCNTL) && defined(F_GETFL)
2740          flags = fcntl(fd, F_GETFL);
2741  #else
2742          flags = O_RDONLY;
2743  #endif
2744      }
2745      MakeOpenFile(io, fp);
2746      fp->mode = rb_io_modenum_flags(flags);
2747      fp->f = rb_fdopen(fd, rb_io_modenum_mode(flags, mbuf));
2748  
2749      return io;
2750  }
2751  
2752  static VALUE
2753  rb_file_initialize(argc, argv, io)
2754      int argc;
2755      VALUE *argv;
2756      VALUE io;
2757  {
2758      if (RFILE(io)->fptr) {
2759          rb_io_close_m(io);
2760          free(RFILE(io)->fptr);
2761          RFILE(io)->fptr = 0;
2762      }
2763      if (0 < argc && argc < 3) {
2764          VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
2765  
2766          if (!NIL_P(fd)) {
2767              argv[0] = fd;
2768              return rb_io_initialize(argc, argv, io);
2769          }
2770      }
2771      rb_open_file(argc, argv, io);
2772  
2773      return io;
2774  }
2775  
2776  static VALUE
2777  rb_io_s_new(argc, argv, klass)
2778      int argc;
2779      VALUE *argv;
2780      VALUE klass;
2781  {
2782      if (rb_block_given_p()) {
2783          char *cname = rb_class2name(klass);
2784  
2785          rb_warn("%s::new() does not take block; use %s::open() instead",
2786                  cname, cname);
2787      }
2788      return rb_class_new_instance(argc, argv, klass);
2789  }
2790  
2791  static int binmode = 0;
2792  
2793  static VALUE
2794  argf_forward()
2795  {
2796      return rb_funcall3(current_file, ruby_frame->last_func,
2797                         ruby_frame->argc, ruby_frame->argv);
2798  }
2799  
2800  static int
2801  next_argv()
2802  {
2803      extern VALUE rb_argv;
2804      char *fn;
2805  
2806      if (init_p == 0) {
2807          if (RARRAY(rb_argv)->len > 0) {
2808              next_p = 1;
2809          }
2810          else {
2811              next_p = -1;
2812              current_file = rb_stdin;
2813              filename = rb_str_new2("-");
2814          }
2815          init_p = 1;
2816          first_p = 0;
2817          gets_lineno = 0;
2818      }
2819  
2820    retry:
2821      if (next_p == 1) {
2822          next_p = 0;
2823          if (RARRAY(rb_argv)->len > 0) {
2824              filename = rb_ary_shift(rb_argv);
2825              fn = StringValuePtr(filename);
2826              if (strlen(fn) == 1 && fn[0] == '-') {
2827                  current_file = rb_stdin;
2828                  if (ruby_inplace_mode) {
2829                      rb_warn("Can't do inplace edit for stdio");
2830                      rb_defout = rb_stdout;
2831                  }
2832              }
2833              else {
2834                  FILE *fr = rb_fopen(fn, "r");
2835  
2836                  if (ruby_inplace_mode) {
2837                      struct stat st, st2;
2838                      VALUE str;
2839                      FILE *fw;
2840  
2841                      if (TYPE(rb_defout) == T_FILE && rb_defout != rb_stdout) {
2842                          rb_io_close(rb_defout);
2843                      }
2844                      fstat(fileno(fr), &st);
2845                      if (*ruby_inplace_mode) {
2846                          str = rb_str_new2(fn);
2847  #ifdef NO_LONG_FNAME
2848                          ruby_add_suffix(str, ruby_inplace_mode);
2849  #else
2850                          rb_str_cat2(str, ruby_inplace_mode);
2851  #endif
2852  #ifdef NO_SAFE_RENAME
2853                          (void)fclose(fr);
2854                          (void)unlink(RSTRING(str)->ptr);
2855                          (void)rename(fn, RSTRING(str)->ptr);
2856                          fr = rb_fopen(RSTRING(str)->ptr, "r");
2857  #else
2858                          if (rename(fn, RSTRING(str)->ptr) < 0) {
2859                              rb_warn("Can't rename %s to %s: %s, skipping file",
2860                                      fn, RSTRING(str)->ptr, strerror(errno));
2861                              fclose(fr);
2862                              goto retry;
2863                          }
2864  #endif
2865                      }
2866                      else {
2867  #ifdef NO_SAFE_RENAME
2868                          rb_fatal("Can't do inplace edit without backup");
2869  #else
2870                          if (unlink(fn) < 0) {
2871                              rb_warn("Can't remove %s: %s, skipping file",
2872                                      fn, strerror(errno));
2873                              fclose(fr);
2874                              goto retry;
2875                          }
2876  #endif
2877                      }
2878                      fw = rb_fopen(fn, "w");
2879  #ifndef NO_SAFE_RENAME
2880                      fstat(fileno(fw), &st2);
2881  #ifdef HAVE_FCHMOD
2882                      fchmod(fileno(fw), st.st_mode);
2883  #else
2884                      chmod(fn, st.st_mode);
2885  #endif
2886                      if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
2887                          fchown(fileno(fw), st.st_uid, st.st_gid);
2888                      }
2889  #endif
2890                      rb_defout = prep_stdio(fw, FMODE_WRITABLE, rb_cFile);
2891                      prep_path(rb_defout, fn);
2892                  }
2893                  current_file = prep_stdio(fr, FMODE_READABLE, rb_cFile);
2894                  prep_path(current_file, fn);
2895              }
2896              if (binmode) rb_io_binmode(current_file);
2897          }
2898          else {
2899              init_p = 0;
2900              return Qfalse;
2901          }
2902      }
2903      return Qtrue;
2904  }
2905  
2906  static void
2907  any_close(file)
2908      VALUE file;
2909  {
2910      if (TYPE(file) == T_FILE)
2911          rb_io_close(file);
2912      else
2913          rb_funcall3(file, rb_intern("close"), 0, 0);
2914  }
2915  
2916  static VALUE
2917  argf_getline(argc, argv)
2918      int argc;
2919      VALUE *argv;
2920  {
2921      VALUE line;
2922  
2923    retry:
2924      if (!next_argv()) return Qnil;
2925      if (TYPE(current_file) != T_FILE) {
2926          line = rb_funcall3(current_file, rb_intern("gets"), argc, argv);
2927      }
2928      else if (argc == 0 && rb_rs == rb_default_rs) {
2929          line = rb_io_gets(current_file);
2930      }
2931      else {
2932          VALUE rs;
2933          OpenFile *fptr;
2934  
2935          if (argc == 0) {
2936              rs = rb_rs;
2937          }
2938          else {
2939              rb_scan_args(argc, argv, "1", &rs);
2940          }
2941          GetOpenFile(current_file, fptr);
2942          rb_io_check_readable(fptr);
2943          line = rb_io_getline(rs, fptr);
2944      }
2945      if (NIL_P(line) && next_p != -1) {
2946          any_close(current_file);
2947          next_p = 1;
2948          goto retry;
2949      }
2950      gets_lineno++;
2951      lineno = INT2FIX(gets_lineno);
2952  
2953      return line;
2954  }
2955  
2956  static VALUE
2957  rb_f_gets(argc, argv)
2958      int argc;
2959      VALUE *argv;
2960  {
2961      VALUE line = argf_getline(argc, argv);
2962  
2963      rb_lastline_set(line);
2964      return line;
2965  }
2966  
2967  VALUE
2968  rb_gets()
2969  {
2970      VALUE line;
2971  
2972      if (rb_rs != rb_default_rs) {
2973          return rb_f_gets(0, 0);
2974      }
2975  
2976    retry:
2977      if (!next_argv()) return Qnil;
2978      line = rb_io_gets(current_file);
2979      if (NIL_P(line) && next_p != -1) {
2980          any_close(current_file);
2981          next_p = 1;
2982          goto retry;
2983      }
2984      rb_lastline_set(line);
2985      if (!NIL_P(line)) {
2986          gets_lineno++;
2987          lineno = INT2FIX(gets_lineno);
2988      }
2989  
2990      return line;
2991  }
2992  
2993  static VALUE
2994  rb_f_readline(argc, argv)
2995      int argc;
2996      VALUE *argv;
2997  {
2998      VALUE line = rb_f_gets(argc, argv);
2999  
3000      if (NIL_P(line)) {
3001          rb_eof_error();
3002      }
3003  
3004      return line;
3005  }
3006  
3007  static VALUE
3008  rb_f_getc()
3009  {
3010      rb_warn("getc is obsolete; use STDIN.getc instead");
3011      return rb_io_getc(rb_stdin);
3012  }
3013  
3014  static VALUE
3015  rb_f_readlines(argc, argv)
3016      int argc;
3017      VALUE *argv;
3018  {
3019      VALUE line, ary;
3020  
3021      ary = rb_ary_new();
3022      while (!NIL_P(line = argf_getline(argc, argv))) {
3023          rb_ary_push(ary, line);
3024      }
3025  
3026      return ary;
3027  }
3028  
3029  static VALUE
3030  rb_f_backquote(obj, str)
3031      VALUE obj, str;
3032  {
3033      VALUE port, result;
3034      OpenFile *fptr;
3035  
3036      SafeStringValue(str);
3037      port = pipe_open(RSTRING(str)->ptr, "r");
3038      if (NIL_P(port)) return rb_str_new(0,0);
3039  
3040      GetOpenFile(port, fptr);
3041      result = read_all(fptr, remain_size(fptr));
3042  
3043      rb_io_close(port);
3044  
3045      if (NIL_P(result)) return rb_str_new(0,0);
3046      return result;
3047  }
3048  
3049  #ifdef HAVE_SYS_SELECT_H
3050  #include <sys/select.h>
3051  #endif
3052  
3053  static VALUE
3054  rb_f_select(argc, argv, obj)
3055      int argc;
3056      VALUE *argv;
3057      VALUE obj;
3058  {
3059      VALUE read, write, except, timeout, res, list;
3060      fd_set rset, wset, eset, pset;
3061      fd_set *rp, *wp, *ep;
3062      struct timeval *tp, timerec;
3063      OpenFile *fptr;
3064      long i;
3065      int max = 0, n;
3066      int interrupt_flag = 0;
3067      int pending = 0;
3068  
3069      rb_scan_args(argc, argv, "13", &read, &write, &except, &timeout);
3070      if (NIL_P(timeout)) {
3071          tp = 0;
3072      }
3073      else {
3074          timerec = rb_time_interval(timeout);
3075          tp = &timerec;
3076      }
3077  
3078      FD_ZERO(&pset);
3079      if (!NIL_P(read)) {
3080          Check_Type(read, T_ARRAY);
3081          rp = &rset;
3082          FD_ZERO(rp);
3083          for (i=0; i<RARRAY(read)->len; i++) {
3084              GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
3085              FD_SET(fileno(fptr->f), rp);
3086              if (READ_DATA_PENDING(fptr->f)) { /* check for buffered data */
3087                  pending++;
3088                  FD_SET(fileno(fptr->f), &pset);
3089              }
3090              if (max < fileno(fptr->f)) max = fileno(fptr->f);
3091          }
3092          if (pending) {          /* no blocking if there's buffered data */
3093              timerec.tv_sec = timerec.tv_usec = 0;
3094              tp = &timerec;
3095          }
3096      }
3097      else
3098          rp = 0;
3099  
3100      if (!NIL_P(write)) {
3101          Check_Type(write, T_ARRAY);
3102          wp = &wset;
3103          FD_ZERO(wp);
3104          for (i=0; i<RARRAY(write)->len; i++) {
3105              GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
3106              FD_SET(fileno(fptr->f), wp);
3107              if (max < fileno(fptr->f)) max = fileno(fptr->f);
3108              if (fptr->f2) {
3109                  FD_SET(fileno(fptr->f2), wp);
3110                  if (max < fileno(fptr->f2)) max = fileno(fptr->f2);
3111              }
3112          }
3113      }
3114      else
3115          wp = 0;
3116  
3117      if (!NIL_P(except)) {
3118          Check_Type(except, T_ARRAY);
3119          ep = &eset;
3120          FD_ZERO(ep);
3121          for (i=0; i<RARRAY(except)->len; i++) {
3122              GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
3123              FD_SET(fileno(fptr->f), ep);
3124              if (max < fileno(fptr->f)) max = fileno(fptr->f);
3125              if (fptr->f2) {
3126                  FD_SET(fileno(fptr->f2), ep);
3127                  if (max < fileno(fptr->f2)) max = fileno(fptr->f2);
3128              }
3129          }
3130      }
3131      else {
3132          ep = 0;
3133      }
3134  
3135      max++;
3136  
3137      n = rb_thread_select(max, rp, wp, ep, tp);
3138      if (n < 0) {
3139          rb_sys_fail(0);
3140      }
3141      if (!pending && n == 0) return Qnil; /* returns nil on timeout */
3142  
3143      res = rb_ary_new2(3);
3144      rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
3145      rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
3146      rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
3147  
3148      if (interrupt_flag == 0) {
3149          if (rp) {
3150              list = RARRAY(res)->ptr[0];
3151              for (i=0; i< RARRAY(read)->len; i++) {
3152                  GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
3153                  if (FD_ISSET(fileno(fptr->f), rp)
3154                      || FD_ISSET(fileno(fptr->f), &pset)) {
3155                      rb_ary_push(list, RARRAY(read)->ptr[i]);
3156                  }
3157              }
3158          }
3159  
3160          if (wp) {
3161              list = RARRAY(res)->ptr[1];
3162              for (i=0; i< RARRAY(write)->len; i++) {
3163                  GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
3164                  if (FD_ISSET(fileno(fptr->f), wp)) {
3165                      rb_ary_push(list, RARRAY(write)->ptr[i]);
3166                  }
3167                  else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), wp)) {
3168                      rb_ary_push(list, RARRAY(write)->ptr[i]);
3169                  }
3170              }
3171          }
3172  
3173          if (ep) {
3174              list = RARRAY(res)->ptr[2];
3175              for (i=0; i< RARRAY(except)->len; i++) {
3176                  GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
3177                  if (FD_ISSET(fileno(fptr->f), ep)) {
3178                      rb_ary_push(list, RARRAY(except)->ptr[i]);
3179                  }
3180                  else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), ep)) {
3181                      rb_ary_push(list, RARRAY(except)->ptr[i]);
3182                  }
3183              }
3184          }
3185      }
3186  
3187      return res;                 /* returns an empty array on interrupt */
3188  }
3189  
3190  #if !defined(MSDOS) && !defined(__human68k__)
3191  static int
3192  io_cntl(fd, cmd, narg, io_p)
3193      int fd, cmd, io_p;
3194      long narg;
3195  {
3196      int retval;
3197  
3198  #ifdef HAVE_FCNTL
3199      TRAP_BEG;
3200  # if defined(__CYGWIN__)
3201      retval = io_p?ioctl(fd, cmd, (void*)narg):fcntl(fd, cmd, narg);
3202  # else
3203      retval = io_p?ioctl(fd, cmd, narg):fcntl(fd, cmd, narg);
3204  # endif
3205      TRAP_END;
3206  #else
3207      if (!io_p) {
3208          rb_notimplement();
3209      }
3210      TRAP_BEG;
3211      retval = ioctl(fd, cmd, narg);
3212      TRAP_END;
3213  #endif
3214      return retval;
3215  }
3216  #endif
3217  
3218  static VALUE
3219  rb_io_ctl(io, req, arg, io_p)
3220      VALUE io, req, arg;
3221      int io_p;
3222  {
3223  #if !defined(MSDOS) && !defined(__human68k__)
3224      int cmd = NUM2ULONG(req);
3225      OpenFile *fptr;
3226      long len = 0;
3227      long narg = 0;
3228      int retval;
3229  
3230      rb_secure(2);
3231      GetOpenFile(io, fptr);
3232  
3233      if (NIL_P(arg) || arg == Qfalse) {
3234          narg = 0;
3235      }
3236      else if (FIXNUM_P(arg)) {
3237          narg = FIX2LONG(arg);
3238      }
3239      else if (arg == Qtrue) {
3240          narg = 1;
3241      }
3242      else if (rb_obj_is_kind_of(arg, rb_cInteger)) {
3243          narg = NUM2LONG(arg);
3244      }
3245      else {
3246          StringValue(arg);
3247  
3248  #ifdef IOCPARM_MASK
3249  #ifndef IOCPARM_LEN
3250  #define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
3251  #endif
3252  #endif
3253  #ifdef IOCPARM_LEN
3254          len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
3255  #else
3256          len = 256;              /* otherwise guess at what's safe */
3257  #endif
3258          rb_str_modify(arg);
3259  
3260          if (len <= RSTRING(arg)->len) {
3261              len = RSTRING(arg)->len;
3262          }
3263          if (RSTRING(arg)->len < len) {
3264              rb_str_resize(arg, len+1);
3265          }
3266          RSTRING(arg)->ptr[len] = 17;    /* a little sanity check here */
3267          narg = (long)RSTRING(arg)->ptr;
3268      }
3269      retval = io_cntl(fileno(fptr->f), cmd, narg, io_p);
3270      if (retval < 0) rb_sys_fail(fptr->path);
3271      if (TYPE(arg) == T_STRING && RSTRING(arg)->ptr[len] != 17) {
3272          rb_raise(rb_eArgError, "return value overflowed string");
3273      }
3274  
3275      if (fptr->f2 && fileno(fptr->f) != fileno(fptr->f2)) {
3276          /* call on f2 too; ignore result */
3277          io_cntl(fileno(fptr->f2), cmd, narg, io_p);
3278      }
3279  
3280      return INT2NUM(retval);
3281  #else
3282      rb_notimplement();
3283      return Qnil;                /* not reached */
3284  #endif
3285  }
3286  
3287  static VALUE
3288  rb_io_ioctl(argc, argv, io)
3289      int argc;
3290      VALUE *argv;
3291      VALUE io;
3292  {
3293      VALUE req, arg;
3294  
3295      rb_scan_args(argc, argv, "11", &req, &arg);
3296      return rb_io_ctl(io, req, arg, 1);
3297  }
3298  
3299  static VALUE
3300  rb_io_fcntl(argc, argv, io)
3301      int argc;
3302      VALUE *argv;
3303      VALUE io;
3304  {
3305  #ifdef HAVE_FCNTL
3306      VALUE req, arg;
3307  
3308      rb_scan_args(argc, argv, "11", &req, &arg);
3309      return rb_io_ctl(io, req, arg, 0);
3310  #else
3311      rb_notimplement();
3312      return Qnil;                /* not reached */
3313  #endif
3314  }
3315  
3316  static VALUE
3317  rb_f_syscall(argc, argv)
3318      int argc;
3319      VALUE *argv;
3320  {
3321  #if defined(HAVE_SYSCALL) && !defined(__CHECKER__)
3322  #ifdef atarist
3323      unsigned long arg[14]; /* yes, we really need that many ! */
3324  #else
3325      unsigned long arg[8];
3326  #endif
3327      int retval = -1;
3328      int i = 1;
3329      int items = argc - 1;
3330  
3331      /* This probably won't work on machines where sizeof(long) != sizeof(int)
3332       * or where sizeof(long) != sizeof(char*).  But such machines will
3333       * not likely have syscall implemented either, so who cares?
3334       */
3335  
3336      rb_secure(2);
3337      if (argc == 0)
3338          rb_raise(rb_eArgError, "too few arguments for syscall");
3339      arg[0] = NUM2LONG(argv[0]); argv++;
3340      while (items--) {
3341          if (FIXNUM_P(*argv)) {
3342              arg[i] = (unsigned long)NUM2LONG(*argv);
3343          }
3344          else {
3345              VALUE v = *argv;
3346  
3347              StringValue(v);
3348              rb_str_modify(v);
3349              arg[i] = (unsigned long)RSTRING(v)->ptr;
3350          }
3351          argv++;
3352          i++;
3353      }
3354      TRAP_BEG;
3355      switch (argc) {
3356        case 1:
3357          retval = syscall(arg[0]);
3358          break;
3359        case 2:
3360          retval = syscall(arg[0],arg[1]);
3361          break;
3362        case 3:
3363          retval = syscall(arg[0],arg[1],arg[2]);
3364          break;
3365        case 4:
3366          retval = syscall(arg[0],arg[1],arg[2],arg[3]);
3367          break;
3368        case 5:
3369          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
3370          break;
3371        case 6:
3372          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
3373          break;
3374        case 7:
3375          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
3376          break;
3377        case 8:
3378          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
3379            arg[7]);
3380          break;
3381  #ifdef atarist
3382        case 9:
3383          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
3384            arg[7], arg[8]);
3385          break;
3386        case 10:
3387          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
3388            arg[7], arg[8], arg[9]);
3389          break;
3390        case 11:
3391          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
3392            arg[7], arg[8], arg[9], arg[10]);
3393          break;
3394        case 12:
3395          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
3396            arg[7], arg[8], arg[9], arg[10], arg[11]);
3397          break;
3398        case 13:
3399          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
3400            arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
3401          break;
3402        case 14:
3403          retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
3404            arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13]);
3405          break;
3406  #endif /* atarist */
3407      }
3408      TRAP_END;
3409      if (retval < 0) rb_sys_fail(0);
3410      return INT2NUM(retval);
3411  #else
3412      rb_notimplement();
3413      return Qnil;                /* not reached */
3414  #endif
3415  }
3416  
3417  static VALUE
3418  rb_io_s_pipe()
3419  {
3420  #ifndef __human68k__
3421      int pipes[2];
3422      VALUE r, w;
3423  
3424  #ifdef NT
3425      if (_pipe(pipes, 1024, O_BINARY) == -1)
3426  #else
3427      if (pipe(pipes) == -1)
3428  #endif
3429          rb_sys_fail(0);
3430  
3431      r = prep_stdio(rb_fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO);
3432      w = prep_stdio(rb_fdopen(pipes[1], "w"), FMODE_WRITABLE|FMODE_SYNC, rb_cIO);
3433  
3434      return rb_assoc_new(r, w);
3435  #else
3436      rb_notimplement();
3437      return Qnil;                /* not reached */
3438  #endif
3439  }
3440  
3441  struct foreach_arg {
3442      int argc;
3443      VALUE sep;
3444      VALUE io;
3445      OpenFile *fptr;
3446  };
3447  
3448  static VALUE
3449  io_s_foreach(arg)
3450      struct foreach_arg *arg;
3451  {
3452      VALUE str;
3453  
3454      while (!NIL_P(str = rb_io_getline(arg->sep, arg->fptr))) {
3455          rb_yield(str);
3456      }
3457      return Qnil;
3458  }
3459  
3460  static VALUE
3461  rb_io_s_foreach(argc, argv)
3462      int argc;
3463      VALUE *argv;
3464  {
3465      VALUE fname, io;
3466      OpenFile *fptr;
3467      struct foreach_arg arg;
3468  
3469      rb_scan_args(argc, argv, "11", &fname, &arg.sep);
3470      SafeStringValue(fname);
3471  
3472      if (argc == 1) {
3473          arg.sep = rb_default_rs;
3474      }
3475      io = rb_io_open(RSTRING(fname)->ptr, "r");
3476      if (NIL_P(io)) return Qnil;
3477      GetOpenFile(io, fptr);
3478      arg.fptr = fptr;
3479  
3480      return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, io);
3481  }
3482  
3483  static VALUE
3484  io_s_readlines(arg)
3485      struct foreach_arg *arg;
3486  {
3487      return rb_io_readlines(arg->argc, &arg->sep, arg->io);
3488  }
3489  
3490  static VALUE
3491  rb_io_s_readlines(argc, argv, io)
3492      int argc;
3493      VALUE *argv;
3494      VALUE io;
3495  {
3496      VALUE fname;
3497      struct foreach_arg arg;
3498  
3499      rb_scan_args(argc, argv, "11", &fname, &arg.sep);
3500      SafeStringValue(fname);
3501  
3502      arg.argc = argc - 1;
3503      arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
3504      if (NIL_P(arg.io)) return Qnil;
3505      return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
3506  }
3507  
3508  static VALUE
3509  io_s_read(arg)
3510      struct foreach_arg *arg;
3511  {
3512      return io_read(arg->argc, &arg->sep, arg->io);
3513  }
3514  
3515  static VALUE
3516  rb_io_s_read(argc, argv, io)
3517      int argc;
3518      VALUE *argv;
3519      VALUE io;
3520  {
3521      VALUE fname, offset;
3522      struct foreach_arg arg;
3523  
3524      rb_scan_args(argc, argv, "12", &fname, &arg.sep, &offset);
3525      SafeStringValue(fname);
3526  
3527      arg.argc = argc ? 1 : 0;
3528      arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
3529      if (NIL_P(arg.io)) return Qnil;
3530      if (!NIL_P(offset)) {
3531          rb_io_seek(arg.io, offset, SEEK_SET);
3532      }
3533      return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
3534  }
3535  
3536  static VALUE
3537  argf_tell()
3538  {
3539      if (!next_argv()) {
3540          rb_raise(rb_eArgError, "no stream to tell");
3541      }
3542  
3543      if (TYPE(current_file) != T_FILE) {
3544          return argf_forward();
3545      }
3546      return rb_io_tell(current_file);
3547  }
3548  
3549  static VALUE
3550  argf_seek_m(argc, argv, self)
3551      int argc;
3552      VALUE *argv;
3553      VALUE self;
3554  {
3555      if (!next_argv()) {
3556          rb_raise(rb_eArgError, "no stream to seek");
3557      }
3558  
3559      if (TYPE(current_file) != T_FILE) {
3560          return argf_forward();
3561      }
3562      return rb_io_seek_m(argc, argv, current_file);
3563  }
3564  
3565  static VALUE
3566  argf_set_pos(self, offset)
3567       VALUE self, offset;
3568  {
3569      if (!next_argv()) {
3570          rb_raise(rb_eArgError, "no stream to set position");
3571      }
3572  
3573      if (TYPE(current_file) != T_FILE) {
3574          return argf_forward();
3575      }
3576      return rb_io_set_pos(current_file, offset);
3577  }
3578  
3579  static VALUE
3580  argf_rewind()
3581  {
3582      if (!next_argv()) {
3583          rb_raise(rb_eArgError, "no stream to rewind");
3584      }
3585      if (TYPE(current_file) != T_FILE) {
3586          return argf_forward();
3587      }
3588      return rb_io_rewind(current_file);
3589  }
3590  
3591  static VALUE
3592  argf_fileno()
3593  {
3594      if (!next_argv()) {
3595          rb_raise(rb_eArgError, "no stream");
3596      }
3597      if (TYPE(current_file) != T_FILE) {
3598          return argf_forward();
3599      }
3600      return rb_io_fileno(current_file);
3601  }
3602  
3603  static VALUE
3604  argf_to_io()
3605  {
3606      return current_file;
3607  }
3608  
3609  static VALUE
3610  argf_read(argc, argv)
3611      int argc;
3612      VALUE *argv;
3613  {
3614      VALUE tmp, str;
3615      long len = 0;
3616  
3617      if (argc == 1) len = NUM2LONG(argv[0]);
3618      str = Qnil;
3619  
3620    retry:
3621      if (!next_argv()) return str;
3622      if (TYPE(current_file) != T_FILE) {
3623          tmp = argf_forward();
3624          StringValue(tmp);
3625      }
3626      else {
3627          tmp = io_read(argc, argv, current_file);
3628      }
3629      if (NIL_P(tmp) && next_p != -1) {
3630          any_close(current_file);
3631          next_p = 1;
3632          goto retry;
3633      }
3634      if (NIL_P(tmp) || RSTRING(tmp)->len == 0) return str;
3635      else if (NIL_P(str)) str = tmp;
3636      else rb_str_append(str, tmp);
3637      if (argc == 0) {
3638          goto retry;
3639      }
3640      if (RSTRING(tmp)->len < len) {
3641          len -= RSTRING(tmp)->len;
3642          argv[0] = LONG2FIX(len);
3643          goto retry;
3644      }
3645  
3646      return str;
3647  }
3648  
3649  static VALUE
3650  argf_getc()
3651  {
3652      VALUE byte;
3653  
3654    retry:
3655      if (!next_argv()) return Qnil;
3656      if (TYPE(current_file) != T_FILE) {
3657          byte = rb_funcall3(current_file, rb_intern("getc"), 0, 0);
3658      }
3659      else {
3660          byte = rb_io_getc(current_file);
3661      }
3662      if (NIL_P(byte) && next_p != -1) {
3663          any_close(current_file);
3664          next_p = 1;
3665          goto retry;
3666      }
3667  
3668      return byte;
3669  }
3670  
3671  static VALUE
3672  argf_readchar()
3673  {
3674      VALUE c = argf_getc();
3675  
3676      if (NIL_P(c)) {
3677          rb_eof_error();
3678      }
3679      return c;
3680  }
3681  
3682  static VALUE
3683  argf_eof()
3684  {
3685      if (!next_argv()) return Qtrue;
3686      if (next_p == 1) {
3687          return Qtrue;
3688      }
3689      if (TYPE(current_file) != T_FILE) {
3690          return argf_forward();
3691      }
3692      if (rb_io_eof(current_file)) {
3693          next_p = 1;
3694          return Qtrue;
3695      }
3696      return Qfalse;
3697  }
3698  
3699  static VALUE
3700  argf_each_line(argc, argv)
3701      int argc;
3702      VALUE *argv;
3703  {
3704      VALUE str;
3705  
3706      while (RTEST(str = argf_getline(argc, argv))) {
3707          rb_yield(str);
3708      }
3709      return argf;
3710  }
3711  
3712  static VALUE
3713  argf_each_byte()
3714  {
3715      VALUE byte;
3716  
3717      while (!NIL_P(byte = argf_getc())) {
3718          rb_yield(byte);
3719      }
3720      return Qnil;
3721  }
3722  
3723  static VALUE
3724  argf_filename()
3725  {
3726      next_argv();
3727      return filename;
3728  }
3729  
3730  static VALUE
3731  argf_file()
3732  {
3733      next_argv();
3734      return current_file;
3735  }
3736  
3737  static VALUE
3738  argf_binmode()
3739  {
3740      binmode = 1;
3741      next_argv();
3742      if (TYPE(current_file) != T_FILE) {
3743          argf_forward();
3744      }
3745      else {
3746          rb_io_binmode(current_file);
3747      }
3748      return argf;
3749  }
3750  
3751  static VALUE
3752  argf_skip()
3753  {
3754      if (next_p != -1) {
3755          any_close(current_file);
3756          next_p = 1;
3757      }
3758      return argf;
3759  }
3760  
3761  static VALUE
3762  argf_close()
3763  {
3764      any_close(current_file);
3765      if (next_p != -1) {
3766          next_p = 1;
3767      }
3768      gets_lineno = 0;
3769      return argf;
3770  }
3771  
3772  static VALUE
3773  argf_closed()
3774  {
3775      if (TYPE(current_file) != T_FILE) {
3776          return argf_forward();
3777      }
3778      return rb_io_closed(current_file);
3779  }
3780  
3781  static VALUE
3782  opt_i_get()
3783  {
3784      if (!ruby_inplace_mode) return Qnil;
3785      return rb_str_new2(ruby_inplace_mode);
3786  }
3787  
3788  static void
3789  opt_i_set(val)
3790      VALUE val;
3791  {
3792      if (!RTEST(val)) {
3793          if (ruby_inplace_mode) free(ruby_inplace_mode);
3794          ruby_inplace_mode = 0;
3795          return;
3796      }
3797      StringValue(val);
3798      if (ruby_inplace_mode) free(ruby_inplace_mode);
3799      ruby_inplace_mode = 0;
3800      ruby_inplace_mode = strdup(RSTRING(val)->ptr);
3801  }
3802  
3803  void
3804  Init_IO()
3805  {
3806      rb_eIOError = rb_define_class("IOError", rb_eStandardError);
3807      rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
3808  
3809      id_write = rb_intern("write");
3810  
3811      rb_define_global_function("syscall", rb_f_syscall, -1);
3812  
3813      rb_define_global_function("open", rb_f_open, -1);
3814      rb_define_global_function("printf", rb_f_printf, -1);
3815      rb_define_global_function("print", rb_f_print, -1);
3816      rb_define_global_function("putc", rb_f_putc, 1);
3817      rb_define_global_function("puts", rb_f_puts, -1);
3818      rb_define_global_function("gets", rb_f_gets, -1);
3819      rb_define_global_function("readline", rb_f_readline, -1);
3820      rb_define_global_function("getc", rb_f_getc, 0);
3821      rb_define_global_function("select", rb_f_select, -1);
3822  
3823      rb_define_global_function("readlines", rb_f_readlines, -1);
3824  
3825      rb_define_global_function("`", rb_f_backquote, 1);
3826  
3827      rb_define_global_function("p", rb_f_p, -1);
3828      rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
3829  
3830      rb_cIO = rb_define_class("IO", rb_cObject);
3831      rb_include_module(rb_cIO, rb_mEnumerable);
3832  
3833      rb_define_singleton_method(rb_cIO, "allocate", rb_io_s_alloc, 0);
3834      rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
3835      rb_define_singleton_method(rb_cIO, "open",  rb_io_s_open, -1);
3836      rb_define_singleton_method(rb_cIO, "sysopen",  rb_io_s_sysopen, -1);
3837      rb_define_singleton_method(rb_cIO, "for_fd", rb_class_new_instance, -1);
3838      rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
3839      rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
3840      rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
3841      rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
3842      rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
3843      rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, 0);
3844  
3845      rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
3846  
3847      rb_output_fs = Qnil;
3848      rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
3849  
3850      rb_rs = rb_default_rs = rb_str_new2("\n");
3851      rb_output_rs = Qnil;
3852      rb_global_variable(&rb_default_rs);
3853      OBJ_FREEZE(rb_default_rs);  /* avoid modifying RS_default */
3854      rb_define_variable("$/", &rb_rs);
3855      rb_define_variable("$-0", &rb_rs);
3856      rb_define_variable("$\\", &rb_output_rs);
3857  
3858      rb_define_hooked_variable("$.", &lineno, 0, lineno_setter);
3859      rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
3860  
3861      rb_define_method(rb_cIO, "become", rb_io_become, 1);
3862      rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
3863  
3864      rb_define_method(rb_cIO, "print", rb_io_print, -1);
3865      rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
3866      rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
3867      rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
3868  
3869      rb_define_method(rb_cIO, "each",  rb_io_each_line, -1);
3870      rb_define_method(rb_cIO, "each_line",  rb_io_each_line, -1);
3871      rb_define_method(rb_cIO, "each_byte",  rb_io_each_byte, 0);
3872  
3873      rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
3874      rb_define_method(rb_cIO, "sysread",  rb_io_sysread, 1);
3875  
3876      rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
3877      rb_define_alias(rb_cIO, "to_i", "fileno");
3878      rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
3879  
3880      rb_define_method(rb_cIO, "fsync",   rb_io_fsync, 0);
3881      rb_define_method(rb_cIO, "sync",   rb_io_sync, 0);
3882      rb_define_method(rb_cIO, "sync=",  rb_io_set_sync, 1);
3883  
3884      rb_define_method(rb_cIO, "lineno",   rb_io_lineno, 0);
3885      rb_define_method(rb_cIO, "lineno=",  rb_io_set_lineno, 1);
3886  
3887      rb_define_method(rb_cIO, "readlines",  rb_io_readlines, -1);
3888  
3889      rb_define_method(rb_cIO, "read",  io_read, -1);
3890      rb_define_method(rb_cIO, "write", io_write, 1);
3891      rb_define_method(rb_cIO, "gets",  rb_io_gets_m, -1);
3892      rb_define_method(rb_cIO, "readline",  rb_io_readline, -1);
3893      rb_define_method(rb_cIO, "getc",  rb_io_getc, 0);
3894      rb_define_method(rb_cIO, "readchar",  rb_io_readchar, 0);
3895      rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
3896      rb_define_method(rb_cIO, "<<",    rb_io_addstr, 1);
3897      rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
3898      rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
3899      rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
3900      rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
3901      rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
3902      rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
3903      rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
3904      rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
3905      rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
3906      rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
3907      rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
3908  
3909      rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
3910      rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
3911      rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
3912      rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
3913  
3914      rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
3915      rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
3916      rb_define_method(rb_cIO, "binmode",  rb_io_binmode, 0);
3917      rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
3918  
3919      rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
3920      rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
3921      rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
3922      rb_define_method(rb_cIO, "inspect",  rb_io_inspect, 0);
3923  
3924      rb_stdin = orig_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO);
3925      rb_define_hooked_variable("$stdin", &rb_stdin, 0, set_stdin);
3926      rb_stdout = orig_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO);
3927      rb_define_hooked_variable("$stdout", &rb_stdout, 0, set_stdout);
3928      rb_stderr = orig_stderr = prep_stdio(stderr, FMODE_WRITABLE, rb_cIO);
3929      rb_define_hooked_variable("$stderr", &rb_stderr, 0, set_stderr);
3930      rb_defout = rb_stdout;
3931      rb_define_hooked_variable("$>", &rb_defout, 0, rb_io_defset);
3932      rb_define_hooked_variable("$defout", &rb_defout, 0, rb_io_defset);
3933  
3934      rb_define_global_const("STDIN", rb_stdin);
3935      rb_define_global_const("STDOUT", rb_stdout);
3936      rb_define_global_const("STDERR", rb_stderr);
3937  
3938      argf = rb_obj_alloc(rb_cObject);
3939      rb_extend_object(argf, rb_mEnumerable);
3940  
3941      rb_define_readonly_variable("$<", &argf);
3942      rb_define_global_const("ARGF", argf);
3943  
3944      rb_define_singleton_method(argf, "fileno", argf_fileno, 0);
3945      rb_define_singleton_method(argf, "to_i", argf_fileno, 0);
3946      rb_define_singleton_method(argf, "to_io", argf_to_io, 0);
3947      rb_define_singleton_method(argf, "each",  argf_each_line, -1);
3948      rb_define_singleton_method(argf, "each_line",  argf_each_line, -1);
3949      rb_define_singleton_method(argf, "each_byte",  argf_each_byte, 0);
3950  
3951      rb_define_singleton_method(argf, "read",  argf_read, -1);
3952      rb_define_singleton_method(argf, "readlines", rb_f_readlines, -1);
3953      rb_define_singleton_method(argf, "to_a", rb_f_readlines, -1);
3954      rb_define_singleton_method(argf, "gets", rb_f_gets, -1);
3955      rb_define_singleton_method(argf, "readline", rb_f_readline, -1);
3956      rb_define_singleton_method(argf, "getc", argf_getc, 0);
3957      rb_define_singleton_method(argf, "readchar", argf_readchar, 0);
3958      rb_define_singleton_method(argf, "tell", argf_tell, 0);
3959      rb_define_singleton_method(argf, "seek", argf_seek_m, -1);
3960      rb_define_singleton_method(argf, "rewind", argf_rewind, 0);
3961      rb_define_singleton_method(argf, "pos", argf_tell, 0);
3962      rb_define_singleton_method(argf, "pos=", argf_set_pos, 1);
3963      rb_define_singleton_method(argf, "eof", argf_eof, 0);
3964      rb_define_singleton_method(argf, "eof?", argf_eof, 0);
3965      rb_define_singleton_method(argf, "binmode", argf_binmode, 0);
3966  
3967      rb_define_singleton_method(argf, "to_s", argf_filename, 0);
3968      rb_define_singleton_method(argf, "filename", argf_filename, 0);
3969      rb_define_singleton_method(argf, "file", argf_file, 0);
3970      rb_define_singleton_method(argf, "skip", argf_skip, 0);
3971      rb_define_singleton_method(argf, "close", argf_close, 0);
3972      rb_define_singleton_method(argf, "closed?", argf_closed, 0);
3973  
3974      rb_define_singleton_method(argf, "lineno",   argf_lineno, 0);
3975      rb_define_singleton_method(argf, "lineno=",  argf_set_lineno, 1);
3976  
3977      current_file = rb_stdin;
3978      rb_global_variable(&current_file);
3979      filename = rb_str_new2("-");
3980      rb_define_readonly_variable("$FILENAME", &filename);
3981  
3982      rb_define_virtual_variable("$-i", opt_i_get, opt_i_set);
3983  
3984  #if defined (NT) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__)
3985      atexit(pipe_atexit);
3986  #endif
3987  
3988      Init_File();
3989  
3990      rb_define_method(rb_cFile, "initialize",  rb_file_initialize, -1);
3991  
3992      rb_file_const("RDONLY", INT2FIX(O_RDONLY));
3993      rb_file_const("WRONLY", INT2FIX(O_WRONLY));
3994      rb_file_const("RDWR", INT2FIX(O_RDWR));
3995      rb_file_const("APPEND", INT2FIX(O_APPEND));
3996      rb_file_const("CREAT", INT2FIX(O_CREAT));
3997      rb_file_const("EXCL", INT2FIX(O_EXCL));
3998  #if defined(O_NDELAY) || defined(O_NONBLOCK)
3999  #   ifdef O_NONBLOCK
4000      rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
4001  #   else
4002      rb_file_const("NONBLOCK", INT2FIX(O_NDELAY));
4003  #   endif
4004  #endif
4005      rb_file_const("TRUNC", INT2FIX(O_TRUNC));
4006  #ifdef O_NOCTTY
4007      rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
4008  #endif
4009  #ifdef O_BINARY
4010      rb_file_const("BINARY", INT2FIX(O_BINARY));
4011  #endif
4012  #ifdef O_SYNC
4013      rb_file_const("SYNC", INT2FIX(O_SYNC));
4014  #endif
4015  }