Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# io.c

Go to the documentation of this file.

    00001 /**********************************************************************
    00002
    00003   io.c -
    00004
    00005   $Author: yugui $
    00006   created at: Fri Oct 15 18:08:59 JST 1993
    00007
    00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
    00009   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
    00010   Copyright (C) 2000  Information-technology Promotion Agency, Japan
    00011
    00012 **********************************************************************/
    00013
    00014 #include "ruby/ruby.h"
    00015 #include "ruby/io.h"
    00016 #include "dln.h"
    00017 #include <ctype.h>
    00018 #include <errno.h>
    00019
    00020 #define free(x) xfree(x)
    00021
    00022 #if defined(DOSISH) || defined(__CYGWIN__)
    00023 #include <io.h>
    00024 #endif
    00025
    00026 #include <sys/types.h>
    00027 #if defined HAVE_NET_SOCKET_H
    00028 # include <net/socket.h>
    00029 #elif defined HAVE_SYS_SOCKET_H
    00030 # include <sys/socket.h>
    00031 #endif
    00032
    00033 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__EMX__) || defined(__BEOS__) || defined(__HAIKU__)
    00034 # define NO_SAFE_RENAME
    00035 #endif
    00036
    00037 #if defined(__CYGWIN__) || defined(_WIN32)
    00038 # define NO_LONG_FNAME
    00039 #endif
    00040
    00041 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(sun) || defined(_nec_ews)
    00042 # define USE_SETVBUF
    00043 #endif
    00044
    00045 #ifdef __QNXNTO__
    00046 #include "unix.h"
    00047 #endif
    00048
    00049 #include <sys/types.h>
    00050 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
    00051 #include <sys/ioctl.h>
    00052 #endif
    00053 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
    00054 #include <fcntl.h>
    00055 #elif defined(HAVE_SYS_FCNTL_H)
    00056 #include <sys/fcntl.h>
    00057 #endif
    00058
    00059 #if !HAVE_OFF_T && !defined(off_t)
    00060 # define off_t  long
    00061 #endif
    00062
    00063 #include <sys/stat.h>
    00064
    00065 /* EMX has sys/param.h, but.. */
    00066 #if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
    00067 # include <sys/param.h>
    00068 #endif
    00069
    00070 #if !defined NOFILE
    00071 # define NOFILE 64
    00072 #endif
    00073
    00074 #ifdef HAVE_UNISTD_H
    00075 #include <unistd.h>
    00076 #endif
    00077
    00078 #ifdef HAVE_SYSCALL_H
    00079 #include <syscall.h>
    00080 #elif defined HAVE_SYS_SYSCALL_H
    00081 #include <sys/syscall.h>
    00082 #endif
    00083
    00084 extern void Init_File(void);
    00085
    00086 #if defined(__BEOS__) || defined(__HAIKU__)
    00087 # ifndef NOFILE
    00088 #  define NOFILE (OPEN_MAX)
    00089 # endif
    00090 #endif
    00091
    00092 #include "ruby/util.h"
    00093
    00094 #ifndef O_ACCMODE
    00095 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
    00096 #endif
    00097
    00098 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
    00099 # error off_t is bigger than long, but you have no long long...
    00100 #endif
    00101
    00102 #ifndef PIPE_BUF
    00103 # ifdef _POSIX_PIPE_BUF
    00104 #  define PIPE_BUF _POSIX_PIPE_BUF
    00105 # else
    00106 #  define PIPE_BUF 512 /* is this ok? */
    00107 # endif
    00108 #endif
    00109
    00110 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
    00111
    00112 #define IO_RBUF_CAPA_MIN  8192
    00113 #define IO_CBUF_CAPA_MIN  (128*1024)
    00114 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
    00115 #define IO_WBUF_CAPA_MIN  8192
    00116
    00117 /* define system APIs */
    00118 #ifdef _WIN32
    00119 #undef open
    00120 #define open    rb_w32_uopen
    00121 #endif
    00122
    00123 VALUE rb_cIO;
    00124 VALUE rb_eEOFError;
    00125 VALUE rb_eIOError;
    00126 VALUE rb_mWaitReadable;
    00127 VALUE rb_mWaitWritable;
    00128
    00129 VALUE rb_stdin, rb_stdout, rb_stderr;
    00130 VALUE rb_deferr;                /* rescue VIM plugin */
    00131 static VALUE orig_stdout, orig_stderr;
    00132
    00133 VALUE rb_output_fs;
    00134 VALUE rb_rs;
    00135 VALUE rb_output_rs;
    00136 VALUE rb_default_rs;
    00137
    00138 static VALUE argf;
    00139
    00140 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
    00141 static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
    00142 static VALUE sym_textmode, sym_binmode, sym_autoclose;
    00143
    00144 struct timeval rb_time_interval(VALUE);
    00145
    00146 struct argf {
    00147     VALUE filename, current_file;
    00148     int last_lineno;            /* $. */
    00149     int lineno;
    00150     int init_p, next_p;
    00151     VALUE argv;
    00152     char *inplace;
    00153     int binmode;
    00154     struct rb_io_enc_t encs;
    00155 };
    00156
    00157 static int max_file_descriptor = NOFILE;
    00158 #define UPDATE_MAXFD(fd) \
    00159     do { \
    00160         if (max_file_descriptor < (fd)) max_file_descriptor = (fd); \
    00161     } while (0)
    00162
    00163 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
    00164 #define ARGF argf_of(argf)
    00165
    00166 #ifdef _STDIO_USES_IOSTREAM  /* GNU libc */
    00167 #  ifdef _IO_fpos_t
    00168 #    define STDIO_READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
    00169 #  else
    00170 #    define STDIO_READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
    00171 #  endif
    00172 #elif defined(FILE_COUNT)
    00173 #  define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
    00174 #elif defined(FILE_READEND)
    00175 #  define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
    00176 #elif defined(__BEOS__) || defined(__HAIKU__)
    00177 #  define STDIO_READ_DATA_PENDING(fp) (fp->_state._eof == 0)
    00178 #else
    00179 #  define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
    00180 #endif
    00181
    00182 #define GetWriteIO(io) rb_io_get_write_io(io)
    00183
    00184 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf_len)
    00185 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf_len)
    00186 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off)
    00187 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
    00188
    00189 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf_len)
    00190 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf_len)
    00191 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf+(fptr)->cbuf_off)
    00192
    00193 #if defined(_WIN32)
    00194 #define WAIT_FD_IN_WIN32(fptr) \
    00195     (rb_w32_has_cancel_io() ? 0 : rb_thread_wait_fd((fptr)->fd))
    00196 #else
    00197 #define WAIT_FD_IN_WIN32(fptr)
    00198 #endif
    00199
    00200 #define READ_CHECK(fptr) do {\
    00201     if (!READ_DATA_PENDING(fptr)) {\
    00202         WAIT_FD_IN_WIN32(fptr);\
    00203         rb_io_check_closed(fptr);\
    00204      }\
    00205 } while(0)
    00206
    00207 #ifndef S_ISSOCK
    00208 #  ifdef _S_ISSOCK
    00209 #    define S_ISSOCK(m) _S_ISSOCK(m)
    00210 #  else
    00211 #    ifdef _S_IFSOCK
    00212 #      define S_ISSOCK(m) ((m & S_IFMT) == _S_IFSOCK)
    00213 #    else
    00214 #      ifdef S_IFSOCK
    00215 #        define S_ISSOCK(m) ((m & S_IFMT) == S_IFSOCK)
    00216 #      endif
    00217 #    endif
    00218 #  endif
    00219 #endif
    00220
    00221 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
    00222 /* Windows */
    00223 # define NEED_NEWLINE_DECORATOR_ON_READ(fptr) (!(fptr->mode & FMODE_BINMODE))
    00224 # define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) (!(fptr->mode & FMODE_BINMODE))
    00225 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
    00226 #else
    00227 /* Unix */
    00228 # define NEED_NEWLINE_DECORATOR_ON_READ(fptr) (fptr->mode & FMODE_TEXTMODE)
    00229 # define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) 0
    00230 #endif
    00231 #define NEED_READCONV(fptr) (fptr->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
    00232 #define NEED_WRITECONV(fptr) ((fptr->encs.enc != NULL && fptr->encs.enc != rb_ascii8bit_encoding()) || NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || (fptr->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)))
    00233
    00234 #if !defined HAVE_SHUTDOWN && !defined shutdown
    00235 #define shutdown(a,b)   0
    00236 #endif
    00237
    00238 #define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
    00239
    00240 #if defined(_WIN32)
    00241 #define is_socket(fd, path)     rb_w32_is_socket(fd)
    00242 #elif !defined(S_ISSOCK)
    00243 #define is_socket(fd, path)     0
    00244 #else
    00245 static int
    00246 is_socket(int fd, VALUE path)
    00247 {
    00248     struct stat sbuf;
    00249     if (fstat(fd, &sbuf) < 0)
    00250         rb_sys_fail_path(path);
    00251     return S_ISSOCK(sbuf.st_mode);
    00252 }
    00253 #endif
    00254
    00255 void
    00256 rb_eof_error(void)
    00257 {
    00258     rb_raise(rb_eEOFError, "end of file reached");
    00259 }
    00260
    00261 VALUE
    00262 rb_io_taint_check(VALUE io)
    00263 {
    00264     if (!OBJ_UNTRUSTED(io) && rb_safe_level() >= 4)
    00265         rb_raise(rb_eSecurityError, "Insecure: operation on trusted IO");
    00266     rb_check_frozen(io);
    00267     return io;
    00268 }
    00269
    00270 void
    00271 rb_io_check_initialized(rb_io_t *fptr)
    00272 {
    00273     if (!fptr) {
    00274         rb_raise(rb_eIOError, "uninitialized stream");
    00275     }
    00276 }
    00277
    00278 void
    00279 rb_io_check_closed(rb_io_t *fptr)
    00280 {
    00281     rb_io_check_initialized(fptr);
    00282     if (fptr->fd < 0) {
    00283         rb_raise(rb_eIOError, "closed stream");
    00284     }
    00285 }
    00286
    00287 static int io_fflush(rb_io_t *);
    00288
    00289 VALUE
    00290 rb_io_get_io(VALUE io)
    00291 {
    00292     return rb_convert_type(io, T_FILE, "IO", "to_io");
    00293 }
    00294
    00295 static VALUE
    00296 rb_io_check_io(VALUE io)
    00297 {
    00298     return rb_check_convert_type(io, T_FILE, "IO", "to_io");
    00299 }
    00300
    00301 VALUE
    00302 rb_io_get_write_io(VALUE io)
    00303 {
    00304     VALUE write_io;
    00305     rb_io_check_initialized(RFILE(io)->fptr);
    00306     write_io = RFILE(io)->fptr->tied_io_for_writing;
    00307     if (write_io) {
    00308         return write_io;
    00309     }
    00310     return io;
    00311 }
    00312
    00313 /*
    00314  *  call-seq:
    00315  *     IO.try_convert(obj)  ->  io or nil
    00316  *
    00317  *  Try to convert <i>obj</i> into an IO, using to_io method.
    00318  *  Returns converted IO or nil if <i>obj</i> cannot be converted
    00319  *  for any reason.
    00320  *
    00321  *     IO.try_convert(STDOUT)     #=> STDOUT
    00322  *     IO.try_convert("STDOUT")   #=> nil
    00323  *
    00324  *     require 'zlib'
    00325  *     f = open("/tmp/zz.gz")       #=> #<File:/tmp/zz.gz>
    00326  *     z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
    00327  *     IO.try_convert(z)            #=> #<File:/tmp/zz.gz>
    00328  *
    00329  */
    00330 static VALUE
    00331 rb_io_s_try_convert(VALUE dummy, VALUE io)
    00332 {
    00333     return rb_io_check_io(io);
    00334 }
    00335
    00336 static void
    00337 io_unread(rb_io_t *fptr)
    00338 {
    00339     off_t r;
    00340     rb_io_check_closed(fptr);
    00341     if (fptr->rbuf_len == 0 || fptr->mode & FMODE_DUPLEX)
    00342         return;
    00343     /* xxx: target position may be negative if buffer is filled by ungetc */
    00344     errno = 0;
    00345     r = lseek(fptr->fd, -fptr->rbuf_len, SEEK_CUR);
    00346     if (r < 0 && errno) {
    00347         if (errno == ESPIPE)
    00348             fptr->mode |= FMODE_DUPLEX;
    00349         return;
    00350     }
    00351     fptr->rbuf_off = 0;
    00352     fptr->rbuf_len = 0;
    00353     return;
    00354 }
    00355
    00356 static rb_encoding *io_input_encoding(rb_io_t *fptr);
    00357
    00358 static void
    00359 io_ungetbyte(VALUE str, rb_io_t *fptr)
    00360 {
    00361     long len = RSTRING_LEN(str);
    00362
    00363     if (fptr->rbuf == NULL) {
    00364         const int min_capa = IO_RBUF_CAPA_FOR(fptr);
    00365         fptr->rbuf_off = 0;
    00366         fptr->rbuf_len = 0;
    00367 #if SIZEOF_LONG > SIZEOF_INT
    00368         if (len > INT_MAX)
    00369             rb_raise(rb_eIOError, "ungetbyte failed");
    00370 #endif
    00371         if (len > min_capa)
    00372             fptr->rbuf_capa = (int)len;
    00373         else
    00374             fptr->rbuf_capa = min_capa;
    00375         fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
    00376     }
    00377     if (fptr->rbuf_capa < len + fptr->rbuf_len) {
    00378         rb_raise(rb_eIOError, "ungetbyte failed");
    00379     }
    00380     if (fptr->rbuf_off < len) {
    00381         MEMMOVE(fptr->rbuf+fptr->rbuf_capa-fptr->rbuf_len,
    00382                 fptr->rbuf+fptr->rbuf_off,
    00383                 char, fptr->rbuf_len);
    00384         fptr->rbuf_off = fptr->rbuf_capa-fptr->rbuf_len;
    00385     }
    00386     fptr->rbuf_off-=(int)len;
    00387     fptr->rbuf_len+=(int)len;
    00388     MEMMOVE(fptr->rbuf+fptr->rbuf_off, RSTRING_PTR(str), char, len);
    00389 }
    00390
    00391 static rb_io_t *
    00392 flush_before_seek(rb_io_t *fptr)
    00393 {
    00394     if (io_fflush(fptr) < 0)
    00395         rb_sys_fail(0);
    00396     io_unread(fptr);
    00397     errno = 0;
    00398     return fptr;
    00399 }
    00400
    00401 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, ofs, whence))
    00402 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
    00403
    00404 #ifndef SEEK_CUR
    00405 # define SEEK_SET 0
    00406 # define SEEK_CUR 1
    00407 # define SEEK_END 2
    00408 #endif
    00409
    00410 #define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
    00411
    00412 void
    00413 rb_io_check_char_readable(rb_io_t *fptr)
    00414 {
    00415     rb_io_check_closed(fptr);
    00416     if (!(fptr->mode & FMODE_READABLE)) {
    00417         rb_raise(rb_eIOError, "not opened for reading");
    00418     }
    00419     if (fptr->wbuf_len) {
    00420         if (io_fflush(fptr) < 0)
    00421             rb_sys_fail(0);
    00422     }
    00423     if (fptr->tied_io_for_writing) {
    00424         rb_io_t *wfptr;
    00425         GetOpenFile(fptr->tied_io_for_writing, wfptr);
    00426         if (io_fflush(wfptr) < 0)
    00427             rb_sys_fail(0);
    00428     }
    00429 }
    00430
    00431 void
    00432 rb_io_check_byte_readable(rb_io_t *fptr)
    00433 {
    00434     rb_io_check_char_readable(fptr);
    00435     if (READ_CHAR_PENDING(fptr)) {
    00436         rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
    00437     }
    00438 }
    00439
    00440 void
    00441 rb_io_check_readable(rb_io_t *fptr)
    00442 {
    00443     rb_io_check_byte_readable(fptr);
    00444 }
    00445
    00446 static rb_encoding*
    00447 io_read_encoding(rb_io_t *fptr)
    00448 {
    00449     if (fptr->encs.enc) {
    00450         return fptr->encs.enc;
    00451     }
    00452     return rb_default_external_encoding();
    00453 }
    00454
    00455 static rb_encoding*
    00456 io_input_encoding(rb_io_t *fptr)
    00457 {
    00458     if (fptr->encs.enc2) {
    00459         return fptr->encs.enc2;
    00460     }
    00461     return io_read_encoding(fptr);
    00462 }
    00463
    00464 void
    00465 rb_io_check_writable(rb_io_t *fptr)
    00466 {
    00467     rb_io_check_closed(fptr);
    00468     if (!(fptr->mode & FMODE_WRITABLE)) {
    00469         rb_raise(rb_eIOError, "not opened for writing");
    00470     }
    00471     if (fptr->rbuf_len) {
    00472         io_unread(fptr);
    00473     }
    00474 }
    00475
    00476 int
    00477 rb_io_read_pending(rb_io_t *fptr)
    00478 {
    00479     /* This function is used for bytes and chars.  Confusing. */
    00480     if (READ_CHAR_PENDING(fptr))
    00481         return 1; /* should raise? */
    00482     return READ_DATA_PENDING(fptr);
    00483 }
    00484
    00485 void
    00486 rb_read_check(FILE *fp)
    00487 {
    00488     if (!STDIO_READ_DATA_PENDING(fp)) {
    00489         rb_thread_wait_fd(fileno(fp));
    00490     }
    00491 }
    00492
    00493 void
    00494 rb_io_read_check(rb_io_t *fptr)
    00495 {
    00496     if (!READ_DATA_PENDING(fptr)) {
    00497         rb_thread_wait_fd(fptr->fd);
    00498     }
    00499     return;
    00500 }
    00501
    00502 static int
    00503 ruby_dup(int orig)
    00504 {
    00505     int fd;
    00506
    00507     fd = dup(orig);
    00508     if (fd < 0) {
    00509         if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
    00510             rb_gc();
    00511             fd = dup(orig);
    00512         }
    00513         if (fd < 0) {
    00514             rb_sys_fail(0);
    00515         }
    00516     }
    00517     UPDATE_MAXFD(fd);
    00518     return fd;
    00519 }
    00520
    00521 static VALUE
    00522 io_alloc(VALUE klass)
    00523 {
    00524     NEWOBJ(io, struct RFile);
    00525     OBJSETUP(io, klass, T_FILE);
    00526
    00527     io->fptr = 0;
    00528
    00529     return (VALUE)io;
    00530 }
    00531
    00532 #ifndef S_ISREG
    00533 #   define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
    00534 #endif
    00535
    00536 static int
    00537 wsplit_p(rb_io_t *fptr)
    00538 {
    00539 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
    00540     int r;
    00541 #endif
    00542
    00543     if (!(fptr->mode & FMODE_WSPLIT_INITIALIZED)) {
    00544         struct stat buf;
    00545         if (fstat(fptr->fd, &buf) == 0 &&
    00546             !S_ISREG(buf.st_mode)
    00547 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
    00548             && (r = fcntl(fptr->fd, F_GETFL)) != -1 &&
    00549             !(r & O_NONBLOCK)
    00550 #endif
    00551             ) {
    00552             fptr->mode |= FMODE_WSPLIT;
    00553         }
    00554         fptr->mode |= FMODE_WSPLIT_INITIALIZED;
    00555     }
    00556     return fptr->mode & FMODE_WSPLIT;
    00557 }
    00558
    00559 struct io_internal_struct {
    00560     int fd;
    00561     void *buf;
    00562     size_t capa;
    00563 };
    00564
    00565 static VALUE
    00566 internal_read_func(void *ptr)
    00567 {
    00568     struct io_internal_struct *iis = (struct io_internal_struct*)ptr;
    00569     return read(iis->fd, iis->buf, iis->capa);
    00570 }
    00571
    00572 static VALUE
    00573 internal_write_func(void *ptr)
    00574 {
    00575     struct io_internal_struct *iis = (struct io_internal_struct*)ptr;
    00576     return write(iis->fd, iis->buf, iis->capa);
    00577 }
    00578
    00579 static ssize_t
    00580 rb_read_internal(int fd, void *buf, size_t count)
    00581 {
    00582     struct io_internal_struct iis;
    00583     iis.fd = fd;
    00584     iis.buf = buf;
    00585     iis.capa = count;
    00586
    00587     return (ssize_t)rb_thread_blocking_region(internal_read_func, &iis, RUBY_UBF_IO, 0);
    00588 }
    00589
    00590 static ssize_t
    00591 rb_write_internal(int fd, void *buf, size_t count)
    00592 {
    00593     struct io_internal_struct iis;
    00594     iis.fd = fd;
    00595     iis.buf = buf;
    00596     iis.capa = count;
    00597
    00598     return (ssize_t)rb_thread_blocking_region(internal_write_func, &iis, RUBY_UBF_IO, 0);
    00599 }
    00600
    00601 static long
    00602 io_writable_length(rb_io_t *fptr, long l)
    00603 {
    00604     if (PIPE_BUF < l &&
    00605         !rb_thread_alone() &&
    00606         wsplit_p(fptr)) {
    00607         l = PIPE_BUF;
    00608     }
    00609     return l;
    00610 }
    00611
    00612 static VALUE
    00613 io_flush_buffer_sync(void *arg)
    00614 {
    00615     rb_io_t *fptr = arg;
    00616     long l = io_writable_length(fptr, fptr->wbuf_len);
    00617     ssize_t r = write(fptr->fd, fptr->wbuf+fptr->wbuf_off, (size_t)l);
    00618
    00619     if (fptr->wbuf_len <= r) {
    00620         fptr->wbuf_off = 0;
    00621         fptr->wbuf_len = 0;
    00622         return 0;
    00623     }
    00624     if (0 <= r) {
    00625         fptr->wbuf_off += (int)r;
    00626         fptr->wbuf_len -= (int)r;
    00627         errno = EAGAIN;
    00628     }
    00629     return (VALUE)-1;
    00630 }
    00631
    00632 static VALUE
    00633 io_flush_buffer_async(VALUE arg)
    00634 {
    00635     return rb_thread_blocking_region(io_flush_buffer_sync, (void *)arg, RUBY_UBF_IO, 0);
    00636 }
    00637
    00638 static inline int
    00639 io_flush_buffer(rb_io_t *fptr)
    00640 {
    00641     if (fptr->write_lock) {
    00642         return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async, (VALUE)fptr);
    00643     }
    00644     else {
    00645         return (int)io_flush_buffer_async((VALUE)fptr);
    00646     }
    00647 }
    00648
    00649 static int
    00650 io_fflush(rb_io_t *fptr)
    00651 {
    00652     rb_io_check_closed(fptr);
    00653     if (fptr->wbuf_len == 0)
    00654         return 0;
    00655     if (!rb_thread_fd_writable(fptr->fd)) {
    00656         rb_io_check_closed(fptr);
    00657     }
    00658     while (fptr->wbuf_len > 0 && io_flush_buffer(fptr) != 0) {
    00659         if (!rb_io_wait_writable(fptr->fd))
    00660             return -1;
    00661         rb_io_check_closed(fptr);
    00662     }
    00663     return 0;
    00664 }
    00665
    00666 #ifdef HAVE_RB_FD_INIT
    00667 static VALUE
    00668 wait_readable(VALUE p)
    00669 {
    00670     rb_fdset_t *rfds = (rb_fdset_t *)p;
    00671
    00672     return rb_thread_select(rb_fd_max(rfds), rb_fd_ptr(rfds), NULL, NULL, NULL);
    00673 }
    00674 #endif
    00675
    00676 int
    00677 rb_io_wait_readable(int f)
    00678 {
    00679     rb_fdset_t rfds;
    00680
    00681     if (f < 0) {
    00682         rb_raise(rb_eIOError, "closed stream");
    00683     }
    00684     switch (errno) {
    00685       case EINTR:
    00686 #if defined(ERESTART)
    00687       case ERESTART:
    00688 #endif
    00689         rb_thread_wait_fd(f);
    00690         return TRUE;
    00691
    00692       case EAGAIN:
    00693 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
    00694       case EWOULDBLOCK:
    00695 #endif
    00696         rb_fd_init(&rfds);
    00697         rb_fd_set(f, &rfds);
    00698 #ifdef HAVE_RB_FD_INIT
    00699         rb_ensure(wait_readable, (VALUE)&rfds,
    00700                   (VALUE (*)(VALUE))rb_fd_term, (VALUE)&rfds);
    00701 #else
    00702         rb_thread_select(f + 1, rb_fd_ptr(&rfds), NULL, NULL, NULL);
    00703 #endif
    00704         return TRUE;
    00705
    00706       default:
    00707         return FALSE;
    00708     }
    00709 }
    00710
    00711 #ifdef HAVE_RB_FD_INIT
    00712 static VALUE
    00713 wait_writable(VALUE p)
    00714 {
    00715     rb_fdset_t *wfds = (rb_fdset_t *)p;
    00716
    00717     return rb_thread_select(rb_fd_max(wfds), NULL, rb_fd_ptr(wfds), NULL, NULL);
    00718 }
    00719 #endif
    00720
    00721 int
    00722 rb_io_wait_writable(int f)
    00723 {
    00724     rb_fdset_t wfds;
    00725
    00726     if (f < 0) {
    00727         rb_raise(rb_eIOError, "closed stream");
    00728     }
    00729     switch (errno) {
    00730       case EINTR:
    00731 #if defined(ERESTART)
    00732       case ERESTART:
    00733 #endif
    00734         rb_thread_fd_writable(f);
    00735         return TRUE;
    00736
    00737       case EAGAIN:
    00738 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
    00739       case EWOULDBLOCK:
    00740 #endif
    00741         rb_fd_init(&wfds);
    00742         rb_fd_set(f, &wfds);
    00743 #ifdef HAVE_RB_FD_INIT
    00744         rb_ensure(wait_writable, (VALUE)&wfds,
    00745                   (VALUE (*)(VALUE))rb_fd_term, (VALUE)&wfds);
    00746 #else
    00747         rb_thread_select(f + 1, NULL, rb_fd_ptr(&wfds), NULL, NULL);
    00748 #endif
    00749         return TRUE;
    00750
    00751       default:
    00752         return FALSE;
    00753     }
    00754 }
    00755
    00756 static void
    00757 make_writeconv(rb_io_t *fptr)
    00758 {
    00759     if (!fptr->writeconv_initialized) {
    00760         const char *senc, *denc;
    00761         rb_encoding *enc;
    00762         int ecflags;
    00763         VALUE ecopts;
    00764
    00765         fptr->writeconv_initialized = 1;
    00766
    00767         ecflags = fptr->encs.ecflags;
    00768         ecopts = fptr->encs.ecopts;
    00769 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
    00770         if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr))
    00771             ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
    00772 #endif
    00773
    00774         if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
    00775             /* no encoding conversion */
    00776             fptr->writeconv_pre_ecflags = 0;
    00777             fptr->writeconv_pre_ecopts = Qnil;
    00778             fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
    00779             if (!fptr->writeconv)
    00780                 rb_exc_raise(rb_econv_open_exc("", "", ecflags));
    00781             fptr->writeconv_asciicompat = Qnil;
    00782         }
    00783         else {
    00784             enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
    00785             senc = rb_econv_asciicompat_encoding(rb_enc_name(enc));
    00786             if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
    00787                 /* single conversion */
    00788                 fptr->writeconv_pre_ecflags = ecflags;
    00789                 fptr->writeconv_pre_ecopts = ecopts;
    00790                 fptr->writeconv = NULL;
    00791                 fptr->writeconv_asciicompat = Qnil;
    00792             }
    00793             else {
    00794                 /* double conversion */
    00795                 fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_DECORATOR_MASK;
    00796                 fptr->writeconv_pre_ecopts = ecopts;
    00797                 if (senc) {
    00798                     denc = rb_enc_name(enc);
    00799                     fptr->writeconv_asciicompat = rb_str_new2(senc);
    00800                 }
    00801                 else {
    00802                     senc = denc = "";
    00803                     fptr->writeconv_asciicompat = rb_str_new2(rb_enc_name(enc));
    00804                 }
    00805                 ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_DECORATOR_MASK);
    00806                 ecopts = fptr->encs.ecopts;
    00807                 fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
    00808                 if (!fptr->writeconv)
    00809                     rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
    00810             }
    00811         }
    00812     }
    00813 }
    00814
    00815 /* writing functions */
    00816 struct binwrite_arg {
    00817     rb_io_t *fptr;
    00818     VALUE str;
    00819     long offset;
    00820     long length;
    00821 };
    00822
    00823 static VALUE
    00824 io_binwrite_string(VALUE arg)
    00825 {
    00826     struct binwrite_arg *p = (struct binwrite_arg *)arg;
    00827     long l = io_writable_length(p->fptr, p->length);
    00828     return rb_write_internal(p->fptr->fd, RSTRING_PTR(p->str)+p->offset, l);
    00829 }
    00830
    00831 static long
    00832 io_binwrite(VALUE str, rb_io_t *fptr, int nosync)
    00833 {
    00834     long len, n, r, offset = 0;
    00835
    00836     len = RSTRING_LEN(str);
    00837     if ((n = len) <= 0) return n;
    00838     if (fptr->wbuf == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
    00839         fptr->wbuf_off = 0;
    00840         fptr->wbuf_len = 0;
    00841         fptr->wbuf_capa = IO_WBUF_CAPA_MIN;
    00842         fptr->wbuf = ALLOC_N(char, fptr->wbuf_capa);
    00843         fptr->write_lock = rb_mutex_new();
    00844     }
    00845     if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
    00846         (fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len)) {
    00847         struct binwrite_arg arg;
    00848
    00849         /* xxx: use writev to avoid double write if available */
    00850         if (fptr->wbuf_len && fptr->wbuf_len+len <= fptr->wbuf_capa) {
    00851             if (fptr->wbuf_capa < fptr->wbuf_off+fptr->wbuf_len+len) {
    00852                 MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len);
    00853                 fptr->wbuf_off = 0;
    00854             }
    00855             MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING_PTR(str)+offset, char, len);
    00856             fptr->wbuf_len += (int)len;
    00857             n = 0;
    00858         }
    00859         if (io_fflush(fptr) < 0)
    00860             return -1L;
    00861         if (n == 0)
    00862             return len;
    00863         /* avoid context switch between "a" and "\n" in STDERR.puts "a".
    00864            [ruby-dev:25080] */
    00865         if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) {
    00866             rb_io_check_closed(fptr);
    00867         }
    00868         arg.fptr = fptr;
    00869         arg.str = str;
    00870       retry:
    00871         arg.offset = offset;
    00872         arg.length = n;
    00873         if (fptr->write_lock) {
    00874             r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
    00875         }
    00876         else {
    00877             long l = io_writable_length(fptr, n);
    00878             r = rb_write_internal(fptr->fd, RSTRING_PTR(str)+offset, l);
    00879         }
    00880         /* xxx: other threads may modify given string. */
    00881         if (r == n) return len;
    00882         if (0 <= r) {
    00883             offset += r;
    00884             n -= r;
    00885             errno = EAGAIN;
    00886         }
    00887         if (rb_io_wait_writable(fptr->fd)) {
    00888             rb_io_check_closed(fptr);
    00889             if (offset < RSTRING_LEN(str))
    00890                 goto retry;
    00891         }
    00892         return -1L;
    00893     }
    00894
    00895     if (fptr->wbuf_off) {
    00896         if (fptr->wbuf_len)
    00897             MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len);
    00898         fptr->wbuf_off = 0;
    00899     }
    00900     MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING_PTR(str)+offset, char, len);
    00901     fptr->wbuf_len += (int)len;
    00902     return len;
    00903 }
    00904
    00905 static VALUE
    00906 do_writeconv(VALUE str, rb_io_t *fptr)
    00907 {
    00908     if (NEED_WRITECONV(fptr)) {
    00909         VALUE common_encoding = Qnil;
    00910
    00911         make_writeconv(fptr);
    00912
    00913         if (fptr->writeconv) {
    00914             if (!NIL_P(fptr->writeconv_asciicompat))
    00915                 common_encoding = fptr->writeconv_asciicompat;
    00916             else if (!rb_enc_asciicompat(rb_enc_get(str))) {
    00917                 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
    00918                          rb_enc_name(rb_enc_get(str)));
    00919             }
    00920         }
    00921         else {
    00922             if (fptr->encs.enc2)
    00923                 common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
    00924             else if (fptr->encs.enc != rb_ascii8bit_encoding())
    00925                 common_encoding = rb_enc_from_encoding(fptr->encs.enc);
    00926         }
    00927
    00928         if (!NIL_P(common_encoding)) {
    00929             str = rb_str_encode(str, common_encoding,
    00930                 fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
    00931         }
    00932
    00933         if (fptr->writeconv) {
    00934             str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
    00935         }
    00936     }
    00937     return str;
    00938 }
    00939
    00940 static long
    00941 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
    00942 {
    00943     str = do_writeconv(str, fptr);
    00944     return io_binwrite(str, fptr, nosync);
    00945 }
    00946
    00947 static VALUE
    00948 io_write(VALUE io, VALUE str, int nosync)
    00949 {
    00950     rb_io_t *fptr;
    00951     long n;
    00952     VALUE tmp;
    00953
    00954     rb_secure(4);
    00955     io = GetWriteIO(io);
    00956     str = rb_obj_as_string(str);
    00957     tmp = rb_io_check_io(io);
    00958     if (NIL_P(tmp)) {
    00959         /* port is not IO, call write method for it. */
    00960         return rb_funcall(io, id_write, 1, str);
    00961     }
    00962     io = tmp;
    00963     if (RSTRING_LEN(str) == 0) return INT2FIX(0);
    00964
    00965     GetOpenFile(io, fptr);
    00966     rb_io_check_writable(fptr);
    00967
    00968     n = io_fwrite(str, fptr, nosync);
    00969     if (n == -1L) rb_sys_fail_path(fptr->pathv);
    00970
    00971     return LONG2FIX(n);
    00972 }
    00973
    00974 /*
    00975  *  call-seq:
    00976  *     ios.write(string)    -> integer
    00977  *
    00978  *  Writes the given string to <em>ios</em>. The stream must be opened
    00979  *  for writing. If the argument is not a string, it will be converted
    00980  *  to a string using <code>to_s</code>. Returns the number of bytes
    00981  *  written.
    00982  *
    00983  *     count = $stdout.write( "This is a test\n" )
    00984  *     puts "That was #{count} bytes of data"
    00985  *
    00986  *  <em>produces:</em>
    00987  *
    00988  *     This is a test
    00989  *     That was 15 bytes of data
    00990  */
    00991
    00992 static VALUE
    00993 io_write_m(VALUE io, VALUE str)
    00994 {
    00995     return io_write(io, str, 0);
    00996 }
    00997
    00998 VALUE
    00999 rb_io_write(VALUE io, VALUE str)
    01000 {
    01001     return rb_funcall(io, id_write, 1, str);
    01002 }
    01003
    01004 /*
    01005  *  call-seq:
    01006  *     ios << obj     -> ios
    01007  *
    01008  *  String Output---Writes <i>obj</i> to <em>ios</em>.
    01009  *  <i>obj</i> will be converted to a string using
    01010  *  <code>to_s</code>.
    01011  *
    01012  *     $stdout << "Hello " << "world!\n"
    01013  *
    01014  *  <em>produces:</em>
    01015  *
    01016  *     Hello world!
    01017  */
    01018
    01019
    01020 VALUE
    01021 rb_io_addstr(VALUE io, VALUE str)
    01022 {
    01023     rb_io_write(io, str);
    01024     return io;
    01025 }
    01026
    01027 /*
    01028  *  call-seq:
    01029  *     ios.flush    -> ios
    01030  *
    01031  *  Flushes any buffered data within <em>ios</em> to the underlying
    01032  *  operating system (note that this is Ruby internal buffering only;
    01033  *  the OS may buffer the data as well).
    01034  *
    01035  *     $stdout.print "no newline"
    01036  *     $stdout.flush
    01037  *
    01038  *  <em>produces:</em>
    01039  *
    01040  *     no newline
    01041  */
    01042
    01043 VALUE
    01044 rb_io_flush(VALUE io)
    01045 {
    01046     rb_io_t *fptr;
    01047
    01048     if (TYPE(io) != T_FILE) {
    01049         return rb_funcall(io, id_flush, 0);
    01050     }
    01051
    01052     io = GetWriteIO(io);
    01053     GetOpenFile(io, fptr);
    01054
    01055     if (fptr->mode & FMODE_WRITABLE) {
    01056         if (io_fflush(fptr) < 0)
    01057             rb_sys_fail(0);
    01058 #ifdef _WIN32
    01059         fsync(fptr->fd);
    01060 #endif
    01061     }
    01062     if (fptr->mode & FMODE_READABLE) {
    01063         io_unread(fptr);
    01064     }
    01065
    01066     return io;
    01067 }
    01068
    01069 /*
    01070  *  call-seq:
    01071  *     ios.pos     -> integer
    01072  *     ios.tell    -> integer
    01073  *
    01074  *  Returns the current offset (in bytes) of <em>ios</em>.
    01075  *
    01076  *     f = File.new("testfile")
    01077  *     f.pos    #=> 0
    01078  *     f.gets   #=> "This is line one\n"
    01079  *     f.pos    #=> 17
    01080  */
    01081
    01082 static VALUE
    01083 rb_io_tell(VALUE io)
    01084 {
    01085     rb_io_t *fptr;
    01086     off_t pos;
    01087
    01088     GetOpenFile(io, fptr);
    01089     pos = io_tell(fptr);
    01090     if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
    01091     pos -= fptr->rbuf_len;
    01092     return OFFT2NUM(pos);
    01093 }
    01094
    01095 static VALUE
    01096 rb_io_seek(VALUE io, VALUE offset, int whence)
    01097 {
    01098     rb_io_t *fptr;
    01099     off_t pos;
    01100
    01101     pos = NUM2OFFT(offset);
    01102     GetOpenFile(io, fptr);
    01103     pos = io_seek(fptr, pos, whence);
    01104     if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
    01105
    01106     return INT2FIX(0);
    01107 }
    01108
    01109 /*
    01110  *  call-seq:
    01111  *     ios.seek(amount, whence=IO::SEEK_SET)  ->  0
    01112  *
    01113  *  Seeks to a given offset <i>anInteger</i> in the stream according to
    01114  *  the value of <i>whence</i>:
    01115  *
    01116  *    IO::SEEK_CUR  | Seeks to _amount_ plus current position
    01117  *    --------------+----------------------------------------------------
    01118  *    IO::SEEK_END  | Seeks to _amount_ plus end of stream (you probably
    01119  *                  | want a negative value for _amount_)
    01120  *    --------------+----------------------------------------------------
    01121  *    IO::SEEK_SET  | Seeks to the absolute location given by _amount_
    01122  *
    01123  *  Example:
    01124  *
    01125  *     f = File.new("testfile")
    01126  *     f.seek(-13, IO::SEEK_END)   #=> 0
    01127  *     f.readline                  #=> "And so on...\n"
    01128  */
    01129
    01130 static VALUE
    01131 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
    01132 {
    01133     VALUE offset, ptrname;
    01134     int whence = SEEK_SET;
    01135
    01136     if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
    01137         whence = NUM2INT(ptrname);
    01138     }
    01139
    01140     return rb_io_seek(io, offset, whence);
    01141 }
    01142
    01143 /*
    01144  *  call-seq:
    01145  *     ios.pos = integer    -> integer
    01146  *
    01147  *  Seeks to the given position (in bytes) in <em>ios</em>.
    01148  *
    01149  *     f = File.new("testfile")
    01150  *     f.pos = 17
    01151  *     f.gets   #=> "This is line two\n"
    01152  */
    01153
    01154 static VALUE
    01155 rb_io_set_pos(VALUE io, VALUE offset)
    01156 {
    01157     rb_io_t *fptr;
    01158     off_t pos;
    01159
    01160     pos = NUM2OFFT(offset);
    01161     GetOpenFile(io, fptr);
    01162     pos = io_seek(fptr, pos, SEEK_SET);
    01163     if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
    01164
    01165     return OFFT2NUM(pos);
    01166 }
    01167
    01168 static void clear_readconv(rb_io_t *fptr);
    01169
    01170 /*
    01171  *  call-seq:
    01172  *     ios.rewind    -> 0
    01173  *
    01174  *  Positions <em>ios</em> to the beginning of input, resetting
    01175  *  <code>lineno</code> to zero.
    01176  *
    01177  *     f = File.new("testfile")
    01178  *     f.readline   #=> "This is line one\n"
    01179  *     f.rewind     #=> 0
    01180  *     f.lineno     #=> 0
    01181  *     f.readline   #=> "This is line one\n"
    01182  *
    01183  *  Note that it cannot be used with streams such as pipes, ttys, and sockets.
    01184  */
    01185
    01186 static VALUE
    01187 rb_io_rewind(VALUE io)
    01188 {
    01189     rb_io_t *fptr;
    01190
    01191     GetOpenFile(io, fptr);
    01192     if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
    01193     if (io == ARGF.current_file) {
    01194         ARGF.lineno -= fptr->lineno;
    01195     }
    01196     fptr->lineno = 0;
    01197     if (fptr->readconv) {
    01198         clear_readconv(fptr);
    01199     }
    01200
    01201     return INT2FIX(0);
    01202 }
    01203
    01204 static int
    01205 io_fillbuf(rb_io_t *fptr)
    01206 {
    01207     ssize_t r;
    01208
    01209     if (fptr->rbuf == NULL) {
    01210         fptr->rbuf_off = 0;
    01211         fptr->rbuf_len = 0;
    01212         fptr->rbuf_capa = IO_RBUF_CAPA_FOR(fptr);
    01213         fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
    01214 #ifdef _WIN32
    01215         fptr->rbuf_capa--;
    01216 #endif
    01217     }
    01218     if (fptr->rbuf_len == 0) {
    01219       retry:
    01220         {
    01221             r = rb_read_internal(fptr->fd, fptr->rbuf, fptr->rbuf_capa);
    01222         }
    01223         if (r < 0) {
    01224             if (rb_io_wait_readable(fptr->fd))
    01225                 goto retry;
    01226             rb_sys_fail_path(fptr->pathv);
    01227         }
    01228         fptr->rbuf_off = 0;
    01229         fptr->rbuf_len = (int)r; /* r should be <= rbuf_capa */
    01230         if (r == 0)
    01231             return -1; /* EOF */
    01232     }
    01233     return 0;
    01234 }
    01235
    01236 /*
    01237  *  call-seq:
    01238  *     ios.eof     -> true or false
    01239  *     ios.eof?    -> true or false
    01240  *
    01241  *  Returns true if <em>ios</em> is at end of file that means
    01242  *  there are no more data to read.
    01243  *  The stream must be opened for reading or an <code>IOError</code> will be
    01244  *  raised.
    01245  *
    01246  *     f = File.new("testfile")
    01247  *     dummy = f.readlines
    01248  *     f.eof   #=> true
    01249  *
    01250  *  If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
    01251  *  blocks until the other end sends some data or closes it.
    01252  *
    01253  *     r, w = IO.pipe
    01254  *     Thread.new { sleep 1; w.close }
    01255  *     r.eof?  #=> true after 1 second blocking
    01256  *
    01257  *     r, w = IO.pipe
    01258  *     Thread.new { sleep 1; w.puts "a" }
    01259  *     r.eof?  #=> false after 1 second blocking
    01260  *
    01261  *     r, w = IO.pipe
    01262  *     r.eof?  # blocks forever
    01263  *
    01264  *  Note that <code>IO#eof?</code> reads data to the input byte buffer.
    01265  *  So <code>IO#sysread</code> may not behave as you intend with
    01266  *  <code>IO#eof?</code>, unless you call <code>IO#rewind</code>
    01267  *  first (which is not available for some streams).
    01268  */
    01269
    01270 VALUE
    01271 rb_io_eof(VALUE io)
    01272 {
    01273     rb_io_t *fptr;
    01274
    01275     GetOpenFile(io, fptr);
    01276     rb_io_check_char_readable(fptr);
    01277
    01278     if (READ_CHAR_PENDING(fptr)) return Qfalse;
    01279     if (READ_DATA_PENDING(fptr)) return Qfalse;
    01280     READ_CHECK(fptr);
    01281     if (io_fillbuf(fptr) < 0) {
    01282         return Qtrue;
    01283     }
    01284     return Qfalse;
    01285 }
    01286
    01287 /*
    01288  *  call-seq:
    01289  *     ios.sync    -> true or false
    01290  *
    01291  *  Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
    01292  *  true, all output is immediately flushed to the underlying operating
    01293  *  system and is not buffered by Ruby internally. See also
    01294  *  <code>IO#fsync</code>.
    01295  *
    01296  *     f = File.new("testfile")
    01297  *     f.sync   #=> false
    01298  */
    01299
    01300 static VALUE
    01301 rb_io_sync(VALUE io)
    01302 {
    01303     rb_io_t *fptr;
    01304
    01305     io = GetWriteIO(io);
    01306     GetOpenFile(io, fptr);
    01307     return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
    01308 }
    01309
    01310 /*
    01311  *  call-seq:
    01312  *     ios.sync = boolean   -> boolean
    01313  *
    01314  *  Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
    01315  *  When sync mode is true, all output is immediately flushed to the
    01316  *  underlying operating system and is not buffered internally. Returns
    01317  *  the new state. See also <code>IO#fsync</code>.
    01318  *
    01319  *     f = File.new("testfile")
    01320  *     f.sync = true
    01321  *
    01322  *  <em>(produces no output)</em>
    01323  */
    01324
    01325 static VALUE
    01326 rb_io_set_sync(VALUE io, VALUE sync)
    01327 {
    01328     rb_io_t *fptr;
    01329
    01330     io = GetWriteIO(io);
    01331     GetOpenFile(io, fptr);
    01332     if (RTEST(sync)) {
    01333         fptr->mode |= FMODE_SYNC;
    01334     }
    01335     else {
    01336         fptr->mode &= ~FMODE_SYNC;
    01337     }
    01338     return sync;
    01339 }
    01340
    01341 #ifdef HAVE_FSYNC
    01342 /*
    01343  *  call-seq:
    01344  *     ios.fsync   -> 0 or nil
    01345  *
    01346  *  Immediately writes all buffered data in <em>ios</em> to disk.
    01347  *  Note that <code>fsync</code> differs from
    01348  *  using <code>IO#sync=</code>. The latter ensures that data is flushed
    01349  *  from Ruby's buffers, but doesn't not guarantee that the underlying
    01350  *  operating system actually writes it to disk.
    01351  *
    01352  *  <code>NotImplementedError</code> is raised
    01353  *  if the underlying operating system does not support <em>fsync(2)</em>.
    01354  */
    01355
    01356 static VALUE
    01357 rb_io_fsync(VALUE io)
    01358 {
    01359     rb_io_t *fptr;
    01360
    01361     io = GetWriteIO(io);
    01362     GetOpenFile(io, fptr);
    01363
    01364     if (io_fflush(fptr) < 0)
    01365         rb_sys_fail(0);
    01366     if (fsync(fptr->fd) < 0)
    01367         rb_sys_fail_path(fptr->pathv);
    01368     return INT2FIX(0);
    01369 }
    01370 #else
    01371 #define rb_io_fsync rb_f_notimplement
    01372 #endif
    01373
    01374 #ifdef HAVE_FDATASYNC
    01375 /*
    01376  *  call-seq:
    01377  *     ios.fdatasync   -> 0 or nil
    01378  *
    01379  *  Immediately writes all buffered data in <em>ios</em> to disk.
    01380  *
    01381  *  <code>NotImplementedError</code> is raised
    01382  *  if the underlying operating system does not support <em>fdatasync(2)</em>.
    01383  */
    01384
    01385 static VALUE
    01386 rb_io_fdatasync(VALUE io)
    01387 {
    01388     rb_io_t *fptr;
    01389
    01390     io = GetWriteIO(io);
    01391     GetOpenFile(io, fptr);
    01392
    01393     if (io_fflush(fptr) < 0)
    01394         rb_sys_fail(0);
    01395     if (fdatasync(fptr->fd) < 0)
    01396         rb_sys_fail_path(fptr->pathv);
    01397     return INT2FIX(0);
    01398 }
    01399 #else
    01400 #define rb_io_fdatasync rb_f_notimplement
    01401 #endif
    01402
    01403 /*
    01404  *  call-seq:
    01405  *     ios.fileno    -> fixnum
    01406  *     ios.to_i      -> fixnum
    01407  *
    01408  *  Returns an integer representing the numeric file descriptor for
    01409  *  <em>ios</em>.
    01410  *
    01411  *     $stdin.fileno    #=> 0
    01412  *     $stdout.fileno   #=> 1
    01413  */
    01414
    01415 static VALUE
    01416 rb_io_fileno(VALUE io)
    01417 {
    01418     rb_io_t *fptr;
    01419     int fd;
    01420
    01421     GetOpenFile(io, fptr);
    01422     fd = fptr->fd;
    01423     return INT2FIX(fd);
    01424 }
    01425
    01426
    01427 /*
    01428  *  call-seq:
    01429  *     ios.pid    -> fixnum
    01430  *
    01431  *  Returns the process ID of a child process associated with
    01432  *  <em>ios</em>. This will be set by <code>IO.popen</code>.
    01433  *
    01434  *     pipe = IO.popen("-")
    01435  *     if pipe
    01436  *       $stderr.puts "In parent, child pid is #{pipe.pid}"
    01437  *     else
    01438  *       $stderr.puts "In child, pid is #{$$}"
    01439  *     end
    01440  *
    01441  *  <em>produces:</em>
    01442  *
    01443  *     In child, pid is 26209
    01444  *     In parent, child pid is 26209
    01445  */
    01446
    01447 static VALUE
    01448 rb_io_pid(VALUE io)
    01449 {
    01450     rb_io_t *fptr;
    01451
    01452     GetOpenFile(io, fptr);
    01453     if (!fptr->pid)
    01454         return Qnil;
    01455     return PIDT2NUM(fptr->pid);
    01456 }
    01457
    01458
    01459 /*
    01460  * call-seq:
    01461  *   ios.inspect   -> string
    01462  *
    01463  * Return a string describing this IO object.
    01464  */
    01465
    01466 static VALUE
    01467 rb_io_inspect(VALUE obj)
    01468 {
    01469     rb_io_t *fptr;
    01470     const char *cname;
    01471     char fd_desc[4+sizeof(int)*3];
    01472     const char *path;
    01473     const char *st = "";
    01474
    01475     fptr = RFILE(rb_io_taint_check(obj))->fptr;
    01476     if (!fptr) return rb_any_to_s(obj);
    01477     cname = rb_obj_classname(obj);
    01478     if (NIL_P(fptr->pathv)) {
    01479         if (fptr->fd < 0) {
    01480             path = "";
    01481             st = "(closed)";
    01482         }
    01483         else {
    01484             snprintf(fd_desc, sizeof(fd_desc), "fd %d", fptr->fd);
    01485             path = fd_desc;
    01486         }
    01487     }
    01488     else {
    01489         path = RSTRING_PTR(fptr->pathv);
    01490         if (fptr->fd < 0) {
    01491             st = " (closed)";
    01492         }
    01493     }
    01494     return rb_sprintf("#<%s:%s%s>", cname, path, st);
    01495 }
    01496
    01497 /*
    01498  *  call-seq:
    01499  *     ios.to_io  ->  ios
    01500  *
    01501  *  Returns <em>ios</em>.
    01502  */
    01503
    01504 static VALUE
    01505 rb_io_to_io(VALUE io)
    01506 {
    01507     return io;
    01508 }
    01509
    01510 /* reading functions */
    01511 static long
    01512 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
    01513 {
    01514     int n;
    01515
    01516     n = READ_DATA_PENDING_COUNT(fptr);
    01517     if (n <= 0) return 0;
    01518     if (n > len) n = (int)len;
    01519     MEMMOVE(ptr, fptr->rbuf+fptr->rbuf_off, char, n);
    01520     fptr->rbuf_off += n;
    01521     fptr->rbuf_len -= n;
    01522     return n;
    01523 }
    01524
    01525 static long
    01526 io_fread(VALUE str, long offset, rb_io_t *fptr)
    01527 {
    01528     long len = RSTRING_LEN(str) - offset;
    01529     long n = len;
    01530     long c;
    01531
    01532     rb_str_locktmp(str);
    01533     if (READ_DATA_PENDING(fptr) == 0) {
    01534         while (n > 0) {
    01535           again:
    01536             c = rb_read_internal(fptr->fd, RSTRING_PTR(str)+offset, n);
    01537             if (c == 0) break;
    01538             if (c < 0) {
    01539                 if (rb_io_wait_readable(fptr->fd))
    01540                     goto again;
    01541                 rb_sys_fail_path(fptr->pathv);
    01542             }
    01543             offset += c;
    01544             if ((n -= c) <= 0) break;
    01545             rb_thread_wait_fd(fptr->fd);
    01546         }
    01547         rb_str_unlocktmp(str);
    01548         return len - n;
    01549     }
    01550
    01551     while (n > 0) {
    01552         c = read_buffered_data(RSTRING_PTR(str)+offset, n, fptr);
    01553         if (c > 0) {
    01554             offset += c;
    01555             if ((n -= c) <= 0) break;
    01556         }
    01557         rb_thread_wait_fd(fptr->fd);
    01558         rb_io_check_closed(fptr);
    01559         if (io_fillbuf(fptr) < 0) {
    01560             break;
    01561         }
    01562     }
    01563     rb_str_unlocktmp(str);
    01564     return len - n;
    01565 }
    01566
    01567 #define SMALLBUF 100
    01568
    01569 static long
    01570 remain_size(rb_io_t *fptr)
    01571 {
    01572     struct stat st;
    01573     off_t siz = READ_DATA_PENDING_COUNT(fptr);
    01574     off_t pos;
    01575
    01576     if (fstat(fptr->fd, &st) == 0  && S_ISREG(st.st_mode)
    01577 #if defined(__BEOS__) || defined(__HAIKU__)
    01578         && (st.st_dev > 3)
    01579 #endif
    01580         )
    01581     {
    01582         if (io_fflush(fptr) < 0)
    01583             rb_sys_fail(0);
    01584         pos = lseek(fptr->fd, 0, SEEK_CUR);
    01585         if (st.st_size >= pos && pos >= 0) {
    01586             siz += st.st_size - pos;
    01587             if (siz > LONG_MAX) {
    01588                 rb_raise(rb_eIOError, "file too big for single read");
    01589             }
    01590         }
    01591     }
    01592     else {
    01593         siz += BUFSIZ;
    01594     }
    01595     return (long)siz;
    01596 }
    01597
    01598 static VALUE
    01599 io_enc_str(VALUE str, rb_io_t *fptr)
    01600 {
    01601     OBJ_TAINT(str);
    01602     rb_enc_associate(str, io_read_encoding(fptr));
    01603     return str;
    01604 }
    01605
    01606 static void
    01607 make_readconv(rb_io_t *fptr, int size)
    01608 {
    01609     if (!fptr->readconv) {
    01610         int ecflags;
    01611         VALUE ecopts;
    01612         const char *sname, *dname;
    01613         ecflags = fptr->encs.ecflags;
    01614         ecopts = fptr->encs.ecopts;
    01615         if (NEED_NEWLINE_DECORATOR_ON_READ(fptr))
    01616             ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
    01617         if (fptr->encs.enc2) {
    01618             sname = rb_enc_name(fptr->encs.enc2);
    01619             dname = rb_enc_name(fptr->encs.enc);
    01620         }
    01621         else {
    01622             sname = dname = "";
    01623         }
    01624         fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
    01625         if (!fptr->readconv)
    01626             rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
    01627         fptr->cbuf_off = 0;
    01628         fptr->cbuf_len = 0;
    01629         if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
    01630         fptr->cbuf_capa = size;
    01631         fptr->cbuf = ALLOC_N(char, fptr->cbuf_capa);
    01632     }
    01633 }
    01634
    01635 #define MORE_CHAR_SUSPENDED Qtrue
    01636 #define MORE_CHAR_FINISHED Qnil
    01637 static VALUE
    01638 fill_cbuf(rb_io_t *fptr, int ec_flags)
    01639 {
    01640     const unsigned char *ss, *sp, *se;
    01641     unsigned char *ds, *dp, *de;
    01642     rb_econv_result_t res;
    01643     int putbackable;
    01644     int cbuf_len0;
    01645     VALUE exc;
    01646
    01647     ec_flags |= ECONV_PARTIAL_INPUT;
    01648
    01649     if (fptr->cbuf_len == fptr->cbuf_capa)
    01650         return MORE_CHAR_SUSPENDED; /* cbuf full */
    01651     if (fptr->cbuf_len == 0)
    01652         fptr->cbuf_off = 0;
    01653     else if (fptr->cbuf_off + fptr->cbuf_len == fptr->cbuf_capa) {
    01654         memmove(fptr->cbuf, fptr->cbuf+fptr->cbuf_off, fptr->cbuf_len);
    01655         fptr->cbuf_off = 0;
    01656     }
    01657
    01658     cbuf_len0 = fptr->cbuf_len;
    01659
    01660     while (1) {
    01661         ss = sp = (const unsigned char *)fptr->rbuf + fptr->rbuf_off;
    01662         se = sp + fptr->rbuf_len;
    01663         ds = dp = (unsigned char *)fptr->cbuf + fptr->cbuf_off + fptr->cbuf_len;
    01664         de = (unsigned char *)fptr->cbuf + fptr->cbuf_capa;
    01665         res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
    01666         fptr->rbuf_off += (int)(sp - ss);
    01667         fptr->rbuf_len -= (int)(sp - ss);
    01668         fptr->cbuf_len += (int)(dp - ds);
    01669
    01670         putbackable = rb_econv_putbackable(fptr->readconv);
    01671         if (putbackable) {
    01672             rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf + fptr->rbuf_off - putbackable, putbackable);
    01673             fptr->rbuf_off -= putbackable;
    01674             fptr->rbuf_len += putbackable;
    01675         }
    01676
    01677         exc = rb_econv_make_exception(fptr->readconv);
    01678         if (!NIL_P(exc))
    01679             return exc;
    01680
    01681         if (cbuf_len0 != fptr->cbuf_len)
    01682             return MORE_CHAR_SUSPENDED;
    01683
    01684         if (res == econv_finished) {
    01685             return MORE_CHAR_FINISHED;
    01686         }
    01687
    01688         if (res == econv_source_buffer_empty) {
    01689             if (fptr->rbuf_len == 0) {
    01690                 READ_CHECK(fptr);
    01691                 if (io_fillbuf(fptr) == -1) {
    01692                     ds = dp = (unsigned char *)fptr->cbuf + fptr->cbuf_off + fptr->cbuf_len;
    01693                     de = (unsigned char *)fptr->cbuf + fptr->cbuf_capa;
    01694                     res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
    01695                     fptr->cbuf_len += (int)(dp - ds);
    01696                     rb_econv_check_error(fptr->readconv);
    01697                 }
    01698             }
    01699         }
    01700     }
    01701 }
    01702
    01703 static VALUE
    01704 more_char(rb_io_t *fptr)
    01705 {
    01706     VALUE v;
    01707     v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
    01708     if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
    01709         rb_exc_raise(v);
    01710     return v;
    01711 }
    01712
    01713 static VALUE
    01714 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
    01715 {
    01716     VALUE str = Qnil;
    01717     if (strp) {
    01718         str = *strp;
    01719         if (NIL_P(str)) {
    01720             *strp = str = rb_str_new(fptr->cbuf+fptr->cbuf_off, len);
    01721         }
    01722         else {
    01723             rb_str_cat(str, fptr->cbuf+fptr->cbuf_off, len);
    01724         }
    01725         OBJ_TAINT(str);
    01726         rb_enc_associate(str, fptr->encs.enc);
    01727     }
    01728     fptr->cbuf_off += len;
    01729     fptr->cbuf_len -= len;
    01730     /* xxx: set coderange */
    01731     if (fptr->cbuf_len == 0)
    01732         fptr->cbuf_off = 0;
    01733     else if (fptr->cbuf_capa/2 < fptr->cbuf_off) {
    01734         memmove(fptr->cbuf, fptr->cbuf+fptr->cbuf_off, fptr->cbuf_len);
    01735         fptr->cbuf_off = 0;
    01736     }
    01737     return str;
    01738 }
    01739
    01740 static void
    01741 io_setstrbuf(VALUE *str,long len)
    01742 {
    01743 #ifdef _WIN32
    01744     if (NIL_P(*str)) {
    01745         *str = rb_str_new(0, len+1);
    01746         rb_str_set_len(*str,len);
    01747     }
    01748     else {
    01749         StringValue(*str);
    01750         rb_str_modify(*str);
    01751         rb_str_resize(*str, len+1);
    01752         rb_str_set_len(*str,len);
    01753     }
    01754 #else
    01755     if (NIL_P(*str)) {
    01756         *str = rb_str_new(0, len);
    01757     }
    01758     else {
    01759         StringValue(*str);
    01760         rb_str_modify(*str);
    01761         rb_str_resize(*str, len);
    01762     }
    01763 #endif
    01764 }
    01765
    01766 static VALUE
    01767 read_all(rb_io_t *fptr, long siz, VALUE str)
    01768 {
    01769     long bytes;
    01770     long n;
    01771     long pos;
    01772     rb_encoding *enc;
    01773     int cr;
    01774
    01775     if (NEED_READCONV(fptr)) {
    01776         io_setstrbuf(&str,0);
    01777         make_readconv(fptr, 0);
    01778         while (1) {
    01779             VALUE v;
    01780             if (fptr->cbuf_len) {
    01781                 io_shift_cbuf(fptr, fptr->cbuf_len, &str);
    01782             }
    01783             v = fill_cbuf(fptr, 0);
    01784             if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
    01785                 if (fptr->cbuf_len) {
    01786                     io_shift_cbuf(fptr, fptr->cbuf_len, &str);
    01787                 }
    01788                 rb_exc_raise(v);
    01789             }
    01790             if (v == MORE_CHAR_FINISHED) {
    01791                 clear_readconv(fptr);
    01792                 return io_enc_str(str, fptr);
    01793             }
    01794         }
    01795     }
    01796
    01797     bytes = 0;
    01798     pos = 0;
    01799
    01800     enc = io_read_encoding(fptr);
    01801     cr = 0;
    01802
    01803     if (siz == 0) siz = BUFSIZ;
    01804     io_setstrbuf(&str,siz);
    01805     for (;;) {
    01806         READ_CHECK(fptr);
    01807         n = io_fread(str, bytes, fptr);
    01808         if (n == 0 && bytes == 0) {
    01809             break;
    01810         }
    01811         bytes += n;
    01812         if (cr != ENC_CODERANGE_BROKEN)
    01813             pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
    01814         if (bytes < siz) break;
    01815         siz += BUFSIZ;
    01816         rb_str_resize(str, siz);
    01817     }
    01818     if (bytes != siz) rb_str_resize(str, bytes);
    01819     str = io_enc_str(str, fptr);
    01820     ENC_CODERANGE_SET(str, cr);
    01821     return str;
    01822 }
    01823
    01824 void
    01825 rb_io_set_nonblock(rb_io_t *fptr)
    01826 {
    01827     int oflags;
    01828 #ifdef F_GETFL
    01829     oflags = fcntl(fptr->fd, F_GETFL);
    01830     if (oflags == -1) {
    01831         rb_sys_fail_path(fptr->pathv);
    01832     }
    01833 #else
    01834     oflags = 0;
    01835 #endif
    01836     if ((oflags & O_NONBLOCK) == 0) {
    01837         oflags |= O_NONBLOCK;
    01838         if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
    01839             rb_sys_fail_path(fptr->pathv);
    01840         }
    01841     }
    01842 }
    01843
    01844 static VALUE
    01845 io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
    01846 {
    01847     rb_io_t *fptr;
    01848     VALUE length, str;
    01849     long n, len;
    01850
    01851     rb_scan_args(argc, argv, "11", &length, &str);
    01852
    01853     if ((len = NUM2LONG(length)) < 0) {
    01854         rb_raise(rb_eArgError, "negative length %ld given", len);
    01855     }
    01856
    01857     io_setstrbuf(&str,len);
    01858     OBJ_TAINT(str);
    01859
    01860     GetOpenFile(io, fptr);
    01861     rb_io_check_byte_readable(fptr);
    01862
    01863     if (len == 0)
    01864         return str;
    01865
    01866     if (!nonblock)
    01867         READ_CHECK(fptr);
    01868     n = read_buffered_data(RSTRING_PTR(str), len, fptr);
    01869     if (n <= 0) {
    01870       again:
    01871         if (nonblock) {
    01872             rb_io_set_nonblock(fptr);
    01873         }
    01874         rb_str_locktmp(str);
    01875         n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
    01876         rb_str_unlocktmp(str);
    01877         if (n < 0) {
    01878             if (!nonblock && rb_io_wait_readable(fptr->fd))
    01879                 goto again;
    01880             if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
    01881                 rb_mod_sys_fail(rb_mWaitReadable, "read would block");
    01882             rb_sys_fail_path(fptr->pathv);
    01883         }
    01884     }
    01885     rb_str_resize(str, n);
    01886
    01887     if (n == 0)
    01888         return Qnil;
    01889     else
    01890         return str;
    01891 }
    01892
    01893 /*
    01894  *  call-seq:
    01895  *     ios.readpartial(maxlen)              -> string
    01896  *     ios.readpartial(maxlen, outbuf)      -> outbuf
    01897  *
    01898  *  Reads at most <i>maxlen</i> bytes from the I/O stream.
    01899  *  It blocks only if <em>ios</em> has no data immediately available.
    01900  *  It doesn't block if some data available.
    01901  *  If the optional <i>outbuf</i> argument is present,
    01902  *  it must reference a String, which will receive the data.
    01903  *  It raises <code>EOFError</code> on end of file.
    01904  *
    01905  *  readpartial is designed for streams such as pipe, socket, tty, etc.
    01906  *  It blocks only when no data immediately available.
    01907  *  This means that it blocks only when following all conditions hold.
    01908  *  * the byte buffer in the IO object is empty.
    01909  *  * the content of the stream is empty.
    01910  *  * the stream is not reached to EOF.
    01911  *
    01912  *  When readpartial blocks, it waits data or EOF on the stream.
    01913  *  If some data is reached, readpartial returns with the data.
    01914  *  If EOF is reached, readpartial raises EOFError.
    01915  *
    01916  *  When readpartial doesn't blocks, it returns or raises immediately.
    01917  *  If the byte buffer is not empty, it returns the data in the buffer.
    01918  *  Otherwise if the stream has some content,
    01919  *  it returns the data in the stream.
    01920  *  Otherwise if the stream is reached to EOF, it raises EOFError.
    01921  *
    01922  *     r, w = IO.pipe           #               buffer          pipe content
    01923  *     w << "abc"               #               ""              "abc".
    01924  *     r.readpartial(4096)      #=> "abc"       ""              ""
    01925  *     r.readpartial(4096)      # blocks because buffer and pipe is empty.
    01926  *
    01927  *     r, w = IO.pipe           #               buffer          pipe content
    01928  *     w << "abc"               #               ""              "abc"
    01929  *     w.close                  #               ""              "abc" EOF
    01930  *     r.readpartial(4096)      #=> "abc"       ""              EOF
    01931  *     r.readpartial(4096)      # raises EOFError
    01932  *
    01933  *     r, w = IO.pipe           #               buffer          pipe content
    01934  *     w << "abc\ndef\n"        #               ""              "abc\ndef\n"
    01935  *     r.gets                   #=> "abc\n"     "def\n"         ""
    01936  *     w << "ghi\n"             #               "def\n"         "ghi\n"
    01937  *     r.readpartial(4096)      #=> "def\n"     ""              "ghi\n"
    01938  *     r.readpartial(4096)      #=> "ghi\n"     ""              ""
    01939  *
    01940  *  Note that readpartial behaves similar to sysread.
    01941  *  The differences are:
    01942  *  * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)".
    01943  *  * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR.  When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
    01944  *
    01945  *  The later means that readpartial is nonblocking-flag insensitive.
    01946  *  It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
    01947  *
    01948  */
    01949
    01950 static VALUE
    01951 io_readpartial(int argc, VALUE *argv, VALUE io)
    01952 {
    01953     VALUE ret;
    01954
    01955     ret = io_getpartial(argc, argv, io, 0);
    01956     if (NIL_P(ret))
    01957         rb_eof_error();
    01958     else
    01959         return ret;
    01960 }
    01961
    01962 /*
    01963  *  call-seq:
    01964  *     ios.read_nonblock(maxlen)              -> string
    01965  *     ios.read_nonblock(maxlen, outbuf)      -> outbuf
    01966  *
    01967  *  Reads at most <i>maxlen</i> bytes from <em>ios</em> using
    01968  *  the read(2) system call after O_NONBLOCK is set for
    01969  *  the underlying file descriptor.
    01970  *
    01971  *  If the optional <i>outbuf</i> argument is present,
    01972  *  it must reference a String, which will receive the data.
    01973  *
    01974  *  read_nonblock just calls the read(2) system call.
    01975  *  It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
    01976  *  The caller should care such errors.
    01977  *
    01978  *  If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
    01979  *  it is extended by IO::WaitReadable.
    01980  *  So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
    01981  *
    01982  *  read_nonblock causes EOFError on EOF.
    01983  *
    01984  *  If the read byte buffer is not empty,
    01985  *  read_nonblock reads from the buffer like readpartial.
    01986  *  In this case, the read(2) system call is not called.
    01987  *
    01988  *  When read_nonblock raises an exception kind of IO::WaitReadable,
    01989  *  read_nonblock should not be called
    01990  *  until io is readable for avoiding busy loop.
    01991  *  This can be done as follows.
    01992  *
    01993  *    # emulates blocking read (readpartial).
    01994  *    begin
    01995  *      result = io.read_nonblock(maxlen)
    01996  *    rescue IO::WaitReadable
    01997  *      IO.select([io])
    01998  *      retry
    01999  *    end
    02000  *
    02001  *  Although IO#read_nonblock doesn't raise IO::WaitWritable.
    02002  *  OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable.
    02003  *  If IO and SSL should be used polymorphically,
    02004  *  IO::WaitWritable should be rescued too.
    02005  *  See the document of OpenSSL::Buffering#read_nonblock for sample code.
    02006  *
    02007  *  Note that this method is identical to readpartial
    02008  *  except the non-blocking flag is set.
    02009  */
    02010
    02011 static VALUE
    02012 io_read_nonblock(int argc, VALUE *argv, VALUE io)
    02013 {
    02014     VALUE ret;
    02015
    02016     ret = io_getpartial(argc, argv, io, 1);
    02017     if (NIL_P(ret))
    02018         rb_eof_error();
    02019     else
    02020         return ret;
    02021 }
    02022
    02023 /*
    02024  *  call-seq:
    02025  *     ios.write_nonblock(string)   -> integer
    02026  *
    02027  *  Writes the given string to <em>ios</em> using
    02028  *  the write(2) system call after O_NONBLOCK is set for
    02029  *  the underlying file descriptor.
    02030  *
    02031  *  It returns the number of bytes written.
    02032  *
    02033  *  write_nonblock just calls the write(2) system call.
    02034  *  It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
    02035  *  The result may also be smaller than string.length (partial write).
    02036  *  The caller should care such errors and partial write.
    02037  *
    02038  *  If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
    02039  *  it is extended by IO::WaitWritable.
    02040  *  So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.
    02041  *
    02042  *    # Creates a pipe.
    02043  *    r, w = IO.pipe
    02044  *
    02045  *    # write_nonblock writes only 65536 bytes and return 65536.
    02046  *    # (The pipe size is 65536 bytes on this environment.)
    02047  *    s = "a" * 100000
    02048  *    p w.write_nonblock(s)     #=> 65536
    02049  *
    02050  *    # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
    02051  *    p w.write_nonblock("b")   # Resource temporarily unavailable (Errno::EAGAIN)
    02052  *
    02053  *  If the write buffer is not empty, it is flushed at first.
    02054  *
    02055  *  When write_nonblock raises an exception kind of IO::WaitWritable,
    02056  *  write_nonblock should not be called
    02057  *  until io is writable for avoiding busy loop.
    02058  *  This can be done as follows.
    02059  *
    02060  *    begin
    02061  *      result = io.write_nonblock(string)
    02062  *    rescue IO::WaitWritable, Errno::EINTR
    02063  *      IO.select(nil, [io])
    02064  *      retry
    02065  *    end
    02066  *
    02067  *  Note that this doesn't guarantee to write all data in string.
    02068  *  The length written is reported as result and it should be checked later.
    02069  *
    02070  *  On some platforms such as Windows, write_nonblock is not supported
    02071  *  according to the kind of the IO object.
    02072  *  In such cases, write_nonblock raises <code>Errno::EBADF</code>.
    02073  *
    02074  */
    02075
    02076 static VALUE
    02077 rb_io_write_nonblock(VALUE io, VALUE str)
    02078 {
    02079     rb_io_t *fptr;
    02080     long n;
    02081
    02082     rb_secure(4);
    02083     if (TYPE(str) != T_STRING)
    02084         str = rb_obj_as_string(str);
    02085
    02086     io = GetWriteIO(io);
    02087     GetOpenFile(io, fptr);
    02088     rb_io_check_writable(fptr);
    02089
    02090     if (io_fflush(fptr) < 0)
    02091         rb_sys_fail(0);
    02092
    02093     rb_io_set_nonblock(fptr);
    02094     n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
    02095
    02096     if (n == -1) {
    02097         if (errno == EWOULDBLOCK || errno == EAGAIN)
    02098             rb_mod_sys_fail(rb_mWaitWritable, "write would block");
    02099         rb_sys_fail_path(fptr->pathv);
    02100     }
    02101
    02102     return LONG2FIX(n);
    02103 }
    02104
    02105 /*
    02106  *  call-seq:
    02107  *     ios.read([length [, buffer]])    -> string, buffer, or nil
    02108  *
    02109  *  Reads <i>length</i> bytes from the I/O stream.
    02110  *
    02111  *  <i>length</i> must be a non-negative integer or <code>nil</code>.
    02112  *
    02113  *  If <i>length</i> is a positive integer,
    02114  *  it try to read <i>length</i> bytes without any conversion (binary mode).
    02115  *  It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes.
    02116  *  <code>nil</code> means it met EOF at beginning.
    02117  *  The 1 to <i>length</i>-1 bytes string means it met EOF after reading the result.
    02118  *  The <i>length</i> bytes string means it doesn't meet EOF.
    02119  *  The resulted string is always ASCII-8BIT encoding.
    02120  *
    02121  *  If <i>length</i> is omitted or is <code>nil</code>,
    02122  *  it reads until EOF and the encoding conversion is applied.
    02123  *  It returns a string even if EOF is met at beginning.
    02124  *
    02125  *  If <i>length</i> is zero, it returns <code>""</code>.
    02126  *
    02127  *  If the optional <i>buffer</i> argument is present, it must reference
    02128  *  a String, which will receive the data.
    02129  *
    02130  *  At end of file, it returns <code>nil</code> or <code>""</code>
    02131  *  depend on <i>length</i>.
    02132  *  <code><i>ios</i>.read()</code> and
    02133  *  <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
    02134  *  <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>.
    02135  *
    02136  *     f = File.new("testfile")
    02137  *     f.read(16)   #=> "This is line one"
    02138  *
    02139  *     # reads whole file
    02140  *     open("file") {|f|
    02141  *       data = f.read # This returns a string even if the file is empty.
    02142  *       ...
    02143  *     }
    02144  *
    02145  *     # iterate over fixed length records.
    02146  *     open("fixed-record-file") {|f|
    02147  *       while record = f.read(256)
    02148  *         ...
    02149  *       end
    02150  *     }
    02151  *
    02152  *     # iterate over variable length records.
    02153  *     # record is prefixed by 32-bit length.
    02154  *     open("variable-record-file") {|f|
    02155  *       while len = f.read(4)
    02156  *         len = len.unpack("N")[0] # 32-bit length
    02157  *         record = f.read(len) # This returns a string even if len is 0.
    02158  *       end
    02159  *     }
    02160  *
    02161  *  Note that this method behaves like fread() function in C.
    02162  *  If you need the behavior like read(2) system call,
    02163  *  consider readpartial, read_nonblock and sysread.
    02164  */
    02165
    02166 static VALUE
    02167 io_read(int argc, VALUE *argv, VALUE io)
    02168 {
    02169     rb_io_t *fptr;
    02170     long n, len;
    02171     VALUE length, str;
    02172
    02173     rb_scan_args(argc, argv, "02", &length, &str);
    02174
    02175     if (NIL_P(length)) {
    02176         GetOpenFile(io, fptr);
    02177         rb_io_check_char_readable(fptr);
    02178         return read_all(fptr, remain_size(fptr), str);
    02179     }
    02180     len = NUM2LONG(length);
    02181     if (len < 0) {
    02182         rb_raise(rb_eArgError, "negative length %ld given", len);
    02183     }
    02184
    02185     io_setstrbuf(&str,len);
    02186
    02187     GetOpenFile(io, fptr);
    02188     rb_io_check_byte_readable(fptr);
    02189     if (len == 0) return str;
    02190
    02191     READ_CHECK(fptr);
    02192     n = io_fread(str, 0, fptr);
    02193     if (n == 0) {
    02194         if (fptr->fd < 0) return Qnil;
    02195         rb_str_resize(str, 0);
    02196         return Qnil;
    02197     }
    02198     rb_str_resize(str, n);
    02199     OBJ_TAINT(str);
    02200
    02201     return str;
    02202 }
    02203
    02204 static void
    02205 rscheck(const char *rsptr, long rslen, VALUE rs)
    02206 {
    02207     if (!rs) return;
    02208     if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
    02209         rb_raise(rb_eRuntimeError, "rs modified");
    02210 }
    02211
    02212 static int
    02213 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
    02214 {
    02215     VALUE str = *strp;
    02216     long limit = *lp;
    02217
    02218     if (NEED_READCONV(fptr)) {
    02219         make_readconv(fptr, 0);
    02220         do {
    02221             const char *p, *e;
    02222             int searchlen;
    02223             if (fptr->cbuf_len) {
    02224                 p = fptr->cbuf+fptr->cbuf_off;
    02225                 searchlen = fptr->cbuf_len;
    02226                 if (0 < limit && limit < searchlen)
    02227                     searchlen = (int)limit;
    02228                 e = memchr(p, delim, searchlen);
    02229                 if (e) {
    02230                     int len = (int)(e-p+1);
    02231                     if (NIL_P(str))
    02232                         *strp = str = rb_str_new(p, len);
    02233                     else
    02234                         rb_str_buf_cat(str, p, len);
    02235                     fptr->cbuf_off += len;
    02236                     fptr->cbuf_len -= len;
    02237                     limit -= len;
    02238                     *lp = limit;
    02239                     return delim;
    02240                 }
    02241
    02242                 if (NIL_P(str))
    02243                     *strp = str = rb_str_new(p, searchlen);
    02244                 else
    02245                     rb_str_buf_cat(str, p, searchlen);
    02246                 fptr->cbuf_off += searchlen;
    02247                 fptr->cbuf_len -= searchlen;
    02248                 limit -= searchlen;
    02249
    02250                 if (limit == 0) {
    02251                     *lp = limit;
    02252                     return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
    02253                 }
    02254             }
    02255         } while (more_char(fptr) != MORE_CHAR_FINISHED);
    02256         clear_readconv(fptr);
    02257         *lp = limit;
    02258         return EOF;
    02259     }
    02260
    02261     do {
    02262         long pending = READ_DATA_PENDING_COUNT(fptr);
    02263         if (pending > 0) {
    02264             const char *p = READ_DATA_PENDING_PTR(fptr);
    02265             const char *e;
    02266             long last;
    02267
    02268             if (limit > 0 && pending > limit) pending = limit;
    02269             e = memchr(p, delim, pending);
    02270             if (e) pending = e - p + 1;
    02271             if (!NIL_P(str)) {
    02272                 last = RSTRING_LEN(str);
    02273                 rb_str_resize(str, last + pending);
    02274             }
    02275             else {
    02276                 last = 0;
    02277                 *strp = str = rb_str_buf_new(pending);
    02278                 rb_str_set_len(str, pending);
    02279             }
    02280             read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
    02281             limit -= pending;
    02282             *lp = limit;
    02283             if (e) return delim;
    02284             if (limit == 0)
    02285                 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
    02286         }
    02287         READ_CHECK(fptr);
    02288     } while (io_fillbuf(fptr) >= 0);
    02289     *lp = limit;
    02290     return EOF;
    02291 }
    02292
    02293 static inline int
    02294 swallow(rb_io_t *fptr, int term)
    02295 {
    02296     if (NEED_READCONV(fptr)) {
    02297         rb_encoding *enc = io_read_encoding(fptr);
    02298         int needconv = rb_enc_mbminlen(enc) != 1;
    02299         make_readconv(fptr, 0);
    02300         do {
    02301             size_t cnt;
    02302             while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
    02303                 const char *p = READ_CHAR_PENDING_PTR(fptr);
    02304                 int i;
    02305                 if (!needconv) {
    02306                     if (*p != term) return TRUE;
    02307                     i = (int)cnt;
    02308                     while (--i && *++p == term);
    02309                 }
    02310                 else {
    02311                     const char *e = p + cnt;
    02312                     if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
    02313                     while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
    02314                     i = (int)(e - p);
    02315                 }
    02316                 io_shift_cbuf(fptr, (int)cnt - i, NULL);
    02317             }
    02318         } while (more_char(fptr) != MORE_CHAR_FINISHED);
    02319         return FALSE;
    02320     }
    02321
    02322     do {
    02323         size_t cnt;
    02324         while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
    02325             char buf[1024];
    02326             const char *p = READ_DATA_PENDING_PTR(fptr);
    02327             int i;
    02328             if (cnt > sizeof buf) cnt = sizeof buf;
    02329             if (*p != term) return TRUE;
    02330             i = (int)cnt;
    02331             while (--i && *++p == term);
    02332             if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
    02333                 rb_sys_fail_path(fptr->pathv);
    02334         }
    02335         READ_CHECK(fptr);
    02336     } while (io_fillbuf(fptr) == 0);
    02337     return FALSE;
    02338 }
    02339
    02340 static VALUE
    02341 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
    02342 {
    02343     VALUE str = Qnil;
    02344     int len = 0;
    02345     long pos = 0;
    02346     int cr = 0;
    02347
    02348     for (;;) {
    02349         int pending = READ_DATA_PENDING_COUNT(fptr);
    02350
    02351         if (pending > 0) {
    02352             const char *p = READ_DATA_PENDING_PTR(fptr);
    02353             const char *e;
    02354
    02355             e = memchr(p, '\n', pending);
    02356             if (e) {
    02357                 pending = (int)(e - p + 1);
    02358             }
    02359             if (NIL_P(str)) {
    02360                 str = rb_str_new(p, pending);
    02361                 fptr->rbuf_off += pending;
    02362                 fptr->rbuf_len -= pending;
    02363             }
    02364             else {
    02365                 rb_str_resize(str, len + pending);
    02366                 read_buffered_data(RSTRING_PTR(str)+len, pending, fptr);
    02367             }
    02368             len += pending;
    02369             if (cr != ENC_CODERANGE_BROKEN)
    02370                 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
    02371             if (e) break;
    02372         }
    02373         READ_CHECK(fptr);
    02374         if (io_fillbuf(fptr) < 0) {
    02375             if (NIL_P(str)) return Qnil;
    02376             break;
    02377         }
    02378     }
    02379
    02380     str = io_enc_str(str, fptr);
    02381     ENC_CODERANGE_SET(str, cr);
    02382     fptr->lineno++;
    02383     if (io == ARGF.current_file) {
    02384         ARGF.lineno++;
    02385         ARGF.last_lineno = ARGF.lineno;
    02386     }
    02387     else {
    02388         ARGF.last_lineno = fptr->lineno;
    02389     }
    02390
    02391     return str;
    02392 }
    02393
    02394 static void
    02395 prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
    02396 {
    02397     VALUE rs = rb_rs, lim = Qnil;
    02398     rb_io_t *fptr;
    02399
    02400     if (argc == 1) {
    02401         VALUE tmp = Qnil;
    02402
    02403         if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
    02404             rs = tmp;
    02405         }
    02406         else {
    02407             lim = argv[0];
    02408         }
    02409     }
    02410     else if (2 <= argc) {
    02411         rb_scan_args(argc, argv, "2", &rs, &lim);
    02412         if (!NIL_P(rs))
    02413             StringValue(rs);
    02414     }
    02415     if (!NIL_P(rs)) {
    02416         rb_encoding *enc_rs, *enc_io;
    02417
    02418         GetOpenFile(io, fptr);
    02419         enc_rs = rb_enc_get(rs);
    02420         enc_io = io_read_encoding(fptr);
    02421         if (enc_io != enc_rs &&
    02422             (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
    02423              (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
    02424             if (rs == rb_default_rs) {
    02425                 rs = rb_enc_str_new(0, 0, enc_io);
    02426                 rb_str_buf_cat_ascii(rs, "\n");
    02427             }
    02428             else {
    02429                 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
    02430                          rb_enc_name(enc_io),
    02431                          rb_enc_name(enc_rs));
    02432             }
    02433         }
    02434     }
    02435     *rsp = rs;
    02436     *limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
    02437 }
    02438
    02439 static VALUE
    02440 rb_io_getline_1(VALUE rs, long limit, VALUE io)
    02441 {
    02442     VALUE str = Qnil;
    02443     rb_io_t *fptr;
    02444     int nolimit = 0;
    02445     rb_encoding *enc;
    02446
    02447     GetOpenFile(io, fptr);
    02448     rb_io_check_char_readable(fptr);
    02449     if (NIL_P(rs) && limit < 0) {
    02450         str = read_all(fptr, 0, Qnil);
    02451         if (RSTRING_LEN(str) == 0) return Qnil;
    02452     }
    02453     else if (limit == 0) {
    02454         return rb_enc_str_new(0, 0, io_read_encoding(fptr));
    02455     }
    02456     else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
    02457              rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
    02458         return rb_io_getline_fast(fptr, enc, io);
    02459     }
    02460     else {
    02461         int c, newline = -1;
    02462         const char *rsptr = 0;
    02463         long rslen = 0;
    02464         int rspara = 0;
    02465         int extra_limit = 16;
    02466
    02467         enc = io_read_encoding(fptr);
    02468
    02469         if (!NIL_P(rs)) {
    02470             rslen = RSTRING_LEN(rs);
    02471             if (rslen == 0) {
    02472                 rsptr = "\n\n";
    02473                 rslen = 2;
    02474                 rspara = 1;
    02475                 swallow(fptr, '\n');
    02476                 rs = 0;
    02477                 if (!rb_enc_asciicompat(enc)) {
    02478                     rs = rb_usascii_str_new(rsptr, rslen);
    02479                     rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
    02480                     OBJ_FREEZE(rs);
    02481                     rsptr = RSTRING_PTR(rs);
    02482                     rslen = RSTRING_LEN(rs);
    02483                 }
    02484             }
    02485             else {
    02486                 rsptr = RSTRING_PTR(rs);
    02487             }
    02488             newline = (unsigned char)rsptr[rslen - 1];
    02489         }
    02490
    02491         /* MS - Optimisation */
    02492         while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
    02493             const char *s, *p, *pp, *e;
    02494
    02495             if (c == newline) {
    02496                 if (RSTRING_LEN(str) < rslen) continue;
    02497                 s = RSTRING_PTR(str);
    02498                 e = s + RSTRING_LEN(str);
    02499                 p = e - rslen;
    02500                 pp = rb_enc_left_char_head(s, p, e, enc);
    02501                 if (pp != p) continue;
    02502                 if (!rspara) rscheck(rsptr, rslen, rs);
    02503                 if (memcmp(p, rsptr, rslen) == 0) break;
    02504             }
    02505             if (limit == 0) {
    02506                 s = RSTRING_PTR(str);
    02507                 p = s + RSTRING_LEN(str);
    02508                 pp = rb_enc_left_char_head(s, p-1, p, enc);
    02509                 if (extra_limit &&
    02510                     MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
    02511                     /* relax the limit while incomplete character.
    02512                      * extra_limit limits the relax length */
    02513                     limit = 1;
    02514                     extra_limit--;
    02515                 }
    02516                 else {
    02517                     nolimit = 1;
    02518                     break;
    02519                 }
    02520             }
    02521         }
    02522
    02523         if (rspara) {
    02524             if (c != EOF) {
    02525                 swallow(fptr, '\n');
    02526             }
    02527         }
    02528         if (!NIL_P(str))
    02529             str = io_enc_str(str, fptr);
    02530     }
    02531
    02532     if (!NIL_P(str)) {
    02533         if (!nolimit) {
    02534             fptr->lineno++;
    02535             if (io == ARGF.current_file) {
    02536                 ARGF.lineno++;
    02537                 ARGF.last_lineno = ARGF.lineno;
    02538             }
    02539             else {
    02540                 ARGF.last_lineno = fptr->lineno;
    02541             }
    02542         }
    02543     }
    02544
    02545     return str;
    02546 }
    02547
    02548 static VALUE
    02549 rb_io_getline(int argc, VALUE *argv, VALUE io)
    02550 {
    02551     VALUE rs;
    02552     long limit;
    02553
    02554     prepare_getline_args(argc, argv, &rs, &limit, io);
    02555     return rb_io_getline_1(rs, limit, io);
    02556 }
    02557
    02558 VALUE
    02559 rb_io_gets(VALUE io)
    02560 {
    02561     return rb_io_getline_1(rb_default_rs, -1, io);
    02562 }
    02563
    02564 /*
    02565  *  call-seq:
    02566  *     ios.gets(sep=$/)     -> string or nil
    02567  *     ios.gets(limit)      -> string or nil
    02568  *     ios.gets(sep, limit) -> string or nil
    02569  *
    02570  *  Reads the next ``line'' from the I/O stream; lines are separated by
    02571  *  <i>sep</i>. A separator of <code>nil</code> reads the entire
    02572  *  contents, and a zero-length separator reads the input a paragraph at
    02573  *  a time (two successive newlines in the input separate paragraphs).
    02574  *  The stream must be opened for reading or an <code>IOError</code>
    02575  *  will be raised. The line read in will be returned and also assigned
    02576  *  to <code>$_</code>. Returns <code>nil</code> if called at end of
    02577  *  file.  If the first argument is an integer, or optional second
    02578  *  argument is given, the returning string would not be longer than the
    02579  *  given value in bytes.
    02580  *
    02581  *     File.new("testfile").gets   #=> "This is line one\n"
    02582  *     $_                          #=> "This is line one\n"
    02583  */
    02584
    02585 static VALUE
    02586 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
    02587 {
    02588     VALUE str;
    02589
    02590     str = rb_io_getline(argc, argv, io);
    02591     rb_lastline_set(str);
    02592
    02593     return str;
    02594 }
    02595
    02596 /*
    02597  *  call-seq:
    02598  *     ios.lineno    -> integer
    02599  *
    02600  *  Returns the current line number in <em>ios</em>. The stream must be
    02601  *  opened for reading. <code>lineno</code> counts the number of times
    02602  *  <code>gets</code> is called, rather than the number of newlines
    02603  *  encountered. The two values will differ if <code>gets</code> is
    02604  *  called with a separator other than newline. See also the
    02605  *  <code>$.</code> variable.
    02606  *
    02607  *     f = File.new("testfile")
    02608  *     f.lineno   #=> 0
    02609  *     f.gets     #=> "This is line one\n"
    02610  *     f.lineno   #=> 1
    02611  *     f.gets     #=> "This is line two\n"
    02612  *     f.lineno   #=> 2
    02613  */
    02614
    02615 static VALUE
    02616 rb_io_lineno(VALUE io)
    02617 {
    02618     rb_io_t *fptr;
    02619
    02620     GetOpenFile(io, fptr);
    02621     rb_io_check_char_readable(fptr);
    02622     return INT2NUM(fptr->lineno);
    02623 }
    02624
    02625 /*
    02626  *  call-seq:
    02627  *     ios.lineno = integer    -> integer
    02628  *
    02629  *  Manually sets the current line number to the given value.
    02630  *  <code>$.</code> is updated only on the next read.
    02631  *
    02632  *     f = File.new("testfile")
    02633  *     f.gets                     #=> "This is line one\n"
    02634  *     $.                         #=> 1
    02635  *     f.lineno = 1000
    02636  *     f.lineno                   #=> 1000
    02637  *     $.                         #=> 1         # lineno of last read
    02638  *     f.gets                     #=> "This is line two\n"
    02639  *     $.                         #=> 1001      # lineno of last read
    02640  */
    02641
    02642 static VALUE
    02643 rb_io_set_lineno(VALUE io, VALUE lineno)
    02644 {
    02645     rb_io_t *fptr;
    02646
    02647     GetOpenFile(io, fptr);
    02648     rb_io_check_char_readable(fptr);
    02649     fptr->lineno = NUM2INT(lineno);
    02650     return lineno;
    02651 }
    02652
    02653 /*
    02654  *  call-seq:
    02655  *     ios.readline(sep=$/)     -> string
    02656  *     ios.readline(limit)      -> string
    02657  *     ios.readline(sep, limit) -> string
    02658  *
    02659  *  Reads a line as with <code>IO#gets</code>, but raises an
    02660  *  <code>EOFError</code> on end of file.
    02661  */
    02662
    02663 static VALUE
    02664 rb_io_readline(int argc, VALUE *argv, VALUE io)
    02665 {
    02666     VALUE line = rb_io_gets_m(argc, argv, io);
    02667
    02668     if (NIL_P(line)) {
    02669         rb_eof_error();
    02670     }
    02671     return line;
    02672 }
    02673
    02674 /*
    02675  *  call-seq:
    02676  *     ios.readlines(sep=$/)     -> array
    02677  *     ios.readlines(limit)      -> array
    02678  *     ios.readlines(sep, limit) -> array
    02679  *
    02680  *  Reads all of the lines in <em>ios</em>, and returns them in
    02681  *  <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
    02682  *  <i>sep</i> is <code>nil</code>, the rest of the stream is returned
    02683  *  as a single record.  If the first argument is an integer, or
    02684  *  optional second argument is given, the returning string would not be
    02685  *  longer than the given value in bytes. The stream must be opened for
    02686  *  reading or an <code>IOError</code> will be raised.
    02687  *
    02688  *     f = File.new("testfile")
    02689  *     f.readlines[0]   #=> "This is line one\n"
    02690  */
    02691
    02692 static VALUE
    02693 rb_io_readlines(int argc, VALUE *argv, VALUE io)
    02694 {
    02695     VALUE line, ary, rs;
    02696     long limit;
    02697
    02698     prepare_getline_args(argc, argv, &rs, &limit, io);
    02699     ary = rb_ary_new();
    02700     while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
    02701         rb_ary_push(ary, line);
    02702     }
    02703     return ary;
    02704 }
    02705
    02706 /*
    02707  *  call-seq:
    02708  *     ios.each(sep=$/) {|line| block }         -> ios
    02709  *     ios.each(limit) {|line| block }          -> ios
    02710  *     ios.each(sep,limit) {|line| block }      -> ios
    02711  *     ios.each(...)                            -> an_enumerator
    02712  *
    02713  *     ios.each_line(sep=$/) {|line| block }    -> ios
    02714  *     ios.each_line(limit) {|line| block }     -> ios
    02715  *     ios.each_line(sep,limit) {|line| block } -> ios
    02716  *     ios.each_line(...)                       -> an_enumerator
    02717  *
    02718  *     ios.lines(sep=$/) {|line| block }        -> ios
    02719  *     ios.lines(limit) {|line| block }         -> ios
    02720  *     ios.lines(sep,limit) {|line| block }     -> ios
    02721  *     ios.lines(...)                           -> an_enumerator
    02722  *
    02723  *  Executes the block for every line in <em>ios</em>, where lines are
    02724  *  separated by <i>sep</i>. <em>ios</em> must be opened for
    02725  *  reading or an <code>IOError</code> will be raised.
    02726  *
    02727  *  If no block is given, an enumerator is returned instead.
    02728  *
    02729  *     f = File.new("testfile")
    02730  *     f.each {|line| puts "#{f.lineno}: #{line}" }
    02731  *
    02732  *  <em>produces:</em>
    02733  *
    02734  *     1: This is line one
    02735  *     2: This is line two
    02736  *     3: This is line three
    02737  *     4: And so on...
    02738  */
    02739
    02740 static VALUE
    02741 rb_io_each_line(int argc, VALUE *argv, VALUE io)
    02742 {
    02743     VALUE str, rs;
    02744     long limit;
    02745
    02746     RETURN_ENUMERATOR(io, argc, argv);
    02747     prepare_getline_args(argc, argv, &rs, &limit, io);
    02748     while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
    02749         rb_yield(str);
    02750     }
    02751     return io;
    02752 }
    02753
    02754 /*
    02755  *  call-seq:
    02756  *     ios.bytes {|byte| block }      -> ios
    02757  *     ios.bytes                      -> an_enumerator
    02758  *
    02759  *     ios.each_byte {|byte| block }  -> ios
    02760  *     ios.each_byte                  -> an_enumerator
    02761  *
    02762  *  Calls the given block once for each byte (0..255) in <em>ios</em>,
    02763  *  passing the byte as an argument. The stream must be opened for
    02764  *  reading or an <code>IOError</code> will be raised.
    02765  *
    02766  *  If no block is given, an enumerator is returned instead.
    02767  *
    02768  *     f = File.new("testfile")
    02769  *     checksum = 0
    02770  *     f.each_byte {|x| checksum ^= x }   #=> #<File:testfile>
    02771  *     checksum                           #=> 12
    02772  */
    02773
    02774 static VALUE
    02775 rb_io_each_byte(VALUE io)
    02776 {
    02777     rb_io_t *fptr;
    02778     char *p, *e;
    02779
    02780     RETURN_ENUMERATOR(io, 0, 0);
    02781     GetOpenFile(io, fptr);
    02782
    02783     for (;;) {
    02784         p = fptr->rbuf+fptr->rbuf_off;
    02785         e = p + fptr->rbuf_len;
    02786         while (p < e) {
    02787             fptr->rbuf_off++;
    02788             fptr->rbuf_len--;
    02789             rb_yield(INT2FIX(*p & 0xff));
    02790             p++;
    02791             errno = 0;
    02792         }
    02793         rb_io_check_byte_readable(fptr);
    02794         READ_CHECK(fptr);
    02795         if (io_fillbuf(fptr) < 0) {
    02796             break;
    02797         }
    02798     }
    02799     return io;
    02800 }
    02801
    02802 static VALUE
    02803 io_getc(rb_io_t *fptr, rb_encoding *enc)
    02804 {
    02805     int r, n, cr = 0;
    02806     VALUE str;
    02807
    02808     if (NEED_READCONV(fptr)) {
    02809         VALUE str = Qnil;
    02810         rb_encoding *read_enc = io_read_encoding(fptr);
    02811
    02812         make_readconv(fptr, 0);
    02813
    02814         while (1) {
    02815             if (fptr->cbuf_len) {
    02816                 r = rb_enc_precise_mbclen(fptr->cbuf+fptr->cbuf_off,
    02817                         fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
    02818                         read_enc);
    02819                 if (!MBCLEN_NEEDMORE_P(r))
    02820                     break;
    02821                 if (fptr->cbuf_len == fptr->cbuf_capa) {
    02822                     rb_raise(rb_eIOError, "too long character");
    02823                 }
    02824             }
    02825
    02826             if (more_char(fptr) == MORE_CHAR_FINISHED) {
    02827                 if (fptr->cbuf_len == 0) {
    02828                     clear_readconv(fptr);
    02829                     return Qnil;
    02830                 }
    02831                 /* return an unit of an incomplete character just before EOF */
    02832                 str = rb_enc_str_new(fptr->cbuf+fptr->cbuf_off, 1, read_enc);
    02833                 fptr->cbuf_off += 1;
    02834                 fptr->cbuf_len -= 1;
    02835                 if (fptr->cbuf_len == 0) clear_readconv(fptr);
    02836                 ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
    02837                 return str;
    02838             }
    02839         }
    02840         if (MBCLEN_INVALID_P(r)) {
    02841             r = rb_enc_mbclen(fptr->cbuf+fptr->cbuf_off,
    02842                               fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
    02843                               read_enc);
    02844             io_shift_cbuf(fptr, r, &str);
    02845             cr = ENC_CODERANGE_BROKEN;
    02846         }
    02847         else {
    02848             io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
    02849             cr = ENC_CODERANGE_VALID;
    02850         }
    02851         str = io_enc_str(str, fptr);
    02852         ENC_CODERANGE_SET(str, cr);
    02853         return str;
    02854     }
    02855
    02856     if (io_fillbuf(fptr) < 0) {
    02857         return Qnil;
    02858     }
    02859     if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf[fptr->rbuf_off])) {
    02860         str = rb_str_new(fptr->rbuf+fptr->rbuf_off, 1);
    02861         fptr->rbuf_off += 1;
    02862         fptr->rbuf_len -= 1;
    02863         cr = ENC_CODERANGE_7BIT;
    02864     }
    02865     else {
    02866         r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off, fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc);
    02867         if (MBCLEN_CHARFOUND_P(r) &&
    02868             (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf_len) {
    02869             str = rb_str_new(fptr->rbuf+fptr->rbuf_off, n);
    02870             fptr->rbuf_off += n;
    02871             fptr->rbuf_len -= n;
    02872             cr = ENC_CODERANGE_VALID;
    02873         }
    02874         else if (MBCLEN_NEEDMORE_P(r)) {
    02875             str = rb_str_new(fptr->rbuf+fptr->rbuf_off, fptr->rbuf_len);
    02876             fptr->rbuf_len = 0;
    02877           getc_needmore:
    02878             if (io_fillbuf(fptr) != -1) {
    02879                 rb_str_cat(str, fptr->rbuf+fptr->rbuf_off, 1);
    02880                 fptr->rbuf_off++;
    02881                 fptr->rbuf_len--;
    02882                 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
    02883                 if (MBCLEN_NEEDMORE_P(r)) {
    02884                     goto getc_needmore;
    02885                 }
    02886                 else if (MBCLEN_CHARFOUND_P(r)) {
    02887                     cr = ENC_CODERANGE_VALID;
    02888                 }
    02889             }
    02890         }
    02891         else {
    02892             str = rb_str_new(fptr->rbuf+fptr->rbuf_off, 1);
    02893             fptr->rbuf_off++;
    02894             fptr->rbuf_len--;
    02895         }
    02896     }
    02897     if (!cr) cr = ENC_CODERANGE_BROKEN;
    02898     str = io_enc_str(str, fptr);
    02899     ENC_CODERANGE_SET(str, cr);
    02900     return str;
    02901 }
    02902
    02903 /*
    02904  *  call-seq:
    02905  *     ios.chars {|c| block }      -> ios
    02906  *     ios.chars                   -> an_enumerator
    02907  *
    02908  *     ios.each_char {|c| block }  -> ios
    02909  *     ios.each_char               -> an_enumerator
    02910  *
    02911  *  Calls the given block once for each character in <em>ios</em>,
    02912  *  passing the character as an argument. The stream must be opened for
    02913  *  reading or an <code>IOError</code> will be raised.
    02914  *
    02915  *  If no block is given, an enumerator is returned instead.
    02916  *
    02917  *     f = File.new("testfile")
    02918  *     f.each_char {|c| print c, ' ' }   #=> #<File:testfile>
    02919  */
    02920
    02921 static VALUE
    02922 rb_io_each_char(VALUE io)
    02923 {
    02924     rb_io_t *fptr;
    02925     rb_encoding *enc;
    02926     VALUE c;
    02927
    02928     RETURN_ENUMERATOR(io, 0, 0);
    02929     GetOpenFile(io, fptr);
    02930     rb_io_check_char_readable(fptr);
    02931
    02932     enc = io_input_encoding(fptr);
    02933     READ_CHECK(fptr);
    02934     while (!NIL_P(c = io_getc(fptr, enc))) {
    02935         rb_yield(c);
    02936     }
    02937     return io;
    02938 }
    02939
    02940
    02941 /*
    02942  *  call-seq:
    02943  *     ios.each_codepoint {|c| block }  -> ios
    02944  *     ios.codepoints     {|c| block }  -> ios
    02945  *     ios.each_codepoint               -> an_enumerator
    02946  *     ios.codepoints                   -> an_enumerator
    02947  *
    02948  *  Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
    02949  *  passing the codepoint as an argument. The stream must be opened for
    02950  *  reading or an <code>IOError</code> will be raised.
    02951  *
    02952  *  If no block is given, an enumerator is returned instead.
    02953  *
    02954  */
    02955
    02956 static VALUE
    02957 rb_io_each_codepoint(VALUE io)
    02958 {
    02959     rb_io_t *fptr;
    02960     rb_encoding *enc;
    02961     unsigned int c;
    02962     int r, n;
    02963
    02964     RETURN_ENUMERATOR(io, 0, 0);
    02965     GetOpenFile(io, fptr);
    02966     rb_io_check_char_readable(fptr);
    02967
    02968     READ_CHECK(fptr);
    02969     if (NEED_READCONV(fptr)) {
    02970         for (;;) {
    02971             make_readconv(fptr, 0);
    02972             for (;;) {
    02973                 if (fptr->cbuf_len) {
    02974                     if (fptr->encs.enc)
    02975                         r = rb_enc_precise_mbclen(fptr->cbuf+fptr->cbuf_off,
    02976                                                   fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
    02977                                                   fptr->encs.enc);
    02978                     else
    02979                         r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
    02980                     if (!MBCLEN_NEEDMORE_P(r))
    02981                         break;
    02982                     if (fptr->cbuf_len == fptr->cbuf_capa) {
    02983                         rb_raise(rb_eIOError, "too long character");
    02984                     }
    02985                 }
    02986                 if (more_char(fptr) == MORE_CHAR_FINISHED) {
    02987                     clear_readconv(fptr);
    02988                     /* ignore an incomplete character before EOF */
    02989                     return io;
    02990                 }
    02991             }
    02992             if (MBCLEN_INVALID_P(r)) {
    02993                 rb_raise(rb_eArgError, "invalid byte sequence in %s",
    02994                          rb_enc_name(fptr->encs.enc));
    02995             }
    02996             n = MBCLEN_CHARFOUND_LEN(r);
    02997             if (fptr->encs.enc) {
    02998                 c = rb_enc_codepoint(fptr->cbuf+fptr->cbuf_off,
    02999                                      fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
    03000                                      fptr->encs.enc);
    03001             }
    03002             else {
    03003                 c = (unsigned char)fptr->cbuf[fptr->cbuf_off];
    03004             }
    03005             fptr->cbuf_off += n;
    03006             fptr->cbuf_len -= n;
    03007             rb_yield(UINT2NUM(c));
    03008         }
    03009     }
    03010     enc = io_input_encoding(fptr);
    03011     for (;;) {
    03012         if (io_fillbuf(fptr) < 0) {
    03013             return io;
    03014         }
    03015         r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off,
    03016                                   fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc);
    03017         if (MBCLEN_CHARFOUND_P(r) &&
    03018             (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf_len) {
    03019             c = rb_enc_codepoint(fptr->rbuf+fptr->rbuf_off,
    03020                                  fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc);
    03021             fptr->rbuf_off += n;
    03022             fptr->rbuf_len -= n;
    03023             rb_yield(UINT2NUM(c));
    03024         }
    03025         else if (MBCLEN_INVALID_P(r)) {
    03026             rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
    03027         }
    03028         else {
    03029             continue;
    03030         }
    03031     }
    03032     return io;
    03033 }
    03034
    03035
    03036
    03037 /*
    03038  *  call-seq:
    03039  *     ios.getc   -> string or nil
    03040  *
    03041  *  Reads a one-character string from <em>ios</em>. Returns
    03042  *  <code>nil</code> if called at end of file.
    03043  *
    03044  *     f = File.new("testfile")
    03045  *     f.getc   #=> "h"
    03046  *     f.getc   #=> "e"
    03047  */
    03048
    03049 static VALUE
    03050 rb_io_getc(VALUE io)
    03051 {
    03052     rb_io_t *fptr;
    03053     rb_encoding *enc;
    03054
    03055     GetOpenFile(io, fptr);
    03056     rb_io_check_char_readable(fptr);
    03057
    03058     enc = io_input_encoding(fptr);
    03059     READ_CHECK(fptr);
    03060     return io_getc(fptr, enc);
    03061 }
    03062
    03063 /*
    03064  *  call-seq:
    03065  *     ios.readchar   -> string
    03066  *
    03067  *  Reads a one-character string from <em>ios</em>. Raises an
    03068  *  <code>EOFError</code> on end of file.
    03069  *
    03070  *     f = File.new("testfile")
    03071  *     f.readchar   #=> "h"
    03072  *     f.readchar   #=> "e"
    03073  */
    03074
    03075 static VALUE
    03076 rb_io_readchar(VALUE io)
    03077 {
    03078     VALUE c = rb_io_getc(io);
    03079
    03080     if (NIL_P(c)) {
    03081         rb_eof_error();
    03082     }
    03083     return c;
    03084 }
    03085
    03086 /*
    03087  *  call-seq:
    03088  *     ios.getbyte   -> fixnum or nil
    03089  *
    03090  *  Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
    03091  *  <code>nil</code> if called at end of file.
    03092  *
    03093  *     f = File.new("testfile")
    03094  *     f.getbyte   #=> 84
    03095  *     f.getbyte   #=> 104
    03096  */
    03097
    03098 VALUE
    03099 rb_io_getbyte(VALUE io)
    03100 {
    03101     rb_io_t *fptr;
    03102     int c;
    03103
    03104     GetOpenFile(io, fptr);
    03105     rb_io_check_byte_readable(fptr);
    03106     READ_CHECK(fptr);
    03107     if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
    03108         rb_io_t *ofp;
    03109         GetOpenFile(rb_stdout, ofp);
    03110         if (ofp->mode & FMODE_TTY) {
    03111             rb_io_flush(rb_stdout);
    03112         }
    03113     }
    03114     if (io_fillbuf(fptr) < 0) {
    03115         return Qnil;
    03116     }
    03117     fptr->rbuf_off++;
    03118     fptr->rbuf_len--;
    03119     c = (unsigned char)fptr->rbuf[fptr->rbuf_off-1];
    03120     return INT2FIX(c & 0xff);
    03121 }
    03122
    03123 /*
    03124  *  call-seq:
    03125  *     ios.readbyte   -> fixnum
    03126  *
    03127  *  Reads a byte as with <code>IO#getbyte</code>, but raises an
    03128  *  <code>EOFError</code> on end of file.
    03129  */
    03130
    03131 static VALUE
    03132 rb_io_readbyte(VALUE io)
    03133 {
    03134     VALUE c = rb_io_getbyte(io);
    03135
    03136     if (NIL_P(c)) {
    03137         rb_eof_error();
    03138     }
    03139     return c;
    03140 }
    03141
    03142 /*
    03143  *  call-seq:
    03144  *     ios.ungetbyte(string)   -> nil
    03145  *     ios.ungetbyte(integer)   -> nil
    03146  *
    03147  *  Pushes back bytes (passed as a parameter) onto <em>ios</em>,
    03148  *  such that a subsequent buffered read will return it. Only one byte
    03149  *  may be pushed back before a subsequent read operation (that is,
    03150  *  you will be able to read only the last of several bytes that have been pushed
    03151  *  back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
    03152  *
    03153  *     f = File.new("testfile")   #=> #<File:testfile>
    03154  *     b = f.getbyte              #=> 0x38
    03155  *     f.ungetbyte(b)             #=> nil
    03156  *     f.getbyte                  #=> 0x38
    03157  */
    03158
    03159 VALUE
    03160 rb_io_ungetbyte(VALUE io, VALUE b)
    03161 {
    03162     rb_io_t *fptr;
    03163
    03164     GetOpenFile(io, fptr);
    03165     rb_io_check_byte_readable(fptr);
    03166     if (NIL_P(b)) return Qnil;
    03167     if (FIXNUM_P(b)) {
    03168         char cc = FIX2INT(b);
    03169         b = rb_str_new(&cc, 1);
    03170     }
    03171     else {
    03172         SafeStringValue(b);
    03173     }
    03174     io_ungetbyte(b, fptr);
    03175     return Qnil;
    03176 }
    03177
    03178 /*
    03179  *  call-seq:
    03180  *     ios.ungetc(string)   -> nil
    03181  *
    03182  *  Pushes back one character (passed as a parameter) onto <em>ios</em>,
    03183  *  such that a subsequent buffered character read will return it. Only one character
    03184  *  may be pushed back before a subsequent read operation (that is,
    03185  *  you will be able to read only the last of several characters that have been pushed
    03186  *  back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
    03187  *
    03188  *     f = File.new("testfile")   #=> #<File:testfile>
    03189  *     c = f.getc                 #=> "8"
    03190  *     f.ungetc(c)                #=> nil
    03191  *     f.getc                     #=> "8"
    03192  */
    03193
    03194 VALUE
    03195 rb_io_ungetc(VALUE io, VALUE c)
    03196 {
    03197     rb_io_t *fptr;
    03198     long len;
    03199
    03200     GetOpenFile(io, fptr);
    03201     rb_io_check_char_readable(fptr);
    03202     if (NIL_P(c)) return Qnil;
    03203     if (FIXNUM_P(c)) {
    03204         c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
    03205     }
    03206     else if (TYPE(c) == T_BIGNUM) {
    03207         c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
    03208     }
    03209     else {
    03210         SafeStringValue(c);
    03211     }
    03212     if (NEED_READCONV(fptr)) {
    03213         len = RSTRING_LEN(c);
    03214 #if SIZEOF_LONG > SIZEOF_INT
    03215         if (len > INT_MAX)
    03216             rb_raise(rb_eIOError, "ungetc failed");
    03217 #endif
    03218         make_readconv(fptr, (int)len);
    03219         if (fptr->cbuf_capa - fptr->cbuf_len < len)
    03220             rb_raise(rb_eIOError, "ungetc failed");
    03221         if (fptr->cbuf_off < len) {
    03222             MEMMOVE(fptr->cbuf+fptr->cbuf_capa-fptr->cbuf_len,
    03223                     fptr->cbuf+fptr->cbuf_off,
    03224                     char, fptr->cbuf_len);
    03225             fptr->cbuf_off = fptr->cbuf_capa-fptr->cbuf_len;
    03226         }
    03227         fptr->cbuf_off -= (int)len;
    03228         fptr->cbuf_len += (int)len;
    03229         MEMMOVE(fptr->cbuf+fptr->cbuf_off, RSTRING_PTR(c), char, len);
    03230     }
    03231     else {
    03232         io_ungetbyte(c, fptr);
    03233     }
    03234     return Qnil;
    03235 }
    03236
    03237 /*
    03238  *  call-seq:
    03239  *     ios.isatty   -> true or false
    03240  *     ios.tty?     -> true or false
    03241  *
    03242  *  Returns <code>true</code> if <em>ios</em> is associated with a
    03243  *  terminal device (tty), <code>false</code> otherwise.
    03244  *
    03245  *     File.new("testfile").isatty   #=> false
    03246  *     File.new("/dev/tty").isatty   #=> true
    03247  */
    03248
    03249 static VALUE
    03250 rb_io_isatty(VALUE io)
    03251 {
    03252     rb_io_t *fptr;
    03253
    03254     GetOpenFile(io, fptr);
    03255     if (isatty(fptr->fd) == 0)
    03256         return Qfalse;
    03257     return Qtrue;
    03258 }
    03259
    03260 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
    03261 /*
    03262  *  call-seq:
    03263  *     ios.close_on_exec?   -> true or false
    03264  *
    03265  *  Returns <code>true</code> if <em>ios</em> will be closed on exec.
    03266  *
    03267  *     f = open("/dev/null")
    03268  *     f.close_on_exec?                 #=> false
    03269  *     f.close_on_exec = true
    03270  *     f.close_on_exec?                 #=> true
    03271  *     f.close_on_exec = false
    03272  *     f.close_on_exec?                 #=> false
    03273  */
    03274
    03275 static VALUE
    03276 rb_io_close_on_exec_p(VALUE io)
    03277 {
    03278     rb_io_t *fptr;
    03279     VALUE write_io;
    03280     int fd, ret;
    03281
    03282     write_io = GetWriteIO(io);
    03283     if (io != write_io) {
    03284         GetOpenFile(write_io, fptr);
    03285         if (fptr && 0 <= (fd = fptr->fd)) {
    03286             if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
    03287             if (!(ret & FD_CLOEXEC)) return Qfalse;
    03288         }
    03289     }
    03290
    03291     GetOpenFile(io, fptr);
    03292     if (fptr && 0 <= (fd = fptr->fd)) {
    03293         if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
    03294         if (!(ret & FD_CLOEXEC)) return Qfalse;
    03295     }
    03296     return Qtrue;
    03297 }
    03298 #else
    03299 #define rb_io_close_on_exec_p rb_f_notimplement
    03300 #endif
    03301
    03302 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
    03303 /*
    03304  *  call-seq:
    03305  *     ios.close_on_exec = bool    -> true or false
    03306  *
    03307  *  Sets a close-on-exec flag.
    03308  *
    03309  *     f = open("/dev/null")
    03310  *     f.close_on_exec = true
    03311  *     system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
    03312  *     f.closed?                #=> false
    03313  */
    03314
    03315 static VALUE
    03316 rb_io_set_close_on_exec(VALUE io, VALUE arg)
    03317 {
    03318     int flag = RTEST(arg) ? FD_CLOEXEC : 0;
    03319     rb_io_t *fptr;
    03320     VALUE write_io;
    03321     int fd, ret;
    03322
    03323     write_io = GetWriteIO(io);
    03324     if (io != write_io) {
    03325         GetOpenFile(write_io, fptr);
    03326         if (fptr && 0 <= (fd = fptr->fd)) {
    03327             if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
    03328             if ((ret & FD_CLOEXEC) != flag) {
    03329                 ret = (ret & ~FD_CLOEXEC) | flag;
    03330                 ret = fcntl(fd, F_SETFD, ret);
    03331                 if (ret == -1) rb_sys_fail_path(fptr->pathv);
    03332             }
    03333         }
    03334
    03335     }
    03336
    03337     GetOpenFile(io, fptr);
    03338     if (fptr && 0 <= (fd = fptr->fd)) {
    03339         if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
    03340         if ((ret & FD_CLOEXEC) != flag) {
    03341             ret = (ret & ~FD_CLOEXEC) | flag;
    03342             ret = fcntl(fd, F_SETFD, ret);
    03343             if (ret == -1) rb_sys_fail_path(fptr->pathv);
    03344         }
    03345     }
    03346     return Qnil;
    03347 }
    03348 #else
    03349 #define rb_io_set_close_on_exec rb_f_notimplement
    03350 #endif
    03351
    03352 #define FMODE_PREP (1<<16)
    03353 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
    03354 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
    03355
    03356 static VALUE
    03357 finish_writeconv(rb_io_t *fptr, int noalloc)
    03358 {
    03359     unsigned char *ds, *dp, *de;
    03360     rb_econv_result_t res;
    03361
    03362     if (!fptr->wbuf) {
    03363         unsigned char buf[1024];
    03364         long r;
    03365
    03366         res = econv_destination_buffer_full;
    03367         while (res == econv_destination_buffer_full) {
    03368             ds = dp = buf;
    03369             de = buf + sizeof(buf);
    03370             res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
    03371             while (dp-ds) {
    03372               retry:
    03373                 r = rb_write_internal(fptr->fd, ds, dp-ds);
    03374                 if (r == dp-ds)
    03375                     break;
    03376                 if (0 <= r) {
    03377                     ds += r;
    03378                 }
    03379                 if (rb_io_wait_writable(fptr->fd)) {
    03380                     if (fptr->fd < 0)
    03381                         return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
    03382                     goto retry;
    03383                 }
    03384                 return noalloc ? Qtrue : INT2NUM(errno);
    03385             }
    03386             if (res == econv_invalid_byte_sequence ||
    03387                 res == econv_incomplete_input ||
    03388                 res == econv_undefined_conversion) {
    03389                 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
    03390             }
    03391         }
    03392
    03393         return Qnil;
    03394     }
    03395
    03396     res = econv_destination_buffer_full;
    03397     while (res == econv_destination_buffer_full) {
    03398         if (fptr->wbuf_len == fptr->wbuf_capa) {
    03399             if (io_fflush(fptr) < 0)
    03400                 return noalloc ? Qtrue : INT2NUM(errno);
    03401         }
    03402
    03403         ds = dp = (unsigned char *)fptr->wbuf + fptr->wbuf_off + fptr->wbuf_len;
    03404         de = (unsigned char *)fptr->wbuf + fptr->wbuf_capa;
    03405         res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
    03406         fptr->wbuf_len += (int)(dp - ds);
    03407         if (res == econv_invalid_byte_sequence ||
    03408             res == econv_incomplete_input ||
    03409             res == econv_undefined_conversion) {
    03410             return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
    03411         }
    03412     }
    03413     return Qnil;
    03414 }
    03415
    03416 struct finish_writeconv_arg {
    03417     rb_io_t *fptr;
    03418     int noalloc;
    03419 };
    03420
    03421 static VALUE
    03422 finish_writeconv_sync(VALUE arg)
    03423 {
    03424     struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
    03425     return finish_writeconv(p->fptr, p->noalloc);
    03426 }
    03427
    03428 static void
    03429 fptr_finalize(rb_io_t *fptr, int noraise)
    03430 {
    03431     VALUE err = Qnil;
    03432     if (fptr->writeconv) {
    03433         if (fptr->write_lock && !noraise) {
    03434             struct finish_writeconv_arg arg;
    03435             arg.fptr = fptr;
    03436             arg.noalloc = noraise;
    03437             err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
    03438         }
    03439         else {
    03440             err = finish_writeconv(fptr, noraise);
    03441         }
    03442     }
    03443     if (fptr->wbuf_len) {
    03444         if (noraise) {
    03445             if ((int)io_flush_buffer_sync(fptr) < 0 && NIL_P(err))
    03446                 err = Qtrue;
    03447         }
    03448         else {
    03449             if (io_fflush(fptr) < 0 && NIL_P(err))
    03450                 err = INT2NUM(errno);
    03451         }
    03452     }
    03453     if (IS_PREP_STDIO(fptr) || fptr->fd <= 2) {
    03454         goto skip_fd_close;
    03455     }
    03456     if (fptr->stdio_file) {
    03457         /* fptr->stdio_file is deallocated anyway
    03458          * even if fclose failed.  */
    03459         if (fclose(fptr->stdio_file) < 0 && NIL_P(err))
    03460             err = noraise ? Qtrue : INT2NUM(errno);
    03461     }
    03462     else if (0 <= fptr->fd) {
    03463         /* fptr->fd may be closed even if close fails.
    03464          * POSIX doesn't specify it.
    03465          * We assumes it is closed.  */
    03466         if (close(fptr->fd) < 0 && NIL_P(err))
    03467             err = noraise ? Qtrue : INT2NUM(errno);
    03468     }
    03469   skip_fd_close:
    03470     fptr->fd = -1;
    03471     fptr->stdio_file = 0;
    03472     fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
    03473
    03474     if (!NIL_P(err) && !noraise) {
    03475         switch(TYPE(err)) {
    03476           case T_FIXNUM:
    03477           case T_BIGNUM:
    03478             errno = NUM2INT(err);
    03479             rb_sys_fail_path(fptr->pathv);
    03480
    03481           default:
    03482             rb_exc_raise(err);
    03483         }
    03484     }
    03485 }
    03486
    03487 static void
    03488 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
    03489 {
    03490     if (fptr->finalize) {
    03491         (*fptr->finalize)(fptr, noraise);
    03492     }
    03493     else {
    03494         fptr_finalize(fptr, noraise);
    03495     }
    03496 }
    03497
    03498 static void
    03499 clear_readconv(rb_io_t *fptr)
    03500 {
    03501     if (fptr->readconv) {
    03502         rb_econv_close(fptr->readconv);
    03503         fptr->readconv = NULL;
    03504     }
    03505     if (fptr->cbuf) {
    03506         free(fptr->cbuf);
    03507         fptr->cbuf = NULL;
    03508     }
    03509 }
    03510
    03511 static void
    03512 clear_writeconv(rb_io_t *fptr)
    03513 {
    03514     if (fptr->writeconv) {
    03515         rb_econv_close(fptr->writeconv);
    03516         fptr->writeconv = NULL;
    03517     }
    03518     fptr->writeconv_initialized = 0;
    03519 }
    03520
    03521 static void
    03522 clear_codeconv(rb_io_t *fptr)
    03523 {
    03524     clear_readconv(fptr);
    03525     clear_writeconv(fptr);
    03526 }
    03527
    03528 int
    03529 rb_io_fptr_finalize(rb_io_t *fptr)
    03530 {
    03531     if (!fptr) return 0;
    03532     fptr->pathv = Qnil;
    03533     if (0 <= fptr->fd)
    03534         rb_io_fptr_cleanup(fptr, TRUE);
    03535     fptr->write_lock = 0;
    03536     if (fptr->rbuf) {
    03537         free(fptr->rbuf);
    03538         fptr->rbuf = 0;
    03539     }
    03540     if (fptr->wbuf) {
    03541         free(fptr->wbuf);
    03542         fptr->wbuf = 0;
    03543     }
    03544     clear_codeconv(fptr);
    03545     free(fptr);
    03546     return 1;
    03547 }
    03548
    03549 size_t rb_econv_memsize(rb_econv_t *);
    03550
    03551 size_t
    03552 rb_io_memsize(rb_io_t *fptr)
    03553 {
    03554     size_t size = sizeof(rb_io_t);
    03555     size += fptr->rbuf_capa;
    03556     size += fptr->wbuf_capa;
    03557     size += fptr->cbuf_capa;
    03558     if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
    03559     if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
    03560     return size;
    03561 }
    03562
    03563 VALUE
    03564 rb_io_close(VALUE io)
    03565 {
    03566     rb_io_t *fptr;
    03567     int fd;
    03568     VALUE write_io;
    03569     rb_io_t *write_fptr;
    03570
    03571     write_io = GetWriteIO(io);
    03572     if (io != write_io) {
    03573         write_fptr = RFILE(write_io)->fptr;
    03574         if (write_fptr && 0 <= write_fptr->fd) {
    03575             rb_io_fptr_cleanup(write_fptr, TRUE);
    03576         }
    03577     }
    03578
    03579     fptr = RFILE(io)->fptr;
    03580     if (!fptr) return Qnil;
    03581     if (fptr->fd < 0) return Qnil;
    03582
    03583     fd = fptr->fd;
    03584     rb_io_fptr_cleanup(fptr, FALSE);
    03585     rb_thread_fd_close(fd);
    03586
    03587     if (fptr->pid) {
    03588         rb_syswait(fptr->pid);
    03589         fptr->pid = 0;
    03590     }
    03591
    03592     return Qnil;
    03593 }
    03594
    03595 /*
    03596  *  call-seq:
    03597  *     ios.close   -> nil
    03598  *
    03599  *  Closes <em>ios</em> and flushes any pending writes to the operating
    03600  *  system. The stream is unavailable for any further data operations;
    03601  *  an <code>IOError</code> is raised if such an attempt is made. I/O
    03602  *  streams are automatically closed when they are claimed by the
    03603  *  garbage collector.
    03604  *
    03605  *  If <em>ios</em> is opened by <code>IO.popen</code>,
    03606  *  <code>close</code> sets <code>$?</code>.
    03607  */
    03608
    03609 static VALUE
    03610 rb_io_close_m(VALUE io)
    03611 {
    03612     if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
    03613         rb_raise(rb_eSecurityError, "Insecure: can't close");
    03614     }
    03615     rb_io_check_closed(RFILE(io)->fptr);
    03616     rb_io_close(io);
    03617     return Qnil;
    03618 }
    03619
    03620 static VALUE
    03621 io_call_close(VALUE io)
    03622 {
    03623     return rb_funcall(io, rb_intern("close"), 0, 0);
    03624 }
    03625
    03626 static VALUE
    03627 io_close(VALUE io)
    03628 {
    03629     return rb_rescue(io_call_close, io, 0, 0);
    03630 }
    03631
    03632 /*
    03633  *  call-seq:
    03634  *     ios.closed?    -> true or false
    03635  *
    03636  *  Returns <code>true</code> if <em>ios</em> is completely closed (for
    03637  *  duplex streams, both reader and writer), <code>false</code>
    03638  *  otherwise.
    03639  *
    03640  *     f = File.new("testfile")
    03641  *     f.close         #=> nil
    03642  *     f.closed?       #=> true
    03643  *     f = IO.popen("/bin/sh","r+")
    03644  *     f.close_write   #=> nil
    03645  *     f.closed?       #=> false
    03646  *     f.close_read    #=> nil
    03647  *     f.closed?       #=> true
    03648  */
    03649
    03650
    03651 static VALUE
    03652 rb_io_closed(VALUE io)
    03653 {
    03654     rb_io_t *fptr;
    03655     VALUE write_io;
    03656     rb_io_t *write_fptr;
    03657
    03658     write_io = GetWriteIO(io);
    03659     if (io != write_io) {
    03660         write_fptr = RFILE(write_io)->fptr;
    03661         if (write_fptr && 0 <= write_fptr->fd) {
    03662             return Qfalse;
    03663         }
    03664     }
    03665
    03666     fptr = RFILE(io)->fptr;
    03667     rb_io_check_initialized(fptr);
    03668     return 0 <= fptr->fd ? Qfalse : Qtrue;
    03669 }
    03670
    03671 /*
    03672  *  call-seq:
    03673  *     ios.close_read    -> nil
    03674  *
    03675  *  Closes the read end of a duplex I/O stream (i.e., one that contains
    03676  *  both a read and a write stream, such as a pipe). Will raise an
    03677  *  <code>IOError</code> if the stream is not duplexed.
    03678  *
    03679  *     f = IO.popen("/bin/sh","r+")
    03680  *     f.close_read
    03681  *     f.readlines
    03682  *
    03683  *  <em>produces:</em>
    03684  *
    03685  *     prog.rb:3:in `readlines': not opened for reading (IOError)
    03686  *      from prog.rb:3
    03687  */
    03688
    03689 static VALUE
    03690 rb_io_close_read(VALUE io)
    03691 {
    03692     rb_io_t *fptr;
    03693     VALUE write_io;
    03694
    03695     if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
    03696         rb_raise(rb_eSecurityError, "Insecure: can't close");
    03697     }
    03698     GetOpenFile(io, fptr);
    03699     if (is_socket(fptr->fd, fptr->pathv)) {
    03700 #ifndef SHUT_RD
    03701 # define SHUT_RD 0
    03702 #endif
    03703         if (shutdown(fptr->fd, SHUT_RD) < 0)
    03704             rb_sys_fail_path(fptr->pathv);
    03705         fptr->mode &= ~FMODE_READABLE;
    03706         if (!(fptr->mode & FMODE_WRITABLE))
    03707             return rb_io_close(io);
    03708         return Qnil;
    03709     }
    03710
    03711     write_io = GetWriteIO(io);
    03712     if (io != write_io) {
    03713         rb_io_t *wfptr;
    03714         rb_io_fptr_cleanup(fptr, FALSE);
    03715         GetOpenFile(write_io, wfptr);
    03716         RFILE(io)->fptr = wfptr;
    03717         RFILE(write_io)->fptr = NULL;
    03718         rb_io_fptr_finalize(fptr);
    03719         return Qnil;
    03720     }
    03721
    03722     if (fptr->mode & FMODE_WRITABLE) {
    03723         rb_raise(rb_eIOError, "closing non-duplex IO for reading");
    03724     }
    03725     return rb_io_close(io);
    03726 }
    03727
    03728 /*
    03729  *  call-seq:
    03730  *     ios.close_write   -> nil
    03731  *
    03732  *  Closes the write end of a duplex I/O stream (i.e., one that contains
    03733  *  both a read and a write stream, such as a pipe). Will raise an
    03734  *  <code>IOError</code> if the stream is not duplexed.
    03735  *
    03736  *     f = IO.popen("/bin/sh","r+")
    03737  *     f.close_write
    03738  *     f.print "nowhere"
    03739  *
    03740  *  <em>produces:</em>
    03741  *
    03742  *     prog.rb:3:in `write': not opened for writing (IOError)
    03743  *      from prog.rb:3:in `print'
    03744  *      from prog.rb:3
    03745  */
    03746
    03747 static VALUE
    03748 rb_io_close_write(VALUE io)
    03749 {
    03750     rb_io_t *fptr;
    03751     VALUE write_io;
    03752
    03753     if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
    03754         rb_raise(rb_eSecurityError, "Insecure: can't close");
    03755     }
    03756     write_io = GetWriteIO(io);
    03757     GetOpenFile(write_io, fptr);
    03758     if (is_socket(fptr->fd, fptr->pathv)) {
    03759 #ifndef SHUT_WR
    03760 # define SHUT_WR 1
    03761 #endif
    03762         if (shutdown(fptr->fd, SHUT_WR) < 0)
    03763             rb_sys_fail_path(fptr->pathv);
    03764         fptr->mode &= ~FMODE_WRITABLE;
    03765         if (!(fptr->mode & FMODE_READABLE))
    03766             return rb_io_close(write_io);
    03767         return Qnil;
    03768     }
    03769
    03770     if (fptr->mode & FMODE_READABLE) {
    03771         rb_raise(rb_eIOError, "closing non-duplex IO for writing");
    03772     }
    03773
    03774     rb_io_close(write_io);
    03775     if (io != write_io) {
    03776         GetOpenFile(io, fptr);
    03777         fptr->tied_io_for_writing = 0;
    03778         fptr->mode &= ~FMODE_DUPLEX;
    03779     }
    03780     return Qnil;
    03781 }
    03782
    03783 /*
    03784  *  call-seq:
    03785  *     ios.sysseek(offset, whence=IO::SEEK_SET)   -> integer
    03786  *
    03787  *  Seeks to a given <i>offset</i> in the stream according to the value
    03788  *  of <i>whence</i> (see <code>IO#seek</code> for values of
    03789  *  <i>whence</i>). Returns the new offset into the file.
    03790  *
    03791  *     f = File.new("testfile")
    03792  *     f.sysseek(-13, IO::SEEK_END)   #=> 53
    03793  *     f.sysread(10)                  #=> "And so on."
    03794  */
    03795
    03796 static VALUE
    03797 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
    03798 {
    03799     VALUE offset, ptrname;
    03800     int whence = SEEK_SET;
    03801     rb_io_t *fptr;
    03802     off_t pos;
    03803
    03804     if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
    03805         whence = NUM2INT(ptrname);
    03806     }
    03807     pos = NUM2OFFT(offset);
    03808     GetOpenFile(io, fptr);
    03809     if ((fptr->mode & FMODE_READABLE) &&
    03810         (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
    03811         rb_raise(rb_eIOError, "sysseek for buffered IO");
    03812     }
    03813     if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf_len) {
    03814         rb_warn("sysseek for buffered IO");
    03815     }
    03816     errno = 0;
    03817     pos = lseek(fptr->fd, pos, whence);
    03818     if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);
    03819
    03820     return OFFT2NUM(pos);
    03821 }
    03822
    03823 /*
    03824  *  call-seq:
    03825  *     ios.syswrite(string)   -> integer
    03826  *
    03827  *  Writes the given string to <em>ios</em> using a low-level write.
    03828  *  Returns the number of bytes written. Do not mix with other methods
    03829  *  that write to <em>ios</em> or you may get unpredictable results.
    03830  *  Raises <code>SystemCallError</code> on error.
    03831  *
    03832  *     f = File.new("out", "w")
    03833  *     f.syswrite("ABCDEF")   #=> 6
    03834  */
    03835
    03836 static VALUE
    03837 rb_io_syswrite(VALUE io, VALUE str)
    03838 {
    03839     rb_io_t *fptr;
    03840     long n;
    03841
    03842     rb_secure(4);
    03843     if (TYPE(str) != T_STRING)
    03844         str = rb_obj_as_string(str);
    03845
    03846     io = GetWriteIO(io);
    03847     GetOpenFile(io, fptr);
    03848     rb_io_check_writable(fptr);
    03849
    03850     if (fptr->wbuf_len) {
    03851         rb_warn("syswrite for buffered IO");
    03852     }
    03853     if (!rb_thread_fd_writable(fptr->fd)) {
    03854         rb_io_check_closed(fptr);
    03855     }
    03856
    03857     n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
    03858
    03859     if (n == -1) rb_sys_fail_path(fptr->pathv);
    03860
    03861     return LONG2FIX(n);
    03862 }
    03863
    03864 /*
    03865  *  call-seq:
    03866  *     ios.sysread(integer[, outbuf])    -> string
    03867  *
    03868  *  Reads <i>integer</i> bytes from <em>ios</em> using a low-level
    03869  *  read and returns them as a string. Do not mix with other methods
    03870  *  that read from <em>ios</em> or you may get unpredictable results.
    03871  *  If the optional <i>outbuf</i> argument is present, it must reference
    03872  *  a String, which will receive the data.
    03873  *  Raises <code>SystemCallError</code> on error and
    03874  *  <code>EOFError</code> at end of file.
    03875  *
    03876  *     f = File.new("testfile")
    03877  *     f.sysread(16)   #=> "This is line one"
    03878  */
    03879
    03880 static VALUE
    03881 rb_io_sysread(int argc, VALUE *argv, VALUE io)
    03882 {
    03883     VALUE len, str;
    03884     rb_io_t *fptr;
    03885     long n, ilen;
    03886
    03887     rb_scan_args(argc, argv, "11", &len, &str);
    03888     ilen = NUM2LONG(len);
    03889
    03890     io_setstrbuf(&str,ilen);
    03891     if (ilen == 0) return str;
    03892
    03893     GetOpenFile(io, fptr);
    03894     rb_io_check_byte_readable(fptr);
    03895
    03896     if (READ_DATA_BUFFERED(fptr)) {
    03897         rb_raise(rb_eIOError, "sysread for buffered IO");
    03898     }
    03899
    03900     n = fptr->fd;
    03901     rb_thread_wait_fd(fptr->fd);
    03902     rb_io_check_closed(fptr);
    03903
    03904     rb_str_locktmp(str);
    03905     n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen);
    03906     rb_str_unlocktmp(str);
    03907
    03908     if (n == -1) {
    03909         rb_sys_fail_path(fptr->pathv);
    03910     }
    03911     rb_str_set_len(str, n);
    03912     if (n == 0 && ilen > 0) {
    03913         rb_eof_error();
    03914     }
    03915     rb_str_resize(str, n);
    03916     OBJ_TAINT(str);
    03917
    03918     return str;
    03919 }
    03920
    03921 VALUE
    03922 rb_io_binmode(VALUE io)
    03923 {
    03924     rb_io_t *fptr;
    03925
    03926     GetOpenFile(io, fptr);
    03927     if (fptr->readconv)
    03928         rb_econv_binmode(fptr->readconv);
    03929     if (fptr->writeconv)
    03930         rb_econv_binmode(fptr->writeconv);
    03931     fptr->mode |= FMODE_BINMODE;
    03932     fptr->mode &= ~FMODE_TEXTMODE;
    03933     fptr->writeconv_pre_ecflags &= ~(ECONV_UNIVERSAL_NEWLINE_DECORATOR|ECONV_CRLF_NEWLINE_DECORATOR|ECONV_CR_NEWLINE_DECORATOR);
    03934     return io;
    03935 }
    03936
    03937 VALUE
    03938 rb_io_ascii8bit_binmode(VALUE io)
    03939 {
    03940     rb_io_t *fptr;
    03941
    03942     GetOpenFile(io, fptr);
    03943     if (fptr->readconv) {
    03944         rb_econv_close(fptr->readconv);
    03945         fptr->readconv = NULL;
    03946     }
    03947     if (fptr->writeconv) {
    03948         rb_econv_close(fptr->writeconv);
    03949         fptr->writeconv = NULL;
    03950     }
    03951     fptr->mode |= FMODE_BINMODE;
    03952     fptr->mode &= ~FMODE_TEXTMODE;
    03953
    03954     fptr->encs.enc = rb_ascii8bit_encoding();
    03955     fptr->encs.enc2 = NULL;
    03956     fptr->encs.ecflags = 0;
    03957     fptr->encs.ecopts = Qnil;
    03958     clear_codeconv(fptr);
    03959
    03960     return io;
    03961 }
    03962
    03963 /*
    03964  *  call-seq:
    03965  *     ios.binmode    -> ios
    03966  *
    03967  *  Puts <em>ios</em> into binary mode.
    03968  *  Once a stream is in binary mode, it cannot be reset to nonbinary mode.
    03969  *
    03970  *  - newline conversion disabled
    03971  *  - encoding conversion disabled
    03972  *  - content is treated as ASCII-8BIT
    03973  *
    03974  */
    03975
    03976 static VALUE
    03977 rb_io_binmode_m(VALUE io)
    03978 {
    03979     VALUE write_io;
    03980
    03981     rb_io_ascii8bit_binmode(io);
    03982
    03983     write_io = GetWriteIO(io);
    03984     if (write_io != io)
    03985         rb_io_ascii8bit_binmode(write_io);
    03986     return io;
    03987 }
    03988
    03989 /*
    03990  *  call-seq:
    03991  *     ios.binmode?    -> true or false
    03992  *
    03993  *  Returns <code>true</code> if <em>ios</em> is binmode.
    03994  */
    03995 static VALUE
    03996 rb_io_binmode_p(VALUE io)
    03997 {
    03998     rb_io_t *fptr;
    03999     GetOpenFile(io, fptr);
    04000     return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
    04001 }
    04002
    04003 static const char*
    04004 rb_io_fmode_modestr(int fmode)
    04005 {
    04006 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
    04007                              (fmode & FMODE_TEXTMODE) ? (c) : (a))
    04008     if (fmode & FMODE_APPEND) {
    04009         if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
    04010             return MODE_BTMODE("a+", "ab+", "at+");
    04011         }
    04012         return MODE_BTMODE("a", "ab", "at");
    04013     }
    04014     switch (fmode & FMODE_READWRITE) {
    04015       case FMODE_READABLE:
    04016         return MODE_BTMODE("r", "rb", "rt");
    04017       case FMODE_WRITABLE:
    04018         return MODE_BTMODE("w", "wb", "wt");
    04019       case FMODE_READWRITE:
    04020         if (fmode & FMODE_CREATE) {
    04021             return MODE_BTMODE("w+", "wb+", "wt+");
    04022         }
    04023         return MODE_BTMODE("r+", "rb+", "rt+");
    04024     }
    04025     rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
    04026     return NULL;                /* not reached */
    04027 }
    04028
    04029 static int
    04030 io_encname_bom_p(const char *name, long len)
    04031 {
    04032     static const char bom_prefix[] = "bom|utf-";
    04033     enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
    04034     if (!len) {
    04035         const char *p = strchr(name, ':');
    04036         len = p ? (long)(p - name) : (long)strlen(name);
    04037     }
    04038     return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
    04039 }
    04040
    04041 int
    04042 rb_io_modestr_fmode(const char *modestr)
    04043 {
    04044     int fmode = 0;
    04045     const char *m = modestr, *p = NULL;
    04046
    04047     switch (*m++) {
    04048       case 'r':
    04049         fmode |= FMODE_READABLE;
    04050         break;
    04051       case 'w':
    04052         fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
    04053         break;
    04054       case 'a':
    04055         fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
    04056         break;
    04057       default:
    04058       error:
    04059         rb_raise(rb_eArgError, "invalid access mode %s", modestr);
    04060     }
    04061
    04062     while (*m) {
    04063         switch (*m++) {
    04064           case 'b':
    04065             fmode |= FMODE_BINMODE;
    04066             break;
    04067           case 't':
    04068             fmode |= FMODE_TEXTMODE;
    04069             break;
    04070           case '+':
    04071             fmode |= FMODE_READWRITE;
    04072             break;
    04073           default:
    04074             goto error;
    04075           case ':':
    04076             p = m;
    04077             goto finished;
    04078         }
    04079     }
    04080
    04081   finished:
    04082     if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
    04083         goto error;
    04084     if (p && io_encname_bom_p(p, 0))
    04085         fmode |= FMODE_SETENC_BY_BOM;
    04086
    04087     return fmode;
    04088 }
    04089
    04090 int
    04091 rb_io_oflags_fmode(int oflags)
    04092 {
    04093     int fmode = 0;
    04094
    04095     switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
    04096       case O_RDONLY:
    04097         fmode = FMODE_READABLE;
    04098         break;
    04099       case O_WRONLY:
    04100         fmode = FMODE_WRITABLE;
    04101         break;
    04102       case O_RDWR:
    04103         fmode = FMODE_READWRITE;
    04104         break;
    04105     }
    04106
    04107     if (oflags & O_APPEND) {
    04108         fmode |= FMODE_APPEND;
    04109     }
    04110     if (oflags & O_TRUNC) {
    04111         fmode |= FMODE_TRUNC;
    04112     }
    04113     if (oflags & O_CREAT) {
    04114         fmode |= FMODE_CREATE;
    04115     }
    04116 #ifdef O_BINARY
    04117     if (oflags & O_BINARY) {
    04118         fmode |= FMODE_BINMODE;
    04119     }
    04120 #endif
    04121
    04122     return fmode;
    04123 }
    04124
    04125 static int
    04126 rb_io_fmode_oflags(int fmode)
    04127 {
    04128     int oflags = 0;
    04129
    04130     switch (fmode & FMODE_READWRITE) {
    04131       case FMODE_READABLE:
    04132         oflags |= O_RDONLY;
    04133         break;
    04134       case FMODE_WRITABLE:
    04135         oflags |= O_WRONLY;
    04136         break;
    04137       case FMODE_READWRITE:
    04138         oflags |= O_RDWR;
    04139         break;
    04140     }
    04141
    04142     if (fmode & FMODE_APPEND) {
    04143         oflags |= O_APPEND;
    04144     }
    04145     if (fmode & FMODE_TRUNC) {
    04146         oflags |= O_TRUNC;
    04147     }
    04148     if (fmode & FMODE_CREATE) {
    04149         oflags |= O_CREAT;
    04150     }
    04151 #ifdef O_BINARY
    04152     if (fmode & FMODE_BINMODE) {
    04153         oflags |= O_BINARY;
    04154     }
    04155 #endif
    04156
    04157     return oflags;
    04158 }
    04159
    04160 int
    04161 rb_io_modestr_oflags(const char *modestr)
    04162 {
    04163     return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
    04164 }
    04165
    04166 static const char*
    04167 rb_io_oflags_modestr(int oflags)
    04168 {
    04169 #ifdef O_BINARY
    04170 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
    04171 #else
    04172 # define MODE_BINARY(a,b) (a)
    04173 #endif
    04174     int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
    04175     if (oflags & O_APPEND) {
    04176         if (accmode == O_WRONLY) {
    04177             return MODE_BINARY("a", "ab");
    04178         }
    04179         if (accmode == O_RDWR) {
    04180             return MODE_BINARY("a+", "ab+");
    04181         }
    04182     }
    04183     switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
    04184       case O_RDONLY:
    04185         return MODE_BINARY("r", "rb");
    04186       case O_WRONLY:
    04187         return MODE_BINARY("w", "wb");
    04188       case O_RDWR:
    04189         return MODE_BINARY("r+", "rb+");
    04190     }
    04191     rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
    04192     return NULL;                /* not reached */
    04193 }
    04194
    04195 /*
    04196  * Convert external/internal encodings to enc/enc2
    04197  * NULL => use default encoding
    04198  * Qnil => no encoding specified (internal only)
    04199  */
    04200 static void
    04201 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2)
    04202 {
    04203     int default_ext = 0;
    04204
    04205     if (ext == NULL) {
    04206         ext = rb_default_external_encoding();
    04207         default_ext = 1;
    04208     }
    04209     if (intern == NULL && ext != rb_ascii8bit_encoding())
    04210         /* If external is ASCII-8BIT, no default transcoding */
    04211         intern = rb_default_internal_encoding();
    04212     if (intern == NULL || intern == (rb_encoding *)Qnil || intern == ext) {
    04213         /* No internal encoding => use external + no transcoding */
    04214         *enc = (default_ext && intern != ext) ? NULL : ext;
    04215         *enc2 = NULL;
    04216     }
    04217     else {
    04218         *enc = intern;
    04219         *enc2 = ext;
    04220     }
    04221 }
    04222
    04223 static void
    04224 parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
    04225 {
    04226     const char *p;
    04227     char encname[ENCODING_MAXNAMELEN+1];
    04228     int idx, idx2;
    04229     rb_encoding *ext_enc, *int_enc;
    04230
    04231     /* parse estr as "enc" or "enc2:enc" or "enc:-" */
    04232
    04233     p = strrchr(estr, ':');
    04234     if (p) {
    04235         long len = (p++) - estr;
    04236         if (len == 0 || len > ENCODING_MAXNAMELEN)
    04237             idx = -1;
    04238         else {
    04239             if (io_encname_bom_p(estr, len)) {
    04240                 if (fmode_p) *fmode_p |= FMODE_SETENC_BY_BOM;
    04241                 estr += 4;
    04242                 len -= 4;
    04243             }
    04244             memcpy(encname, estr, len);
    04245             encname[len] = '\0';
    04246             estr = encname;
    04247             idx = rb_enc_find_index(encname);
    04248         }
    04249     }
    04250     else {
    04251         long len = strlen(estr);
    04252         if (io_encname_bom_p(estr, len)) {
    04253             if (fmode_p) *fmode_p |= FMODE_SETENC_BY_BOM;
    04254             estr += 4;
    04255             len -= 4;
    04256             memcpy(encname, estr, len);
    04257             encname[len] = '\0';
    04258             estr = encname;
    04259         }
    04260         idx = rb_enc_find_index(estr);
    04261     }
    04262
    04263     if (idx >= 0)
    04264         ext_enc = rb_enc_from_index(idx);
    04265     else {
    04266         if (idx != -2)
    04267             rb_warn("Unsupported encoding %s ignored", estr);
    04268         ext_enc = NULL;
    04269     }
    04270
    04271     int_enc = NULL;
    04272     if (p) {
    04273         if (*p == '-' && *(p+1) == '\0') {
    04274             /* Special case - "-" => no transcoding */
    04275             int_enc = (rb_encoding *)Qnil;
    04276         }
    04277         else {
    04278             idx2 = rb_enc_find_index(p);
    04279             if (idx2 < 0)
    04280                 rb_warn("Unsupported encoding %s ignored", p);
    04281             else if (idx2 == idx) {
    04282                 rb_warn("Ignoring internal encoding %s: it is identical to external encoding %s", p, estr);
    04283                 int_enc = (rb_encoding *)Qnil;
    04284             }
    04285             else
    04286                 int_enc = rb_enc_from_index(idx2);
    04287         }
    04288     }
    04289
    04290     rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p);
    04291 }
    04292
    04293 static void
    04294 mode_enc(rb_io_t *fptr, const char *estr)
    04295 {
    04296     clear_codeconv(fptr);
    04297
    04298     parse_mode_enc(estr, &fptr->encs.enc, &fptr->encs.enc2, NULL);
    04299 }
    04300
    04301 static void
    04302 rb_io_mode_enc(rb_io_t *fptr, const char *modestr)
    04303 {
    04304     const char *p = strchr(modestr, ':');
    04305     if (p) {
    04306         mode_enc(fptr, p+1);
    04307     }
    04308 }
    04309
    04310 int
    04311 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
    04312 {
    04313     VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
    04314     int extracted = 0;
    04315     rb_encoding *extencoding = NULL;
    04316     rb_encoding *intencoding = NULL;
    04317
    04318     if (!NIL_P(opt)) {
    04319         VALUE v;
    04320         v = rb_hash_lookup2(opt, sym_encoding, Qnil);
    04321         if (v != Qnil) encoding = v;
    04322         v = rb_hash_lookup2(opt, sym_extenc, Qundef);
    04323         if (v != Qnil) extenc = v;
    04324         v = rb_hash_lookup2(opt, sym_intenc, Qundef);
    04325         if (v != Qundef) intenc = v;
    04326     }
    04327     if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
    04328         rb_warn("Ignoring encoding parameter '%s': %s_encoding is used",
    04329                 StringValueCStr(encoding),
    04330                 extenc == Qundef ? "internal" : "external");
    04331         encoding = Qnil;
    04332     }
    04333     if (extenc != Qundef && !NIL_P(extenc)) {
    04334         extencoding = rb_to_encoding(extenc);
    04335     }
    04336     if (intenc != Qundef) {
    04337         if (NIL_P(intenc)) {
    04338             /* internal_encoding: nil => no transcoding */
    04339             intencoding = (rb_encoding *)Qnil;
    04340         }
    04341         else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
    04342             char *p = StringValueCStr(tmp);
    04343
    04344             if (*p == '-' && *(p+1) == '\0') {
    04345                 /* Special case - "-" => no transcoding */
    04346                 intencoding = (rb_encoding *)Qnil;
    04347             }
    04348             else {
    04349                 intencoding = rb_to_encoding(intenc);
    04350             }
    04351         }
    04352         else {
    04353             intencoding = rb_to_encoding(intenc);
    04354         }
    04355         if (extencoding == intencoding) {
    04356             intencoding = (rb_encoding *)Qnil;
    04357         }
    04358     }
    04359     if (!NIL_P(encoding)) {
    04360         extracted = 1;
    04361         parse_mode_enc(StringValueCStr(encoding), enc_p, enc2_p, fmode_p);
    04362     }
    04363     else if (extenc != Qundef || intenc != Qundef) {
    04364         extracted = 1;
    04365         rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p);
    04366     }
    04367     return extracted;
    04368 }
    04369
    04370 typedef struct rb_io_enc_t convconfig_t;
    04371
    04372 static void
    04373 validate_enc_binmode(int fmode, rb_encoding *enc, rb_encoding *enc2)
    04374 {
    04375     if ((fmode & FMODE_READABLE) &&
    04376         !enc2 &&
    04377         !(fmode & FMODE_BINMODE) &&
    04378         !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
    04379         rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
    04380 }
    04381
    04382 static void
    04383 extract_binmode(VALUE opthash, int *fmode)
    04384 {
    04385     if (!NIL_P(opthash)) {
    04386         VALUE v;
    04387         v = rb_hash_aref(opthash, sym_textmode);
    04388         if (!NIL_P(v) && RTEST(v))
    04389             *fmode |= FMODE_TEXTMODE;
    04390         v = rb_hash_aref(opthash, sym_binmode);
    04391         if (!NIL_P(v) && RTEST(v))
    04392             *fmode |= FMODE_BINMODE;
    04393
    04394         if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
    04395             rb_raise(rb_eArgError, "both textmode and binmode specified");
    04396     }
    04397 }
    04398
    04399 static void
    04400 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
    04401         int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
    04402 {
    04403     VALUE vmode;
    04404     int oflags, fmode;
    04405     rb_encoding *enc, *enc2;
    04406     int ecflags;
    04407     VALUE ecopts;
    04408     int has_enc = 0, has_vmode = 0;
    04409     VALUE intmode;
    04410
    04411     vmode = *vmode_p;
    04412
    04413     /* Set to defaults */
    04414     rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2);
    04415
    04416     if (NIL_P(vmode)) {
    04417         fmode = FMODE_READABLE;
    04418         oflags = O_RDONLY;
    04419     }
    04420     else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
    04421         vmode = intmode;
    04422         oflags = NUM2INT(intmode);
    04423         fmode = rb_io_oflags_fmode(oflags);
    04424     }
    04425     else {
    04426         const char *p;
    04427
    04428       vmode_handle:
    04429         SafeStringValue(vmode);
    04430         p = StringValueCStr(vmode);
    04431         fmode = rb_io_modestr_fmode(p);
    04432         oflags = rb_io_fmode_oflags(fmode);
    04433         p = strchr(p, ':');
    04434         if (p) {
    04435             has_enc = 1;
    04436             parse_mode_enc(p+1, &enc, &enc2, &fmode);
    04437         }
    04438         else {
    04439             rb_encoding *e;
    04440
    04441             e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
    04442             rb_io_ext_int_to_encs(e, NULL, &enc, &enc2);
    04443         }
    04444     }
    04445
    04446     if (NIL_P(opthash)) {
    04447         ecflags = 0;
    04448         ecopts = Qnil;
    04449     }
    04450     else {
    04451         VALUE v;
    04452         extract_binmode(opthash, &fmode);
    04453 #ifdef O_BINARY
    04454         if (fmode & FMODE_BINMODE)
    04455             oflags |= O_BINARY;
    04456 #endif
    04457         if (!has_vmode) {
    04458             v = rb_hash_aref(opthash, sym_mode);
    04459             if (!NIL_P(v)) {
    04460                 if (!NIL_P(vmode)) {
    04461                     rb_raise(rb_eArgError, "mode specified twice");
    04462                 }
    04463                 has_vmode = 1;
    04464                 vmode = v;
    04465                 goto vmode_handle;
    04466             }
    04467         }
    04468         v = rb_hash_aref(opthash, sym_perm);
    04469         if (!NIL_P(v)) {
    04470             if (vperm_p) {
    04471                 if (!NIL_P(*vperm_p)) {
    04472                     rb_raise(rb_eArgError, "perm specified twice");
    04473                 }
    04474                 *vperm_p = v;
    04475             }
    04476             else {
    04477                 /* perm no use, just ignore */
    04478             }
    04479         }
    04480         ecflags = rb_econv_prepare_opts(opthash, &ecopts);
    04481
    04482         if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
    04483             if (has_enc) {
    04484                 rb_raise(rb_eArgError, "encoding specified twice");
    04485             }
    04486         }
    04487     }
    04488
    04489     validate_enc_binmode(fmode, enc, enc2);
    04490
    04491     *vmode_p = vmode;
    04492
    04493     *oflags_p = oflags;
    04494     *fmode_p = fmode;
    04495     convconfig_p->enc = enc;
    04496     convconfig_p->enc2 = enc2;
    04497     convconfig_p->ecflags = ecflags;
    04498     convconfig_p->ecopts = ecopts;
    04499 }
    04500
    04501 struct sysopen_struct {
    04502     VALUE fname;
    04503     int oflags;
    04504     mode_t perm;
    04505 };
    04506
    04507 static VALUE
    04508 sysopen_func(void *ptr)
    04509 {
    04510     const struct sysopen_struct *data = ptr;
    04511     const char *fname = RSTRING_PTR(data->fname);
    04512     return (VALUE)open(fname, data->oflags, data->perm);
    04513 }
    04514
    04515 static inline int
    04516 rb_sysopen_internal(struct sysopen_struct *data)
    04517 {
    04518     return (int)rb_thread_blocking_region(sysopen_func, data, RUBY_UBF_IO, 0);
    04519 }
    04520
    04521 static int
    04522 rb_sysopen(VALUE fname, int oflags, mode_t perm)
    04523 {
    04524     int fd;
    04525     struct sysopen_struct data;
    04526
    04527 #ifdef O_BINARY
    04528     oflags |= O_BINARY;
    04529 #endif
    04530     data.fname = rb_str_encode_ospath(fname);
    04531     data.oflags = oflags;
    04532     data.perm = perm;
    04533
    04534     fd = rb_sysopen_internal(&data);
    04535     if (fd < 0) {
    04536         if (errno == EMFILE || errno == ENFILE) {
    04537             rb_gc();
    04538             fd = rb_sysopen_internal(&data);
    04539         }
    04540         if (fd < 0) {
    04541             rb_sys_fail(RSTRING_PTR(fname));
    04542         }
    04543     }
    04544     UPDATE_MAXFD(fd);
    04545     return fd;
    04546 }
    04547
    04548 FILE *
    04549 rb_fdopen(int fd, const char *modestr)
    04550 {
    04551     FILE *file;
    04552
    04553 #if defined(sun)
    04554     errno = 0;
    04555 #endif
    04556     file = fdopen(fd, modestr);
    04557     if (!file) {
    04558         if (
    04559 #if defined(sun)
    04560             errno == 0 ||
    04561 #endif
    04562             errno == EMFILE || errno == ENFILE) {
    04563             rb_gc();
    04564 #if defined(sun)
    04565             errno = 0;
    04566 #endif
    04567             file = fdopen(fd, modestr);
    04568         }
    04569         if (!file) {
    04570 #ifdef _WIN32
    04571             if (errno == 0) errno = EINVAL;
    04572 #elif defined(sun)
    04573             if (errno == 0) errno = EMFILE;
    04574 #endif
    04575             rb_sys_fail(0);
    04576         }
    04577     }
    04578
    04579     /* xxx: should be _IONBF?  A buffer in FILE may have trouble. */
    04580 #ifdef USE_SETVBUF
    04581     if (setvbuf(file, NULL, _IOFBF, 0) != 0)
    04582         rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
    04583 #endif
    04584     return file;
    04585 }
    04586
    04587 static void
    04588 io_check_tty(rb_io_t *fptr)
    04589 {
    04590     if (isatty(fptr->fd))
    04591         fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
    04592 }
    04593
    04594 static VALUE rb_io_internal_encoding(VALUE);
    04595 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
    04596
    04597 static int
    04598 io_strip_bom(VALUE io)
    04599 {
    04600     int b1, b2, b3, b4;
    04601     switch (b1 = FIX2INT(rb_io_getbyte(io))) {
    04602       case 0xEF:
    04603         b2 = FIX2INT(rb_io_getbyte(io));
    04604         if (b2 == 0xBB) {
    04605             b3 = FIX2INT(rb_io_getbyte(io));
    04606             if (b3 == 0xBF) {
    04607                 return rb_utf8_encindex();
    04608             }
    04609             rb_io_ungetbyte(io, INT2FIX(b3));
    04610         }
    04611         rb_io_ungetbyte(io, INT2FIX(b2));
    04612         break;
    04613
    04614       case 0xFE:
    04615         b2 = FIX2INT(rb_io_getbyte(io));
    04616         if (b2 == 0xFF) {
    04617             return rb_enc_find_index("UTF-16BE");
    04618         }
    04619         rb_io_ungetbyte(io, INT2FIX(b2));
    04620         break;
    04621
    04622       case 0xFF:
    04623         b2 = FIX2INT(rb_io_getbyte(io));
    04624         if (b2 == 0xFE) {
    04625             b3 = FIX2INT(rb_io_getbyte(io));
    04626             if (b3 == 0) {
    04627                 b4 = FIX2INT(rb_io_getbyte(io));
    04628                 if (b4 == 0) {
    04629                     return rb_enc_find_index("UTF-32LE");
    04630                 }
    04631                 rb_io_ungetbyte(io, INT2FIX(b4));
    04632             }
    04633             else {
    04634                 rb_io_ungetbyte(io, INT2FIX(b3));
    04635                 return rb_enc_find_index("UTF-16LE");
    04636             }
    04637             rb_io_ungetbyte(io, INT2FIX(b3));
    04638         }
    04639         rb_io_ungetbyte(io, INT2FIX(b2));
    04640         break;
    04641
    04642       case 0:
    04643         b2 = FIX2INT(rb_io_getbyte(io));
    04644         if (b2 == 0) {
    04645             b3 = FIX2INT(rb_io_getbyte(io));
    04646             if (b3 == 0xFE) {
    04647                 b4 = FIX2INT(rb_io_getbyte(io));
    04648                 if (b4 == 0xFF) {
    04649                     return rb_enc_find_index("UTF-32BE");
    04650                 }
    04651                 rb_io_ungetbyte(io, INT2FIX(b4));
    04652             }
    04653             rb_io_ungetbyte(io, INT2FIX(b3));
    04654         }
    04655         rb_io_ungetbyte(io, INT2FIX(b2));
    04656         break;
    04657     }
    04658     rb_io_ungetbyte(io, INT2FIX(b1));
    04659     return 0;
    04660 }
    04661
    04662 static void
    04663 io_set_encoding_by_bom(VALUE io)
    04664 {
    04665     int idx = io_strip_bom(io);
    04666
    04667     if (idx) {
    04668         rb_io_t *fptr;
    04669         GetOpenFile(io, fptr);
    04670         io_encoding_set(fptr, rb_enc_from_encoding(rb_enc_from_index(idx)),
    04671                 rb_io_internal_encoding(io), Qnil);
    04672     }
    04673 }
    04674
    04675 static VALUE
    04676 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
    04677 {
    04678     rb_io_t *fptr;
    04679     convconfig_t cc;
    04680     if (!convconfig) {
    04681         /* Set to default encodings */
    04682         rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2);
    04683         cc.ecflags = 0;
    04684         cc.ecopts = Qnil;
    04685         convconfig = &cc;
    04686     }
    04687     validate_enc_binmode(fmode, convconfig->enc, convconfig->enc2);
    04688
    04689     MakeOpenFile(io, fptr);
    04690     fptr->mode = fmode;
    04691     fptr->encs = *convconfig;
    04692     fptr->pathv = rb_str_new_frozen(filename);
    04693     fptr->fd = rb_sysopen(fptr->pathv, oflags, perm);
    04694     io_check_tty(fptr);
    04695     if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
    04696
    04697     return io;
    04698 }
    04699
    04700 static VALUE
    04701 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
    04702 {
    04703     int fmode = rb_io_modestr_fmode(modestr);
    04704     const char *p = strchr(modestr, ':');
    04705     convconfig_t convconfig;
    04706
    04707     if (p) {
    04708         parse_mode_enc(p+1, &convconfig.enc, &convconfig.enc2, &fmode);
    04709     }
    04710     else {
    04711         rb_encoding *e;
    04712         /* Set to default encodings */
    04713
    04714         e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
    04715         rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2);
    04716         convconfig.ecflags = 0;
    04717         convconfig.ecopts = Qnil;
    04718     }
    04719
    04720     return rb_file_open_generic(io, filename,
    04721             rb_io_fmode_oflags(fmode),
    04722             fmode,
    04723             &convconfig,
    04724             0666);
    04725 }
    04726
    04727 VALUE
    04728 rb_file_open_str(VALUE fname, const char *modestr)
    04729 {
    04730     FilePathValue(fname);
    04731     return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
    04732 }
    04733
    04734 VALUE
    04735 rb_file_open(const char *fname, const char *modestr)
    04736 {
    04737     return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
    04738 }
    04739
    04740 #if defined(__CYGWIN__) || !defined(HAVE_FORK)
    04741 static struct pipe_list {
    04742     rb_io_t *fptr;
    04743     struct pipe_list *next;
    04744 } *pipe_list;
    04745
    04746 static void
    04747 pipe_add_fptr(rb_io_t *fptr)
    04748 {
    04749     struct pipe_list *list;
    04750
    04751     list = ALLOC(struct pipe_list);
    04752     list->fptr = fptr;
    04753     list->next = pipe_list;
    04754     pipe_list = list;
    04755 }
    04756
    04757 static void
    04758 pipe_del_fptr(rb_io_t *fptr)
    04759 {
    04760     struct pipe_list *list = pipe_list;
    04761     struct pipe_list *tmp;
    04762
    04763     if (list->fptr == fptr) {
    04764         pipe_list = list->next;
    04765         free(list);
    04766         return;
    04767     }
    04768
    04769     while (list->next) {
    04770         if (list->next->fptr == fptr) {
    04771             tmp = list->next;
    04772             list->next = list->next->next;
    04773             free(tmp);
    04774             return;
    04775         }
    04776         list = list->next;
    04777     }
    04778 }
    04779
    04780 static void
    04781 pipe_atexit(void)
    04782 {
    04783     struct pipe_list *list = pipe_list;
    04784     struct pipe_list *tmp;
    04785
    04786     while (list) {
    04787         tmp = list->next;
    04788         rb_io_fptr_finalize(list->fptr);
    04789         list = tmp;
    04790     }
    04791 }
    04792
    04793 static void
    04794 pipe_finalize(rb_io_t *fptr, int noraise)
    04795 {
    04796 #if !defined(HAVE_FORK) && !defined(_WIN32)
    04797     int status = 0;
    04798     if (fptr->stdio_file) {
    04799         status = pclose(fptr->stdio_file);
    04800     }
    04801     fptr->fd = -1;
    04802     fptr->stdio_file = 0;
    04803     rb_last_status_set(status, fptr->pid);
    04804 #else
    04805     fptr_finalize(fptr, noraise);
    04806 #endif
    04807     pipe_del_fptr(fptr);
    04808 }
    04809 #endif
    04810
    04811 void
    04812 rb_io_synchronized(rb_io_t *fptr)
    04813 {
    04814     rb_io_check_initialized(fptr);
    04815     fptr->mode |= FMODE_SYNC;
    04816 }
    04817
    04818 void
    04819 rb_io_unbuffered(rb_io_t *fptr)
    04820 {
    04821     rb_io_synchronized(fptr);
    04822 }
    04823
    04824 int
    04825 rb_pipe(int *pipes)
    04826 {
    04827     int ret;
    04828     ret = pipe(pipes);
    04829     if (ret == -1) {
    04830         if (errno == EMFILE || errno == ENFILE) {
    04831             rb_gc();
    04832             ret = pipe(pipes);
    04833         }
    04834     }
    04835     if (ret == 0) {
    04836         UPDATE_MAXFD(pipes[0]);
    04837         UPDATE_MAXFD(pipes[1]);
    04838     }
    04839     return ret;
    04840 }
    04841
    04842 #ifdef HAVE_FORK
    04843 struct popen_arg {
    04844     struct rb_exec_arg *execp;
    04845     int modef;
    04846     int pair[2];
    04847     int write_pair[2];
    04848 };
    04849
    04850 static void
    04851 popen_redirect(struct popen_arg *p)
    04852 {
    04853     if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
    04854         close(p->write_pair[1]);
    04855         if (p->write_pair[0] != 0) {
    04856             dup2(p->write_pair[0], 0);
    04857             close(p->write_pair[0]);
    04858         }
    04859         close(p->pair[0]);
    04860         if (p->pair[1] != 1) {
    04861             dup2(p->pair[1], 1);
    04862             close(p->pair[1]);
    04863         }
    04864     }
    04865     else if (p->modef & FMODE_READABLE) {
    04866         close(p->pair[0]);
    04867         if (p->pair[1] != 1) {
    04868             dup2(p->pair[1], 1);
    04869             close(p->pair[1]);
    04870         }
    04871     }
    04872     else {
    04873         close(p->pair[1]);
    04874         if (p->pair[0] != 0) {
    04875             dup2(p->pair[0], 0);
    04876             close(p->pair[0]);
    04877         }
    04878     }
    04879 }
    04880
    04881 void
    04882 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
    04883 {
    04884     int fd, ret;
    04885     int max = max_file_descriptor;
    04886     if (max < maxhint)
    04887         max = maxhint;
    04888     for (fd = lowfd; fd <= max; fd++) {
    04889         if (!NIL_P(noclose_fds) &&
    04890             RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd))))
    04891             continue;
    04892 #ifdef FD_CLOEXEC
    04893         ret = fcntl(fd, F_GETFD);
    04894         if (ret != -1 && !(ret & FD_CLOEXEC)) {
    04895             fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
    04896         }
    04897 #else
    04898         ret = close(fd);
    04899 #endif
    04900 #define CONTIGUOUS_CLOSED_FDS 20
    04901         if (ret != -1) {
    04902             if (max < fd + CONTIGUOUS_CLOSED_FDS)
    04903                 max = fd + CONTIGUOUS_CLOSED_FDS;
    04904         }
    04905     }
    04906 }
    04907
    04908 static int
    04909 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
    04910 {
    04911     struct popen_arg *p = (struct popen_arg*)pp;
    04912
    04913     rb_thread_atfork_before_exec();
    04914     return rb_exec_err(p->execp, errmsg, errmsg_len);
    04915 }
    04916 #endif
    04917
    04918 static VALUE
    04919 pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
    04920 {
    04921     rb_pid_t pid = 0;
    04922     rb_io_t *fptr;
    04923     VALUE port;
    04924     rb_io_t *write_fptr;
    04925     VALUE write_port;
    04926 #if defined(HAVE_FORK)
    04927     int status;
    04928     struct popen_arg arg;
    04929     char errmsg[80] = { '\0' };
    04930 #elif defined(_WIN32)
    04931     volatile VALUE argbuf;
    04932     char **args = NULL;
    04933     int pair[2], write_pair[2];
    04934 #endif
    04935 #if !defined(HAVE_FORK)
    04936     struct rb_exec_arg sarg;
    04937 #endif
    04938     FILE *fp = 0;
    04939     int fd = -1;
    04940     int write_fd = -1;
    04941     const char *cmd = 0;
    04942     int argc;
    04943     VALUE *argv;
    04944
    04945     if (prog)
    04946         cmd = StringValueCStr(prog);
    04947
    04948     if (!eargp) {
    04949         /* fork : IO.popen("-") */
    04950         argc = 0;
    04951         argv = 0;
    04952     }
    04953     else if (eargp->argc) {
    04954         /* no shell : IO.popen([prog, arg0], arg1, ...) */
    04955         argc = eargp->argc;
    04956         argv = eargp->argv;
    04957     }
    04958     else {
    04959         /* with shell : IO.popen(prog) */
    04960         argc = 0;
    04961         argv = 0;
    04962     }
    04963
    04964 #if defined(HAVE_FORK)
    04965     arg.execp = eargp;
    04966     arg.modef = fmode;
    04967     arg.pair[0] = arg.pair[1] = -1;
    04968     arg.write_pair[0] = arg.write_pair[1] = -1;
    04969     switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
    04970       case FMODE_READABLE|FMODE_WRITABLE:
    04971         if (rb_pipe(arg.write_pair) < 0)
    04972             rb_sys_fail(cmd);
    04973         if (rb_pipe(arg.pair) < 0) {
    04974             int e = errno;
    04975             close(arg.write_pair[0]);
    04976             close(arg.write_pair[1]);
    04977             errno = e;
    04978             rb_sys_fail(cmd);
    04979         }
    04980         if (eargp) {
    04981             rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.write_pair[0]));
    04982             rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1]));
    04983         }
    04984         break;
    04985       case FMODE_READABLE:
    04986         if (rb_pipe(arg.pair) < 0)
    04987             rb_sys_fail(cmd);
    04988         if (eargp)
    04989             rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1]));
    04990         break;
    04991       case FMODE_WRITABLE:
    04992         if (rb_pipe(arg.pair) < 0)
    04993             rb_sys_fail(cmd);
    04994         if (eargp)
    04995             rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.pair[0]));
    04996         break;
    04997       default:
    04998         rb_sys_fail(cmd);
    04999     }
    05000     if (eargp) {
    05001         rb_exec_arg_fixup(arg.execp);
    05002         pid = rb_fork_err(&status, popen_exec, &arg, arg.execp->redirect_fds, errmsg, sizeof(errmsg));
    05003     }
    05004     else {
    05005         fflush(stdin);          /* is it really needed? */
    05006         pid = rb_fork(&status, 0, 0, Qnil);
    05007         if (pid == 0) {         /* child */
    05008             popen_redirect(&arg);
    05009             rb_io_synchronized(RFILE(orig_stdout)->fptr);
    05010             rb_io_synchronized(RFILE(orig_stderr)->fptr);
    05011             return Qnil;
    05012         }
    05013     }
    05014
    05015     /* parent */
    05016     if (pid == -1) {
    05017         int e = errno;
    05018         close(arg.pair[0]);
    05019         close(arg.pair[1]);
    05020         if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
    05021             close(arg.write_pair[0]);
    05022             close(arg.write_pair[1]);
    05023         }
    05024         errno = e;
    05025         if (errmsg[0])
    05026             rb_sys_fail(errmsg);
    05027         rb_sys_fail(cmd);
    05028     }
    05029     if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
    05030         close(arg.pair[1]);
    05031         fd = arg.pair[0];
    05032         close(arg.write_pair[0]);
    05033         write_fd = arg.write_pair[1];
    05034     }
    05035     else if (fmode & FMODE_READABLE) {
    05036         close(arg.pair[1]);
    05037         fd = arg.pair[0];
    05038     }
    05039     else {
    05040         close(arg.pair[0]);
    05041         fd = arg.pair[1];
    05042     }
    05043 #elif defined(_WIN32)
    05044     if (argc) {
    05045         int i;
    05046
    05047         if (argc >= (int)(FIXNUM_MAX / sizeof(char *))) {
    05048             rb_raise(rb_eArgError, "too many arguments");
    05049         }
    05050         argbuf = rb_str_tmp_new((argc+1) * sizeof(char *));
    05051         args = (void *)RSTRING_PTR(argbuf);
    05052         for (i = 0; i < argc; ++i) {
    05053             args[i] = StringValueCStr(argv[i]);
    05054         }
    05055         args[i] = NULL;
    05056     }
    05057     switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
    05058       case FMODE_READABLE|FMODE_WRITABLE:
    05059         if (rb_pipe(write_pair) < 0)
    05060             rb_sys_fail(cmd);
    05061         if (rb_pipe(pair) < 0) {
    05062             int e = errno;
    05063             close(write_pair[0]);
    05064             close(write_pair[1]);
    05065             errno = e;
    05066             rb_sys_fail(cmd);
    05067         }
    05068         if (eargp) {
    05069             rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(write_pair[0]));
    05070             rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(pair[1]));
    05071         }
    05072         break;
    05073       case FMODE_READABLE:
    05074         if (rb_pipe(pair) < 0)
    05075             rb_sys_fail(cmd);
    05076         if (eargp)
    05077             rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(pair[1]));
    05078         break;
    05079       case FMODE_WRITABLE:
    05080         if (rb_pipe(pair) < 0)
    05081             rb_sys_fail(cmd);
    05082         if (eargp)
    05083             rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(pair[0]));
    05084         break;
    05085       default:
    05086         rb_sys_fail(cmd);
    05087     }
    05088     if (eargp) {
    05089         rb_exec_arg_fixup(eargp);
    05090         rb_run_exec_options(eargp, &sarg);
    05091     }
    05092     while ((pid = (args ?
    05093                    rb_w32_aspawn(P_NOWAIT, cmd, args) :
    05094                    rb_w32_spawn(P_NOWAIT, cmd, 0))) == -1) {
    05095         /* exec failed */
    05096         switch (errno) {
    05097           case EAGAIN:
    05098 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
    05099           case EWOULDBLOCK:
    05100 #endif
    05101             rb_thread_sleep(1);
    05102             break;
    05103           default:
    05104             {
    05105                 int e = errno;
    05106                 if (eargp)
    05107                     rb_run_exec_options(&sarg, NULL);
    05108                 close(pair[0]);
    05109                 close(pair[1]);
    05110                 if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
    05111                     close(write_pair[0]);
    05112                     close(write_pair[1]);
    05113                 }
    05114                 errno = e;
    05115                 rb_sys_fail(cmd);
    05116             }
    05117             break;
    05118         }
    05119     }
    05120
    05121     RB_GC_GUARD(argbuf);
    05122
    05123     if (eargp)
    05124         rb_run_exec_options(&sarg, NULL);
    05125     if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
    05126         close(pair[1]);
    05127         fd = pair[0];
    05128         close(write_pair[0]);
    05129         write_fd = write_pair[1];
    05130     }
    05131     else if (fmode & FMODE_READABLE) {
    05132         close(pair[1]);
    05133         fd = pair[0];
    05134     }
    05135     else {
    05136         close(pair[0]);
    05137         fd = pair[1];
    05138     }
    05139 #else
    05140     if (argc) {
    05141         prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
    05142         cmd = StringValueCStr(prog);
    05143     }
    05144     if (eargp) {
    05145         rb_exec_arg_fixup(eargp);
    05146         rb_run_exec_options(eargp, &sarg);
    05147     }
    05148     fp = popen(cmd, modestr);
    05149     if (eargp)
    05150         rb_run_exec_options(&sarg, NULL);
    05151     if (!fp) rb_sys_fail(RSTRING_PTR(prog));
    05152     fd = fileno(fp);
    05153 #endif
    05154
    05155     port = io_alloc(rb_cIO);
    05156     MakeOpenFile(port, fptr);
    05157     fptr->fd = fd;
    05158     fptr->stdio_file = fp;
    05159     fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
    05160     if (convconfig) {
    05161         fptr->encs = *convconfig;
    05162     }
    05163     fptr->pid = pid;
    05164
    05165     if (0 <= write_fd) {
    05166         write_port = io_alloc(rb_cIO);
    05167         MakeOpenFile(write_port, write_fptr);
    05168         write_fptr->fd = write_fd;
    05169         write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
    05170         fptr->mode &= ~FMODE_WRITABLE;
    05171         fptr->tied_io_for_writing = write_port;
    05172         rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
    05173     }
    05174
    05175 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
    05176     fptr->finalize = pipe_finalize;
    05177     pipe_add_fptr(fptr);
    05178 #endif
    05179     return port;
    05180 }
    05181
    05182 static VALUE
    05183 pipe_open_v(int argc, VALUE *argv, const char *modestr, int fmode, convconfig_t *convconfig)
    05184 {
    05185     VALUE prog;
    05186     struct rb_exec_arg earg;
    05187     prog = rb_exec_arg_init(argc, argv, FALSE, &earg);
    05188     return pipe_open(&earg, prog, modestr, fmode, convconfig);
    05189 }
    05190
    05191 static VALUE
    05192 pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
    05193 {
    05194     const char *cmd = RSTRING_PTR(prog);
    05195     int argc = 1;
    05196     VALUE *argv = &prog;
    05197     struct rb_exec_arg earg;
    05198
    05199     if (RSTRING_LEN(prog) == 1 && cmd[0] == '-') {
    05200 #if !defined(HAVE_FORK)
    05201         rb_raise(rb_eNotImpError,
    05202                  "fork() function is unimplemented on this machine");
    05203 #endif
    05204         return pipe_open(0, 0, modestr, fmode, convconfig);
    05205     }
    05206
    05207     rb_exec_arg_init(argc, argv, TRUE, &earg);
    05208     return pipe_open(&earg, prog, modestr, fmode, convconfig);
    05209 }
    05210
    05211 static VALUE
    05212 pop_last_hash(int *argc_p, VALUE *argv)
    05213 {
    05214     VALUE last, tmp;
    05215     if (*argc_p == 0)
    05216         return Qnil;
    05217     last = argv[*argc_p-1];
    05218     if (NIL_P(last)) return Qnil;
    05219     tmp = rb_check_convert_type(last, T_HASH, "Hash", "to_hash");
    05220     if (NIL_P(tmp))
    05221         return Qnil;
    05222     (*argc_p)--;
    05223     return tmp;
    05224 }
    05225
    05226 /*
    05227  *  call-seq:
    05228  *     IO.popen(cmd, mode="r" [, opt])               -> io
    05229  *     IO.popen(cmd, mode="r" [, opt]) {|io| block } -> obj
    05230  *
    05231  *  Runs the specified command as a subprocess; the subprocess's
    05232  *  standard input and output will be connected to the returned
    05233  *  <code>IO</code> object.
    05234  *
    05235  *  The PID of the started process can be obtained by IO#pid method.
    05236  *
    05237  *  _cmd_ is a string or an array as follows.
    05238  *
    05239  *    cmd:
    05240  *      "-"                                      : fork
    05241  *      commandline                              : command line string which is passed to a shell
    05242  *      [env, cmdname, arg1, ..., opts]          : command name and zero or more arguments (no shell)
    05243  *      [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
    05244  *    (env and opts are optional.)
    05245  *
    05246  *  If _cmd_ is a +String+ ``<code>-</code>'',
    05247  *  then a new instance of Ruby is started as the subprocess.
    05248  *
    05249  *  If <i>cmd</i> is an +Array+ of +String+,
    05250  *  then it will be used as the subprocess's +argv+ bypassing a shell.
    05251  *  The array can contains a hash at first for environments and
    05252  *  a hash at last for options similar to <code>spawn</code>.
    05253  *
    05254  *  The default mode for the new file object is ``r'',
    05255  *  but <i>mode</i> may be set to any of the modes listed in the description for class IO.
    05256  *  The last argument <i>opt</i> qualifies <i>mode</i>.
    05257  *
    05258  *    # set IO encoding
    05259  *    IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
    05260  *      euc_jp_string = nkf_io.read
    05261  *    }
    05262  *
    05263  *    # merge standard output and standard error using
    05264  *    # spawn option.  See the document of Kernel.spawn.
    05265  *    IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
    05266  *      ls_result_with_error = ls_io.read
    05267  *    }
    05268  *
    05269  *  Raises exceptions which <code>IO.pipe</code> and
    05270  *  <code>Kernel.spawn</code> raise.
    05271  *
    05272  *  If a block is given, Ruby will run the command as a child connected
    05273  *  to Ruby with a pipe. Ruby's end of the pipe will be passed as a
    05274  *  parameter to the block.
    05275  *  At the end of block, Ruby close the pipe and sets <code>$?</code>.
    05276  *  In this case <code>IO.popen</code> returns
    05277  *  the value of the block.
    05278  *
    05279  *  If a block is given with a _cmd_ of ``<code>-</code>'',
    05280  *  the block will be run in two separate processes: once in the parent,
    05281  *  and once in a child. The parent process will be passed the pipe
    05282  *  object as a parameter to the block, the child version of the block
    05283  *  will be passed <code>nil</code>, and the child's standard in and
    05284  *  standard out will be connected to the parent through the pipe. Not
    05285  *  available on all platforms.
    05286  *
    05287  *     f = IO.popen("uname")
    05288  *     p f.readlines
    05289  *     f.close
    05290  *     puts "Parent is #{Process.pid}"
    05291  *     IO.popen("date") { |f| puts f.gets }
    05292  *     IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
    05293  *     p $?
    05294  *     IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
    05295  *       f.puts "bar"; f.close_write; puts f.gets
    05296  *     }
    05297  *
    05298  *  <em>produces:</em>
    05299  *
    05300  *     ["Linux\n"]
    05301  *     Parent is 21346
    05302  *     Thu Jan 15 22:41:19 JST 2009
    05303  *     21346 is here, f is #<IO:fd 3>
    05304  *     21352 is here, f is nil
    05305  *     #<Process::Status: pid 21352 exit 0>
    05306  *     <foo>bar;zot;
    05307  */
    05308
    05309 static VALUE
    05310 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
    05311 {
    05312     const char *modestr;
    05313     VALUE pname, pmode, port, tmp, opt;
    05314     int oflags, fmode;
    05315     convconfig_t convconfig;
    05316
    05317     opt = pop_last_hash(&argc, argv);
    05318     rb_scan_args(argc, argv, "11", &pname, &pmode);
    05319
    05320     rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
    05321     modestr = rb_io_oflags_modestr(oflags);
    05322
    05323     tmp = rb_check_array_type(pname);
    05324     if (!NIL_P(tmp)) {
    05325         long len = RARRAY_LEN(tmp);
    05326 #if SIZEOF_LONG > SIZEOF_INT
    05327         if (len > INT_MAX) {
    05328             rb_raise(rb_eArgError, "too many arguments");
    05329         }
    05330 #endif
    05331         tmp = rb_ary_dup(tmp);
    05332         RBASIC(tmp)->klass = 0;
    05333         port = pipe_open_v((int)len, RARRAY_PTR(tmp), modestr, fmode, &convconfig);
    05334         rb_ary_clear(tmp);
    05335     }
    05336     else {
    05337         SafeStringValue(pname);
    05338         port = pipe_open_s(pname, modestr, fmode, &convconfig);
    05339     }
    05340     if (NIL_P(port)) {
    05341         /* child */
    05342         if (rb_block_given_p()) {
    05343             rb_yield(Qnil);
    05344             rb_io_flush(rb_stdout);
    05345             rb_io_flush(rb_stderr);
    05346             _exit(0);
    05347         }
    05348         return Qnil;
    05349     }
    05350     RBASIC(port)->klass = klass;
    05351     if (rb_block_given_p()) {
    05352         return rb_ensure(rb_yield, port, io_close, port);
    05353     }
    05354     return port;
    05355 }
    05356
    05357 static void
    05358 rb_scan_open_args(int argc, VALUE *argv,
    05359         VALUE *fname_p, int *oflags_p, int *fmode_p,
    05360         convconfig_t *convconfig_p, mode_t *perm_p)
    05361 {
    05362     VALUE opt=Qnil, fname, vmode, vperm;
    05363     int oflags, fmode;
    05364     mode_t perm;
    05365
    05366     opt = pop_last_hash(&argc, argv);
    05367     rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
    05368     FilePathValue(fname);
    05369
    05370     rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
    05371
    05372     perm = NIL_P(vperm) ? 0666 :  NUM2UINT(vperm);
    05373
    05374     *fname_p = fname;
    05375     *oflags_p = oflags;
    05376     *fmode_p = fmode;
    05377     *perm_p = perm;
    05378 }
    05379
    05380 static VALUE
    05381 rb_open_file(int argc, VALUE *argv, VALUE io)
    05382 {
    05383     VALUE fname;
    05384     int oflags, fmode;
    05385     convconfig_t convconfig;
    05386     mode_t perm;
    05387
    05388     rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
    05389     rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
    05390
    05391     return io;
    05392 }
    05393
    05394
    05395 /*
    05396  *  Document-method: File::open
    05397  *
    05398  *  call-seq:
    05399  *     File.open(filename, mode="r" [, opt])                 -> file
    05400  *     File.open(filename [, mode [, perm]] [, opt])         -> file
    05401  *     File.open(filename, mode="r" [, opt]) {|file| block } -> obj
    05402  *     File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
    05403  *
    05404  *  With no associated block, <code>open</code> is a synonym for
    05405  *  <code>File.new</code>. If the optional code block is given, it will
    05406  *  be passed <i>file</i> as an argument, and the File object will
    05407  *  automatically be closed when the block terminates. In this instance,
    05408  *  <code>File.open</code> returns the value of the block.
    05409  */
    05410
    05411 /*
    05412  *  Document-method: IO::open
    05413  *
    05414  *  call-seq:
    05415  *     IO.open(fd, mode_string="r" [, opt] )               -> io
    05416  *     IO.open(fd, mode_string="r" [, opt] ) {|io| block } -> obj
    05417  *
    05418  *  With no associated block, <code>open</code> is a synonym for
    05419  *  <code>IO.new</code>. If the optional code block is given, it will
    05420  *  be passed <i>io</i> as an argument, and the IO object will
    05421  *  automatically be closed when the block terminates. In this instance,
    05422  *  <code>IO.open</code> returns the value of the block.
    05423  *
    05424  */
    05425
    05426 static VALUE
    05427 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
    05428 {
    05429     VALUE io = rb_class_new_instance(argc, argv, klass);
    05430
    05431     if (rb_block_given_p()) {
    05432         return rb_ensure(rb_yield, io, io_close, io);
    05433     }
    05434
    05435     return io;
    05436 }
    05437
    05438 /*
    05439  *  call-seq:
    05440  *     IO.sysopen(path, [mode, [perm]])  -> fixnum
    05441  *
    05442  *  Opens the given path, returning the underlying file descriptor as a
    05443  *  <code>Fixnum</code>.
    05444  *
    05445  *     IO.sysopen("testfile")   #=> 3
    05446  *
    05447  */
    05448
    05449 static VALUE
    05450 rb_io_s_sysopen(int argc, VALUE *argv)
    05451 {
    05452     VALUE fname, vmode, vperm;
    05453     VALUE intmode;
    05454     int oflags, fd;
    05455     mode_t perm;
    05456
    05457     rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
    05458     FilePathValue(fname);
    05459
    05460     if (NIL_P(vmode))
    05461         oflags = O_RDONLY;
    05462     else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
    05463         oflags = NUM2INT(intmode);
    05464     else {
    05465         SafeStringValue(vmode);
    05466         oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
    05467     }
    05468     if (NIL_P(vperm)) perm = 0666;
    05469     else              perm = NUM2UINT(vperm);
    05470
    05471     RB_GC_GUARD(fname) = rb_str_new4(fname);
    05472     fd = rb_sysopen(fname, oflags, perm);
    05473     return INT2NUM(fd);
    05474 }
    05475
    05476 static VALUE
    05477 check_pipe_command(VALUE filename_or_command)
    05478 {
    05479     char *s = RSTRING_PTR(filename_or_command);
    05480     long l = RSTRING_LEN(filename_or_command);
    05481     char *e = s + l;
    05482     int chlen;
    05483
    05484     if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
    05485         VALUE cmd = rb_str_new(s+chlen, l-chlen);
    05486         OBJ_INFECT(cmd, filename_or_command);
    05487         return cmd;
    05488     }
    05489     return Qnil;
    05490 }
    05491
    05492 /*
    05493  *  call-seq:
    05494  *     open(path [, mode_enc [, perm]] [, opt] )                -> io or nil
    05495  *     open(path [, mode_enc [, perm]] [, opt] ) {|io| block }  -> obj
    05496  *
    05497  *  Creates an <code>IO</code> object connected to the given stream,
    05498  *  file, or subprocess.
    05499  *
    05500  *  If <i>path</i> does not start with a pipe character
    05501  *  (``<code>|</code>''), treat it as the name of a file to open using
    05502  *  the specified mode (defaulting to ``<code>r</code>'').
    05503  *
    05504  *  The mode_enc is
    05505  *  either a string or an integer.  If it is an integer, it must be
    05506  *  bitwise-or of open(2) flags, such as File::RDWR or File::EXCL.
    05507  *  If it is a string, it is either "mode", "mode:ext_enc", or
    05508  *  "mode:ext_enc:int_enc".
    05509  *  The mode is one of the following:
    05510  *
    05511  *   r: read (default)
    05512  *   w: write
    05513  *   a: append
    05514  *
    05515  *  The mode can be followed by "b" (means binary-mode), or "+"
    05516  *  (means both reading and writing allowed) or both.
    05517  *  If ext_enc (external encoding) is specified,
    05518  *  read string will be tagged by the encoding in reading,
    05519  *  and output string will be converted
    05520  *  to the specified encoding in writing.
    05521  *  If ext_enc starts with 'BOM|', check whether the input has a BOM. If
    05522  *  there is a BOM, strip it and set external encoding as
    05523  *  what the BOM tells. If there is no BOM, use ext_enc without 'BOM|'.
    05524  *  If two encoding names,
    05525  *  ext_enc and int_enc (external encoding and internal encoding),
    05526  *  are specified, the read string is converted from ext_enc
    05527  *  to int_enc then tagged with the int_enc in read mode,
    05528  *  and in write mode, the output string will be
    05529  *  converted from int_enc to ext_enc before writing.
    05530  *
    05531  *  If a file is being created, its initial permissions may be
    05532  *  set using the integer third parameter.
    05533  *
    05534  *  If a block is specified, it will be invoked with the
    05535  *  <code>File</code> object as a parameter, and the file will be
    05536  *  automatically closed when the block terminates. The call
    05537  *  returns the value of the block.
    05538  *
    05539  *  If <i>path</i> starts with a pipe character, a subprocess is
    05540  *  created, connected to the caller by a pair of pipes. The returned
    05541  *  <code>IO</code> object may be used to write to the standard input
    05542  *  and read from the standard output of this subprocess. If the command
    05543  *  following the ``<code>|</code>'' is a single minus sign, Ruby forks,
    05544  *  and this subprocess is connected to the parent. In the subprocess,
    05545  *  the <code>open</code> call returns <code>nil</code>. If the command
    05546  *  is not ``<code>-</code>'', the subprocess runs the command. If a
    05547  *  block is associated with an <code>open("|-")</code> call, that block
    05548  *  will be run twice---once in the parent and once in the child. The
    05549  *  block parameter will be an <code>IO</code> object in the parent and
    05550  *  <code>nil</code> in the child. The parent's <code>IO</code> object
    05551  *  will be connected to the child's <code>$stdin</code> and
    05552  *  <code>$stdout</code>. The subprocess will be terminated at the end
    05553  *  of the block.
    05554  *
    05555  *     open("testfile") do |f|
    05556  *       print f.gets
    05557  *     end
    05558  *
    05559  *  <em>produces:</em>
    05560  *
    05561  *     This is line one
    05562  *
    05563  *  Open a subprocess and read its output:
    05564  *
    05565  *     cmd = open("|date")
    05566  *     print cmd.gets
    05567  *     cmd.close
    05568  *
    05569  *  <em>produces:</em>
    05570  *
    05571  *     Wed Apr  9 08:56:31 CDT 2003
    05572  *
    05573  *  Open a subprocess running the same Ruby program:
    05574  *
    05575  *     f = open("|-", "w+")
    05576  *     if f == nil
    05577  *       puts "in Child"
    05578  *       exit
    05579  *     else
    05580  *       puts "Got: #{f.gets}"
    05581  *     end
    05582  *
    05583  *  <em>produces:</em>
    05584  *
    05585  *     Got: in Child
    05586  *
    05587  *  Open a subprocess using a block to receive the I/O object:
    05588  *
    05589  *     open("|-") do |f|
    05590  *       if f == nil
    05591  *         puts "in Child"
    05592  *       else
    05593  *         puts "Got: #{f.gets}"
    05594  *       end
    05595  *     end
    05596  *
    05597  *  <em>produces:</em>
    05598  *
    05599  *     Got: in Child
    05600  */
    05601
    05602 static VALUE
    05603 rb_f_open(int argc, VALUE *argv)
    05604 {
    05605     ID to_open = 0;
    05606     int redirect = FALSE;
    05607
    05608     if (argc >= 1) {
    05609         CONST_ID(to_open, "to_open");
    05610         if (rb_respond_to(argv[0], to_open)) {
    05611             redirect = TRUE;
    05612         }
    05613         else {
    05614             VALUE tmp = argv[0];
    05615             FilePathValue(tmp);
    05616             if (NIL_P(tmp)) {
    05617                 redirect = TRUE;
    05618             }
    05619             else {
    05620                 VALUE cmd = check_pipe_command(tmp);
    05621                 if (!NIL_P(cmd)) {
    05622                     argv[0] = cmd;
    05623                     return rb_io_s_popen(argc, argv, rb_cIO);
    05624                 }
    05625             }
    05626         }
    05627     }
    05628     if (redirect) {
    05629         VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
    05630
    05631         if (rb_block_given_p()) {
    05632             return rb_ensure(rb_yield, io, io_close, io);
    05633         }
    05634         return io;
    05635     }
    05636     return rb_io_s_open(argc, argv, rb_cFile);
    05637 }
    05638
    05639 static VALUE
    05640 rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
    05641 {
    05642     VALUE cmd;
    05643     int oflags, fmode;
    05644     convconfig_t convconfig;
    05645     mode_t perm;
    05646
    05647     rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
    05648     perm = NIL_P(vperm) ? 0666 :  NUM2UINT(vperm);
    05649
    05650     if (!NIL_P(cmd = check_pipe_command(filename))) {
    05651         return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, &convconfig);
    05652     }
    05653     else {
    05654         return rb_file_open_generic(io_alloc(rb_cFile), filename,
    05655                 oflags, fmode, &convconfig, perm);
    05656     }
    05657 }
    05658
    05659 static VALUE
    05660 rb_io_open_with_args(int argc, VALUE *argv)
    05661 {
    05662     VALUE io;
    05663
    05664     io = io_alloc(rb_cFile);
    05665     rb_open_file(argc, argv, io);
    05666     return io;
    05667 }
    05668
    05669 static VALUE
    05670 io_reopen(VALUE io, VALUE nfile)
    05671 {
    05672     rb_io_t *fptr, *orig;
    05673     int fd, fd2;
    05674     off_t pos = 0;
    05675
    05676     nfile = rb_io_get_io(nfile);
    05677     if (rb_safe_level() >= 4 &&
    05678         (!OBJ_UNTRUSTED(io) || !OBJ_UNTRUSTED(nfile))) {
    05679         rb_raise(rb_eSecurityError, "Insecure: can't reopen");
    05680     }
    05681     GetOpenFile(io, fptr);
    05682     GetOpenFile(nfile, orig);
    05683
    05684     if (fptr == orig) return io;
    05685     if (IS_PREP_STDIO(fptr)) {
    05686         if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
    05687             (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
    05688             (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
    05689             rb_raise(rb_eArgError,
    05690                      "%s can't change access mode from \"%s\" to \"%s\"",
    05691                      PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
    05692                      rb_io_fmode_modestr(orig->mode));
    05693         }
    05694     }
    05695     if (fptr->mode & FMODE_WRITABLE) {
    05696         if (io_fflush(fptr) < 0)
    05697             rb_sys_fail(0);
    05698     }
    05699     else {
    05700         io_tell(fptr);
    05701     }
    05702     if (orig->mode & FMODE_READABLE) {
    05703         pos = io_tell(orig);
    05704     }
    05705     if (orig->mode & FMODE_WRITABLE) {
    05706         if (io_fflush(orig) < 0)
    05707             rb_sys_fail(0);
    05708     }
    05709
    05710     /* copy rb_io_t structure */
    05711     fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
    05712     fptr->pid = orig->pid;
    05713     fptr->lineno = orig->lineno;
    05714     if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
    05715     else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
    05716     fptr->finalize = orig->finalize;
    05717 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
    05718     if (fptr->finalize == pipe_finalize)
    05719         pipe_add_fptr(fptr);
    05720 #endif
    05721
    05722     fd = fptr->fd;
    05723     fd2 = orig->fd;
    05724     if (fd != fd2) {
    05725         if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
    05726             /* need to keep FILE objects of stdin, stdout and stderr */
    05727             if (dup2(fd2, fd) < 0)
    05728                 rb_sys_fail_path(orig->pathv);
    05729         }
    05730         else {
    05731             fclose(fptr->stdio_file);
    05732             fptr->stdio_file = 0;
    05733             fptr->fd = -1;
    05734             if (dup2(fd2, fd) < 0)
    05735                 rb_sys_fail_path(orig->pathv);
    05736             fptr->fd = fd;
    05737         }
    05738         rb_thread_fd_close(fd);
    05739         if ((orig->mode & FMODE_READABLE) && pos >= 0) {
    05740             if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
    05741                 rb_sys_fail_path(fptr->pathv);
    05742             }
    05743             if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
    05744                 rb_sys_fail_path(orig->pathv);
    05745             }
    05746         }
    05747     }
    05748
    05749     if (fptr->mode & FMODE_BINMODE) {
    05750         rb_io_binmode(io);
    05751     }
    05752
    05753     RBASIC(io)->klass = rb_obj_class(nfile);
    05754     return io;
    05755 }
    05756
    05757 /*
    05758  *  call-seq:
    05759  *     ios.reopen(other_IO)         -> ios
    05760  *     ios.reopen(path, mode_str)   -> ios
    05761  *
    05762  *  Reassociates <em>ios</em> with the I/O stream given in
    05763  *  <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
    05764  *  dynamically change the actual class of this stream.
    05765  *
    05766  *     f1 = File.new("testfile")
    05767  *     f2 = File.new("testfile")
    05768  *     f2.readlines[0]   #=> "This is line one\n"
    05769  *     f2.reopen(f1)     #=> #<File:testfile>
    05770  *     f2.readlines[0]   #=> "This is line one\n"
    05771  */
    05772
    05773 static VALUE
    05774 rb_io_reopen(int argc, VALUE *argv, VALUE file)
    05775 {
    05776     VALUE fname, nmode;
    05777     int oflags;
    05778     rb_io_t *fptr;
    05779
    05780     rb_secure(4);
    05781     if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
    05782         VALUE tmp = rb_io_check_io(fname);
    05783         if (!NIL_P(tmp)) {
    05784             return io_reopen(file, tmp);
    05785         }
    05786     }
    05787
    05788     FilePathValue(fname);
    05789     rb_io_taint_check(file);
    05790     fptr = RFILE(file)->fptr;
    05791     if (!fptr) {
    05792         fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
    05793         MEMZERO(fptr, rb_io_t, 1);
    05794     }
    05795
    05796     if (!NIL_P(nmode)) {
    05797         int fmode = rb_io_modestr_fmode(StringValueCStr(nmode));
    05798         if (IS_PREP_STDIO(fptr) &&
    05799             ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
    05800             (fptr->mode & FMODE_READWRITE)) {
    05801             rb_raise(rb_eArgError,
    05802                      "%s can't change access mode from \"%s\" to \"%s\"",
    05803                      PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
    05804                      rb_io_fmode_modestr(fmode));
    05805         }
    05806         fptr->mode = fmode;
    05807         rb_io_mode_enc(fptr, StringValueCStr(nmode));
    05808         fptr->encs.ecflags = 0;
    05809         fptr->encs.ecopts = Qnil;
    05810     }
    05811
    05812     fptr->pathv = rb_str_new_frozen(fname);
    05813     oflags = rb_io_fmode_oflags(fptr->mode);
    05814     if (fptr->fd < 0) {
    05815         fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
    05816         fptr->stdio_file = 0;
    05817         return file;
    05818     }
    05819
    05820     if (fptr->mode & FMODE_WRITABLE) {
    05821         if (io_fflush(fptr) < 0)
    05822             rb_sys_fail(0);
    05823     }
    05824     fptr->rbuf_off = fptr->rbuf_len = 0;
    05825
    05826     if (fptr->stdio_file) {
    05827         if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
    05828             rb_sys_fail_path(fptr->pathv);
    05829         }
    05830         fptr->fd = fileno(fptr->stdio_file);
    05831 #ifdef USE_SETVBUF
    05832         if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
    05833             rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
    05834 #endif
    05835     }
    05836     else {
    05837         if (close(fptr->fd) < 0)
    05838             rb_sys_fail_path(fptr->pathv);
    05839         fptr->fd = -1;
    05840         fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
    05841     }
    05842
    05843     return file;
    05844 }
    05845
    05846 /* :nodoc: */
    05847 static VALUE
    05848 rb_io_init_copy(VALUE dest, VALUE io)
    05849 {
    05850     rb_io_t *fptr, *orig;
    05851     int fd;
    05852     VALUE write_io;
    05853     off_t pos;
    05854
    05855     io = rb_io_get_io(io);
    05856     if (dest == io) return dest;
    05857     GetOpenFile(io, orig);
    05858     MakeOpenFile(dest, fptr);
    05859
    05860     rb_io_flush(io);
    05861
    05862     /* copy rb_io_t structure */
    05863     fptr->mode = orig->mode & ~FMODE_PREP;
    05864     fptr->encs = orig->encs;
    05865     fptr->pid = orig->pid;
    05866     fptr->lineno = orig->lineno;
    05867     if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
    05868     fptr->finalize = orig->finalize;
    05869 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
    05870     if (fptr->finalize == pipe_finalize)
    05871         pipe_add_fptr(fptr);
    05872 #endif
    05873
    05874     fd = ruby_dup(orig->fd);
    05875     fptr->fd = fd;
    05876     pos = io_tell(orig);
    05877     if (0 <= pos)
    05878         io_seek(fptr, pos, SEEK_SET);
    05879     if (fptr->mode & FMODE_BINMODE) {
    05880         rb_io_binmode(dest);
    05881     }
    05882
    05883     write_io = GetWriteIO(io);
    05884     if (io != write_io) {
    05885         write_io = rb_obj_dup(write_io);
    05886         fptr->tied_io_for_writing = write_io;
    05887         rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
    05888     }
    05889
    05890     return dest;
    05891 }
    05892
    05893 /*
    05894  *  call-seq:
    05895  *     ios.printf(format_string [, obj, ...] )   -> nil
    05896  *
    05897  *  Formats and writes to <em>ios</em>, converting parameters under
    05898  *  control of the format string. See <code>Kernel#sprintf</code>
    05899  *  for details.
    05900  */
    05901
    05902 VALUE
    05903 rb_io_printf(int argc, VALUE *argv, VALUE out)
    05904 {
    05905     rb_io_write(out, rb_f_sprintf(argc, argv));
    05906     return Qnil;
    05907 }
    05908
    05909 /*
    05910  *  call-seq:
    05911  *     printf(io, string [, obj ... ] )    -> nil
    05912  *     printf(string [, obj ... ] )        -> nil
    05913  *
    05914  *  Equivalent to:
    05915  *     io.write(sprintf(string, obj, ...)
    05916  *  or
    05917  *     $stdout.write(sprintf(string, obj, ...)
    05918  */
    05919
    05920 static VALUE
    05921 rb_f_printf(int argc, VALUE *argv)
    05922 {
    05923     VALUE out;
    05924
    05925     if (argc == 0) return Qnil;
    05926     if (TYPE(argv[0]) == T_STRING) {
    05927         out = rb_stdout;
    05928     }
    05929     else {
    05930         out = argv[0];
    05931         argv++;
    05932         argc--;
    05933     }
    05934     rb_io_write(out, rb_f_sprintf(argc, argv));
    05935
    05936     return Qnil;
    05937 }
    05938
    05939 /*
    05940  *  call-seq:
    05941  *     ios.print()             -> nil
    05942  *     ios.print(obj, ...)     -> nil
    05943  *
    05944  *  Writes the given object(s) to <em>ios</em>. The stream must be
    05945  *  opened for writing. If the output field separator (<code>$,</code>)
    05946  *  is not <code>nil</code>, it will be inserted between each object.
    05947  *  If the output record separator (<code>$\</code>)
    05948  *  is not <code>nil</code>, it will be appended to the output. If no
    05949  *  arguments are given, prints <code>$_</code>. Objects that aren't
    05950  *  strings will be converted by calling their <code>to_s</code> method.
    05951  *  With no argument, prints the contents of the variable <code>$_</code>.
    05952  *  Returns <code>nil</code>.
    05953  *
    05954  *     $stdout.print("This is ", 100, " percent.\n")
    05955  *
    05956  *  <em>produces:</em>
    05957  *
    05958  *     This is 100 percent.
    05959  */
    05960
    05961 VALUE
    05962 rb_io_print(int argc, VALUE *argv, VALUE out)
    05963 {
    05964     int i;
    05965     VALUE line;
    05966
    05967     /* if no argument given, print `$_' */
    05968     if (argc == 0) {
    05969         argc = 1;
    05970         line = rb_lastline_get();
    05971         argv = &line;
    05972     }
    05973     for (i=0; i<argc; i++) {
    05974         if (!NIL_P(rb_output_fs) && i>0) {
    05975             rb_io_write(out, rb_output_fs);
    05976         }
    05977         rb_io_write(out, argv[i]);
    05978     }
    05979     if (argc > 0 && !NIL_P(rb_output_rs)) {
    05980         rb_io_write(out, rb_output_rs);
    05981     }
    05982
    05983     return Qnil;
    05984 }
    05985
    05986 /*
    05987  *  call-seq:
    05988  *     print(obj, ...)    -> nil
    05989  *
    05990  *  Prints each object in turn to <code>$stdout</code>. If the output
    05991  *  field separator (<code>$,</code>) is not +nil+, its
    05992  *  contents will appear between each field. If the output record
    05993  *  separator (<code>$\</code>) is not +nil+, it will be
    05994  *  appended to the output. If no arguments are given, prints
    05995  *  <code>$_</code>. Objects that aren't strings will be converted by
    05996  *  calling their <code>to_s</code> method.
    05997  *
    05998  *     print "cat", [1,2,3], 99, "\n"
    05999  *     $, = ", "
    06000  *     $\ = "\n"
    06001  *     print "cat", [1,2,3], 99
    06002  *
    06003  *  <em>produces:</em>
    06004  *
    06005  *     cat12399
    06006  *     cat, 1, 2, 3, 99
    06007  */
    06008
    06009 static VALUE
    06010 rb_f_print(int argc, VALUE *argv)
    06011 {
    06012     rb_io_print(argc, argv, rb_stdout);
    06013     return Qnil;
    06014 }
    06015
    06016 /*
    06017  *  call-seq:
    06018  *     ios.putc(obj)    -> obj
    06019  *
    06020  *  If <i>obj</i> is <code>Numeric</code>, write the character whose code is
    06021  *  the least-significant byte of <i>obj</i>, otherwise write the first byte
    06022  *  of the string representation of <i>obj</i> to <em>ios</em>. Note: This
    06023  *  method is not safe for use with multi-byte characters as it will truncate
    06024  *  them.
    06025  *
    06026  *     $stdout.putc "A"
    06027  *     $stdout.putc 65
    06028  *
    06029  *  <em>produces:</em>
    06030  *
    06031  *     AA
    06032  */
    06033
    06034 static VALUE
    06035 rb_io_putc(VALUE io, VALUE ch)
    06036 {
    06037     char c = NUM2CHR(ch);
    06038
    06039     rb_io_write(io, rb_str_new(&c, 1));
    06040     return ch;
    06041 }
    06042
    06043 /*
    06044  *  call-seq:
    06045  *     putc(int)   -> int
    06046  *
    06047  *  Equivalent to:
    06048  *
    06049  *    $stdout.putc(int)
    06050  *
    06051  * Refer to the documentation for IO#putc for important information regarding
    06052  * multi-byte characters.
    06053  */
    06054
    06055 static VALUE
    06056 rb_f_putc(VALUE recv, VALUE ch)
    06057 {
    06058     if (recv == rb_stdout) {
    06059         return rb_io_putc(recv, ch);
    06060     }
    06061     return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
    06062 }
    06063
    06064
    06065 static int
    06066 str_end_with_asciichar(VALUE str, int c)
    06067 {
    06068     long len = RSTRING_LEN(str);
    06069     const char *ptr = RSTRING_PTR(str);
    06070     rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
    06071     int n;
    06072
    06073     if (len == 0) return 0;
    06074     if ((n = rb_enc_mbminlen(enc)) == 1) {
    06075         return ptr[len - 1] == c;
    06076     }
    06077     return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
    06078 }
    06079
    06080 static VALUE
    06081 io_puts_ary(VALUE ary, VALUE out, int recur)
    06082 {
    06083     VALUE tmp;
    06084     long i;
    06085
    06086     if (recur) {
    06087         tmp = rb_str_new2("[...]");
    06088         rb_io_puts(1, &tmp, out);
    06089         return Qnil;
    06090     }
    06091     for (i=0; i<RARRAY_LEN(ary); i++) {
    06092         tmp = RARRAY_PTR(ary)[i];
    06093         rb_io_puts(1, &tmp, out);
    06094     }
    06095     return Qnil;
    06096 }
    06097
    06098 /*
    06099  *  call-seq:
    06100  *     ios.puts(obj, ...)    -> nil
    06101  *
    06102  *  Writes the given objects to <em>ios</em> as with
    06103  *  <code>IO#print</code>. Writes a record separator (typically a
    06104  *  newline) after any that do not already end with a newline sequence.
    06105  *  If called with an array argument, writes each element on a new line.
    06106  *  If called without arguments, outputs a single record separator.
    06107  *
    06108  *     $stdout.puts("this", "is", "a", "test")
    06109  *
    06110  *  <em>produces:</em>
    06111  *
    06112  *     this
    06113  *     is
    06114  *     a
    06115  *     test
    06116  */
    06117
    06118 VALUE
    06119 rb_io_puts(int argc, VALUE *argv, VALUE out)
    06120 {
    06121     int i;
    06122     VALUE line;
    06123
    06124     /* if no argument given, print newline. */
    06125     if (argc == 0) {
    06126         rb_io_write(out, rb_default_rs);
    06127         return Qnil;
    06128     }
    06129     for (i=0; i<argc; i++) {
    06130         if (TYPE(argv[i]) == T_STRING) {
    06131             line = argv[i];
    06132             goto string;
    06133         }
    06134         line = rb_check_array_type(argv[i]);
    06135         if (!NIL_P(line)) {
    06136             rb_exec_recursive(io_puts_ary, line, out);
    06137             continue;
    06138         }
    06139         line = rb_obj_as_string(argv[i]);
    06140       string:
    06141         rb_io_write(out, line);
    06142         if (RSTRING_LEN(line) == 0 ||
    06143             !str_end_with_asciichar(line, '\n')) {
    06144             rb_io_write(out, rb_default_rs);
    06145         }
    06146     }
    06147
    06148     return Qnil;
    06149 }
    06150
    06151 /*
    06152  *  call-seq:
    06153  *     puts(obj, ...)    -> nil
    06154  *
    06155  *  Equivalent to
    06156  *
    06157  *      $stdout.puts(obj, ...)
    06158  */
    06159
    06160 static VALUE
    06161 rb_f_puts(int argc, VALUE *argv, VALUE recv)
    06162 {
    06163     if (recv == rb_stdout) {
    06164         return rb_io_puts(argc, argv, recv);
    06165     }
    06166     return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
    06167 }
    06168
    06169 void
    06170 rb_p(VALUE obj) /* for debug print within C code */
    06171 {
    06172     VALUE str = rb_obj_as_string(rb_inspect(obj));
    06173     if (TYPE(rb_stdout) == T_FILE &&
    06174         rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
    06175         io_write(rb_stdout, str, 1);
    06176         io_write(rb_stdout, rb_default_rs, 0);
    06177     }
    06178     else {
    06179         rb_io_write(rb_stdout, str);
    06180         rb_io_write(rb_stdout, rb_default_rs);
    06181     }
    06182 }
    06183
    06184 /*
    06185  *  call-seq:
    06186  *     p(obj)              -> obj
    06187  *     p(obj1, obj2, ...)  -> [obj, ...]
    06188  *     p()                 -> nil
    06189  *
    06190  *  For each object, directly writes
    06191  *  _obj_.+inspect+ followed by the current output
    06192  *  record separator to the program's standard output.
    06193  *
    06194  *     S = Struct.new(:name, :state)
    06195  *     s = S['dave', 'TX']
    06196  *     p s
    06197  *
    06198  *  <em>produces:</em>
    06199  *
    06200  *     #<S name="dave", state="TX">
    06201  */
    06202
    06203 static VALUE
    06204 rb_f_p(int argc, VALUE *argv, VALUE self)
    06205 {
    06206     int i;
    06207     VALUE ret = Qnil;
    06208
    06209     for (i=0; i<argc; i++) {
    06210         rb_p(argv[i]);
    06211     }
    06212     if (argc == 1) {
    06213         ret = argv[0];
    06214     }
    06215     else if (argc > 1) {
    06216         ret = rb_ary_new4(argc, argv);
    06217     }
    06218     if (TYPE(rb_stdout) == T_FILE) {
    06219         rb_io_flush(rb_stdout);
    06220     }
    06221     return ret;
    06222 }
    06223
    06224 /*
    06225  *  call-seq:
    06226  *     obj.display(port=$>)    -> nil
    06227  *
    06228  *  Prints <i>obj</i> on the given port (default <code>$></code>).
    06229  *  Equivalent to:
    06230  *
    06231  *     def display(port=$>)
    06232  *       port.write self
    06233  *     end
    06234  *
    06235  *  For example:
    06236  *
    06237  *     1.display
    06238  *     "cat".display
    06239  *     [ 4, 5, 6 ].display
    06240  *     puts
    06241  *
    06242  *  <em>produces:</em>
    06243  *
    06244  *     1cat456
    06245  */
    06246
    06247 static VALUE
    06248 rb_obj_display(int argc, VALUE *argv, VALUE self)
    06249 {
    06250     VALUE out;
    06251
    06252     if (argc == 0) {
    06253         out = rb_stdout;
    06254     }
    06255     else {
    06256         rb_scan_args(argc, argv, "01", &out);
    06257     }
    06258     rb_io_write(out, self);
    06259
    06260     return Qnil;
    06261 }
    06262
    06263 void
    06264 rb_write_error2(const char *mesg, long len)
    06265 {
    06266     if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
    06267         (void)fwrite(mesg, sizeof(char), len, stderr);
    06268     }
    06269     else {
    06270         rb_io_write(rb_stderr, rb_str_new(mesg, len));
    06271     }
    06272 }
    06273
    06274 void
    06275 rb_write_error(const char *mesg)
    06276 {
    06277     rb_write_error2(mesg, strlen(mesg));
    06278 }
    06279
    06280 static void
    06281 must_respond_to(ID mid, VALUE val, ID id)
    06282 {
    06283     if (!rb_respond_to(val, mid)) {
    06284         rb_raise(rb_eTypeError, "%s must have %s method, %s given",
    06285                  rb_id2name(id), rb_id2name(mid),
    06286                  rb_obj_classname(val));
    06287     }
    06288 }
    06289
    06290 static void
    06291 stdout_setter(VALUE val, ID id, VALUE *variable)
    06292 {
    06293     must_respond_to(id_write, val, id);
    06294     *variable = val;
    06295 }
    06296
    06297 static VALUE
    06298 prep_io(int fd, int fmode, VALUE klass, const char *path)
    06299 {
    06300     rb_io_t *fp;
    06301     VALUE io = io_alloc(klass);
    06302
    06303     MakeOpenFile(io, fp);
    06304     fp->fd = fd;
    06305 #ifdef __CYGWIN__
    06306     if (!isatty(fd)) {
    06307         fmode |= FMODE_BINMODE;
    06308         setmode(fd, O_BINARY);
    06309     }
    06310 #endif
    06311     fp->mode = fmode;
    06312     io_check_tty(fp);
    06313     if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
    06314
    06315     return io;
    06316 }
    06317
    06318 VALUE
    06319 rb_io_fdopen(int fd, int oflags, const char *path)
    06320 {
    06321     VALUE klass = rb_cIO;
    06322
    06323     if (path && strcmp(path, "-")) klass = rb_cFile;
    06324     return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
    06325 }
    06326
    06327 static VALUE
    06328 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
    06329 {
    06330     rb_io_t *fptr;
    06331     VALUE io = prep_io(fileno(f), fmode|FMODE_PREP, klass, path);
    06332
    06333     GetOpenFile(io, fptr);
    06334     fptr->stdio_file = f;
    06335
    06336     return io;
    06337 }
    06338
    06339 FILE *
    06340 rb_io_stdio_file(rb_io_t *fptr)
    06341 {
    06342     if (!fptr->stdio_file) {
    06343         int oflags = rb_io_fmode_oflags(fptr->mode);
    06344         fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
    06345     }
    06346     return fptr->stdio_file;
    06347 }
    06348
    06349 /*
    06350  *  call-seq:
    06351  *     IO.new(fd [, mode] [, opt])   -> io
    06352  *
    06353  *  Returns a new <code>IO</code> object (a stream) for the given
    06354  *  <code>IO</code> object or integer file descriptor and mode
    06355  *  string. See also <code>IO.sysopen</code> and
    06356  *  <code>IO.for_fd</code>.
    06357  *
    06358  *  === Parameters
    06359  *  fd:: numeric file descriptor
    06360  *  mode:: file mode. a string or an integer
    06361  *  opt:: hash for specifying mode by name.
    06362  *
    06363  *  ==== Mode
    06364  *  When <code>mode</code> is an integer it must be combination of
    06365  *  the modes defined in <code>File::Constants</code>.
    06366  *
    06367  *  When <code>mode</code> is a string it must be in one of the
    06368  *  following forms:
    06369  *  - "fmode",
    06370  *  - "fmode:extern",
    06371  *  - "fmode:extern:intern".
    06372  *  <code>extern</code> is the external encoding name for the IO.
    06373  *  <code>intern</code> is the internal encoding.
    06374  *  <code>fmode</code> must be combination of the directives. See
    06375  *  the description of class +IO+ for a description of the directives.
    06376  *
    06377  *  When the mode of original IO is read only, the mode cannot be changed to
    06378  *  be writable.  Similarly, the mode cannot be changed from write only to
    06379  *  readable.
    06380  *  If such a wrong change is directed, timing where the error actually occurs
    06381  *  is different according to the platform.
    06382  *
    06383  *  ==== Options
    06384  *  <code>opt</code> can have the following keys
    06385  *  :mode ::
    06386  *    same as <code>mode</code> parameter
    06387  *  :external_encoding ::
    06388  *    external encoding for the IO. "-" is a
    06389  *    synonym for the default external encoding.
    06390  *  :internal_encoding ::
    06391  *    internal encoding for the IO.
    06392  *    "-" is a synonym for the default internal encoding.
    06393  *    If the value is nil no conversion occurs.
    06394  *  :encoding ::
    06395  *    specifies external and internal encodings as "extern:intern".
    06396  *  :textmode ::
    06397  *    If the value is truth value, same as "t" in argument <code>mode</code>.
    06398  *  :binmode ::
    06399  *    If the value is truth value, same as "b" in argument <code>mode</code>.
    06400  *  :autoclose ::
    06401  *    If the value is +false+, the _fd_ will be kept open after this
    06402  *    +IO+ instance gets finalized.
    06403  *
    06404  *  Also <code>opt</code> can have same keys in <code>String#encode</code> for
    06405  *  controlling conversion between the external encoding and the internal encoding.
    06406  *
    06407  *  === Example1
    06408  *
    06409  *     fd = IO.sysopen("/dev/tty", "w")
    06410  *     a = IO.new(fd,"w")
    06411  *     $stderr.puts "Hello"
    06412  *     a.puts "World"
    06413  *
    06414  *  <em>produces:</em>
    06415  *
    06416  *     Hello
    06417  *     World
    06418  *
    06419  *  === Example2
    06420  *
    06421  *     require 'fcntl'
    06422  *
    06423  *     fd = STDERR.fcntl(Fcntl::F_DUPFD)
    06424  *     io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
    06425  *     io.puts "Hello, World!"
    06426  *
    06427  *     fd = STDERR.fcntl(Fcntl::F_DUPFD)
    06428  *     io = IO.new(fd, mode: 'w', cr_newline: true, external_encoding: Encoding::UTF_16LE)
    06429  *     io.puts "Hello, World!"
    06430  *
    06431  *  both of above print "Hello, World!" in UTF-16LE to standard error output with
    06432  *  converting EOL generated by <code>puts</code> to CR.
    06433  */
    06434
    06435 static VALUE
    06436 rb_io_initialize(int argc, VALUE *argv, VALUE io)
    06437 {
    06438     VALUE fnum, vmode;
    06439     rb_io_t *fp;
    06440     int fd, fmode, oflags = O_RDONLY;
    06441     convconfig_t convconfig;
    06442     VALUE opt;
    06443 #if defined(HAVE_FCNTL) && defined(F_GETFL)
    06444     int ofmode;
    06445 #else
    06446     struct stat st;
    06447 #endif
    06448
    06449     rb_secure(4);
    06450
    06451     opt = pop_last_hash(&argc, argv);
    06452     rb_scan_args(argc, argv, "11", &fnum, &vmode);
    06453     rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
    06454
    06455     fd = NUM2INT(fnum);
    06456 #if defined(HAVE_FCNTL) && defined(F_GETFL)
    06457     oflags = fcntl(fd, F_GETFL);
    06458     if (oflags == -1) rb_sys_fail(0);
    06459 #else
    06460     if (fstat(fd, &st) == -1) rb_sys_fail(0);
    06461 #endif
    06462     UPDATE_MAXFD(fd);
    06463 #if defined(HAVE_FCNTL) && defined(F_GETFL)
    06464     ofmode = rb_io_oflags_fmode(oflags);
    06465     if (NIL_P(vmode)) {
    06466         fmode = ofmode;
    06467     }
    06468     else if ((~ofmode & fmode) & FMODE_READWRITE) {
    06469         VALUE error = INT2FIX(EINVAL);
    06470         rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
    06471     }
    06472 #endif
    06473     if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
    06474         fmode |= FMODE_PREP;
    06475     }
    06476     MakeOpenFile(io, fp);
    06477     fp->fd = fd;
    06478     fp->mode = fmode;
    06479     fp->encs = convconfig;
    06480     clear_codeconv(fp);
    06481     io_check_tty(fp);
    06482     if (fileno(stdin) == fd)
    06483         fp->stdio_file = stdin;
    06484     else if (fileno(stdout) == fd)
    06485         fp->stdio_file = stdout;
    06486     else if (fileno(stderr) == fd)
    06487         fp->stdio_file = stderr;
    06488
    06489     if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
    06490     return io;
    06491 }
    06492
    06493 /*
    06494  *  call-seq:
    06495  *     File.new(filename, mode="r" [, opt])            -> file
    06496  *     File.new(filename [, mode [, perm]] [, opt])    -> file
    06497  *
    06498  *  Opens the file named by _filename_ according to
    06499  *  _mode_ (default is ``r'') and returns a new
    06500  *  <code>File</code> object.
    06501  *
    06502  *  === Parameters
    06503  *  See the description of class +IO+ for a description of _mode_.
    06504  *  The file mode may optionally be specified as a +Fixnum+
    06505  *  by _or_-ing together the flags (O_RDONLY etc,
    06506  *  again described under +IO+).
    06507  *
    06508  *  Optional permission bits may be given in _perm_.
    06509  *  These mode and permission bits are platform dependent;
    06510  *  on Unix systems, see <code>open(2)</code> for details.
    06511  *
    06512  *  Optional _opt_ parameter is same as in <code.IO.open</code>.
    06513  *
    06514  *  === Examples
    06515  *
    06516  *     f = File.new("testfile", "r")
    06517  *     f = File.new("newfile",  "w+")
    06518  *     f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
    06519  */
    06520
    06521 static VALUE
    06522 rb_file_initialize(int argc, VALUE *argv, VALUE io)
    06523 {
    06524     if (RFILE(io)->fptr) {
    06525         rb_raise(rb_eRuntimeError, "reinitializing File");
    06526     }
    06527     if (0 < argc && argc < 3) {
    06528         VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
    06529
    06530         if (!NIL_P(fd)) {
    06531             argv[0] = fd;
    06532             return rb_io_initialize(argc, argv, io);
    06533         }
    06534     }
    06535     rb_open_file(argc, argv, io);
    06536
    06537     return io;
    06538 }
    06539
    06540 /* :nodoc: */
    06541 static VALUE
    06542 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
    06543 {
    06544     if (rb_block_given_p()) {
    06545         const char *cname = rb_class2name(klass);
    06546
    06547         rb_warn("%s::new() does not take block; use %s::open() instead",
    06548                 cname, cname);
    06549     }
    06550     return rb_class_new_instance(argc, argv, klass);
    06551 }
    06552
    06553
    06554 /*
    06555  *  call-seq:
    06556  *     IO.for_fd(fd, mode [, opt])    -> io
    06557  *
    06558  *  Synonym for <code>IO.new</code>.
    06559  *
    06560  */
    06561
    06562 static VALUE
    06563 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
    06564 {
    06565     VALUE io = rb_obj_alloc(klass);
    06566     rb_io_initialize(argc, argv, io);
    06567     return io;
    06568 }
    06569
    06570 /*
    06571  *  call-seq:
    06572  *     ios.autoclose?   -> true or false
    06573  *
    06574  *  Returns +true+ if the underlying file descriptor of _ios_ will be
    06575  *  closed automatically at its finalization, otherwise +false+.
    06576  */
    06577
    06578 static VALUE
    06579 rb_io_autoclose_p(VALUE io)
    06580 {
    06581     rb_io_t *fptr;
    06582     rb_secure(4);
    06583     GetOpenFile(io, fptr);
    06584     return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
    06585 }
    06586
    06587 /*
    06588  *  call-seq:
    06589  *     io.autoclose = bool    -> true or false
    06590  *
    06591  *  Sets auto-close flag.
    06592  *
    06593  *     f = open("/dev/null")
    06594  *     IO.for_fd(f.fileno)
    06595  *     # ...
    06596  *     f.gets # may cause IOError
    06597  *
    06598  *     f = open("/dev/null")
    06599  *     IO.for_fd(f.fileno).autoclose = true
    06600  *     # ...
    06601  *     f.gets # won't cause IOError
    06602  */
    06603
    06604 static VALUE
    06605 rb_io_set_autoclose(VALUE io, VALUE autoclose)
    06606 {
    06607     rb_io_t *fptr;
    06608     rb_secure(4);
    06609     GetOpenFile(io, fptr);
    06610     if (!RTEST(autoclose))
    06611         fptr->mode |= FMODE_PREP;
    06612     else
    06613         fptr->mode &= ~FMODE_PREP;
    06614     return io;
    06615 }
    06616
    06617 static void
    06618 argf_mark(void *ptr)
    06619 {
    06620     struct argf *p = ptr;
    06621     rb_gc_mark(p->filename);
    06622     rb_gc_mark(p->current_file);
    06623     rb_gc_mark(p->argv);
    06624     rb_gc_mark(p->encs.ecopts);
    06625 }
    06626
    06627 static void
    06628 argf_free(void *ptr)
    06629 {
    06630     struct argf *p = ptr;
    06631     xfree(p->inplace);
    06632     xfree(p);
    06633 }
    06634
    06635 static inline void
    06636 argf_init(struct argf *p, VALUE v)
    06637 {
    06638     p->filename = Qnil;
    06639     p->current_file = Qnil;
    06640     p->lineno = 0;
    06641     p->argv = v;
    06642 }
    06643
    06644 static VALUE
    06645 argf_alloc(VALUE klass)
    06646 {
    06647     struct argf *p;
    06648     VALUE argf = Data_Make_Struct(klass, struct argf, argf_mark, argf_free, p);
    06649
    06650     argf_init(p, Qnil);
    06651     return argf;
    06652 }
    06653
    06654 #undef rb_argv
    06655
    06656 /* :nodoc: */
    06657 static VALUE
    06658 argf_initialize(VALUE argf, VALUE argv)
    06659 {
    06660     memset(&ARGF, 0, sizeof(ARGF));
    06661     argf_init(&ARGF, argv);
    06662
    06663     return argf;
    06664 }
    06665
    06666 /* :nodoc: */
    06667 static VALUE
    06668 argf_initialize_copy(VALUE argf, VALUE orig)
    06669 {
    06670     ARGF = argf_of(orig);
    06671     ARGF.argv = rb_obj_dup(ARGF.argv);
    06672     if (ARGF.inplace) {
    06673         const char *inplace = ARGF.inplace;
    06674         ARGF.inplace = 0;
    06675         ARGF.inplace = ruby_strdup(inplace);
    06676     }
    06677     return argf;
    06678 }
    06679
    06680 /*
    06681  *  call-seq:
    06682  *     ARGF.lineno = number  -> nil
    06683  *
    06684  *  Sets the line number of +ARGF+ as a whole to the given +Integer+.
    06685  *
    06686  *  +ARGF+ sets the line number automatically as you read data, so normally
    06687  *  you will not need to set it explicitly. To access the current line number
    06688  *  use +ARGF.lineno+.
    06689  *
    06690  *  For example:
    06691  *
    06692  *      ARGF.lineno      #=> 0
    06693  *      ARGF.readline    #=> "This is line 1\n"
    06694  *      ARGF.lineno      #=> 1
    06695  *      ARGF.lineno = 0  #=> nil
    06696  *      ARGF.lineno      #=> 0
    06697  */
    06698 static VALUE
    06699 argf_set_lineno(VALUE argf, VALUE val)
    06700 {
    06701     ARGF.lineno = NUM2INT(val);
    06702     ARGF.last_lineno = ARGF.lineno;
    06703     return Qnil;
    06704 }
    06705
    06706 /*
    06707  *  call-seq:
    06708  *     ARGF.lineno -> integer
    06709  *
    06710  *  Returns the current line number of ARGF as a whole. This value
    06711  *  can be set manually with +ARGF.lineno=+.
    06712  *
    06713  *  For example:
    06714  *
    06715  *      ARGF.lineno   #=> 0
    06716  *      ARGF.readline #=> "This is line 1\n"
    06717  *      ARGF.lineno   #=> 1
    06718  */
    06719 static VALUE
    06720 argf_lineno(VALUE argf)
    06721 {
    06722     return INT2FIX(ARGF.lineno);
    06723 }
    06724
    06725 static VALUE
    06726 argf_forward(int argc, VALUE *argv, VALUE argf)
    06727 {
    06728     return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
    06729 }
    06730
    06731 #define next_argv() argf_next_argv(argf)
    06732 #define ARGF_GENERIC_INPUT_P() \
    06733     (ARGF.current_file == rb_stdin && TYPE(ARGF.current_file) != T_FILE)
    06734 #define ARGF_FORWARD(argc, argv) do {\
    06735     if (ARGF_GENERIC_INPUT_P())\
    06736         return argf_forward(argc, argv, argf);\
    06737 } while (0)
    06738 #define NEXT_ARGF_FORWARD(argc, argv) do {\
    06739     if (!next_argv()) return Qnil;\
    06740     ARGF_FORWARD(argc, argv);\
    06741 } while (0)
    06742
    06743 static void
    06744 argf_close(VALUE file)
    06745 {
    06746     rb_funcall3(file, rb_intern("close"), 0, 0);
    06747 }
    06748
    06749 static int
    06750 argf_next_argv(VALUE argf)
    06751 {
    06752     char *fn;
    06753     rb_io_t *fptr;
    06754     int stdout_binmode = 0;
    06755
    06756     if (TYPE(rb_stdout) == T_FILE) {
    06757         GetOpenFile(rb_stdout, fptr);
    06758         if (fptr->mode & FMODE_BINMODE)
    06759             stdout_binmode = 1;
    06760     }
    06761
    06762     if (ARGF.init_p == 0) {
    06763         if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
    06764             ARGF.next_p = 1;
    06765         }
    06766         else {
    06767             ARGF.next_p = -1;
    06768         }
    06769         ARGF.init_p = 1;
    06770     }
    06771
    06772     if (ARGF.next_p == 1) {
    06773         ARGF.next_p = 0;
    06774       retry:
    06775         if (RARRAY_LEN(ARGF.argv) > 0) {
    06776             ARGF.filename = rb_ary_shift(ARGF.argv);
    06777             fn = StringValueCStr(ARGF.filename);
    06778             if (strlen(fn) == 1 && fn[0] == '-') {
    06779                 ARGF.current_file = rb_stdin;
    06780                 if (ARGF.inplace) {
    06781                     rb_warn("Can't do inplace edit for stdio; skipping");
    06782                     goto retry;
    06783                 }
    06784             }
    06785             else {
    06786                 int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0);
    06787
    06788                 if (ARGF.inplace) {
    06789                     struct stat st;
    06790 #ifndef NO_SAFE_RENAME
    06791                     struct stat st2;
    06792 #endif
    06793                     VALUE str;
    06794                     int fw;
    06795
    06796                     if (TYPE(rb_stdout) == T_FILE && rb_stdout != orig_stdout) {
    06797                         rb_io_close(rb_stdout);
    06798                     }
    06799                     fstat(fr, &st);
    06800                     if (*ARGF.inplace) {
    06801                         str = rb_str_new2(fn);
    06802 #ifdef NO_LONG_FNAME
    06803                         ruby_add_suffix(str, ARGF.inplace);
    06804 #else
    06805                         rb_str_cat2(str, ARGF.inplace);
    06806 #endif
    06807 #ifdef NO_SAFE_RENAME
    06808                         (void)close(fr);
    06809                         (void)unlink(RSTRING_PTR(str));
    06810                         (void)rename(fn, RSTRING_PTR(str));
    06811                         fr = rb_sysopen(str, O_RDONLY, 0);
    06812 #else
    06813                         if (rename(fn, RSTRING_PTR(str)) < 0) {
    06814                             rb_warn("Can't rename %s to %s: %s, skipping file",
    06815                                     fn, RSTRING_PTR(str), strerror(errno));
    06816                             close(fr);
    06817                             goto retry;
    06818                         }
    06819 #endif
    06820                     }
    06821                     else {
    06822 #ifdef NO_SAFE_RENAME
    06823                         rb_fatal("Can't do inplace edit without backup");
    06824 #else
    06825                         if (unlink(fn) < 0) {
    06826                             rb_warn("Can't remove %s: %s, skipping file",
    06827                                     fn, strerror(errno));
    06828                             close(fr);
    06829                             goto retry;
    06830                         }
    06831 #endif
    06832                     }
    06833                     fw = rb_sysopen(ARGF.filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
    06834 #ifndef NO_SAFE_RENAME
    06835                     fstat(fw, &st2);
    06836 #ifdef HAVE_FCHMOD
    06837                     fchmod(fw, st.st_mode);
    06838 #else
    06839                     chmod(fn, st.st_mode);
    06840 #endif
    06841                     if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
    06842 #ifdef HAVE_FCHOWN
    06843                         (void)fchown(fw, st.st_uid, st.st_gid);
    06844 #else
    06845                         (void)chown(fn, st.st_uid, st.st_gid);
    06846 #endif
    06847                     }
    06848 #endif
    06849                     rb_stdout = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
    06850                     if (stdout_binmode) rb_io_binmode(rb_stdout);
    06851                 }
    06852                 ARGF.current_file = prep_io(fr, FMODE_READABLE, rb_cFile, fn);
    06853             }
    06854             if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
    06855             if (ARGF.encs.enc) {
    06856                 rb_io_t *fptr;
    06857
    06858                 GetOpenFile(ARGF.current_file, fptr);
    06859                 fptr->encs = ARGF.encs;
    06860                 clear_codeconv(fptr);
    06861             }
    06862         }
    06863         else {
    06864             ARGF.next_p = 1;
    06865             return FALSE;
    06866         }
    06867     }
    06868     else if (ARGF.next_p == -1) {
    06869         ARGF.current_file = rb_stdin;
    06870         ARGF.filename = rb_str_new2("-");
    06871         if (ARGF.inplace) {
    06872             rb_warn("Can't do inplace edit for stdio");
    06873             rb_stdout = orig_stdout;
    06874         }
    06875     }
    06876     return TRUE;
    06877 }
    06878
    06879 static VALUE
    06880 argf_getline(int argc, VALUE *argv, VALUE argf)
    06881 {
    06882     VALUE line;
    06883     int lineno = ARGF.lineno;
    06884
    06885   retry:
    06886     if (!next_argv()) return Qnil;
    06887     if (ARGF_GENERIC_INPUT_P()) {
    06888         line = rb_funcall3(ARGF.current_file, rb_intern("gets"), argc, argv);
    06889     }
    06890     else {
    06891         if (argc == 0 && rb_rs == rb_default_rs) {
    06892             line = rb_io_gets(ARGF.current_file);
    06893         }
    06894         else {
    06895             line = rb_io_getline(argc, argv, ARGF.current_file);
    06896         }
    06897         if (NIL_P(line) && ARGF.next_p != -1) {
    06898             argf_close(ARGF.current_file);
    06899             ARGF.next_p = 1;
    06900             goto retry;
    06901         }
    06902     }
    06903     if (!NIL_P(line)) {
    06904         ARGF.lineno = ++lineno;
    06905         ARGF.last_lineno = ARGF.lineno;
    06906     }
    06907     return line;
    06908 }
    06909
    06910 static VALUE
    06911 argf_lineno_getter(ID id, VALUE *var)
    06912 {
    06913     VALUE argf = *var;
    06914     return INT2FIX(ARGF.last_lineno);
    06915 }
    06916
    06917 static void
    06918 argf_lineno_setter(VALUE val, ID id, VALUE *var)
    06919 {
    06920     VALUE argf = *var;
    06921     int n = NUM2INT(val);
    06922     ARGF.last_lineno = ARGF.lineno = n;
    06923 }
    06924
    06925 static VALUE argf_gets(int, VALUE *, VALUE);
    06926
    06927 /*
    06928  *  call-seq:
    06929  *     gets(sep=$/)    -> string or nil
    06930  *     gets(limit)     -> string or nil
    06931  *     gets(sep,limit) -> string or nil
    06932  *
    06933  *  Returns (and assigns to <code>$_</code>) the next line from the list
    06934  *  of files in +ARGV+ (or <code>$*</code>), or from standard input if
    06935  *  no files are present on the command line. Returns +nil+ at end of
    06936  *  file. The optional argument specifies the record separator. The
    06937  *  separator is included with the contents of each record. A separator
    06938  *  of +nil+ reads the entire contents, and a zero-length separator
    06939  *  reads the input one paragraph at a time, where paragraphs are
    06940  *  divided by two consecutive newlines.  If the first argument is an
    06941  *  integer, or optional second argument is given, the returning string
    06942  *  would not be longer than the given value in bytes.  If multiple
    06943  *  filenames are present in +ARGV+, +gets(nil)+ will read the contents
    06944  *  one file at a time.
    06945  *
    06946  *     ARGV << "testfile"
    06947  *     print while gets
    06948  *
    06949  *  <em>produces:</em>
    06950  *
    06951  *     This is line one
    06952  *     This is line two
    06953  *     This is line three
    06954  *     And so on...
    06955  *
    06956  *  The style of programming using <code>$_</code> as an implicit
    06957  *  parameter is gradually losing favor in the Ruby community.
    06958  */
    06959
    06960 static VALUE
    06961 rb_f_gets(int argc, VALUE *argv, VALUE recv)
    06962 {
    06963     if (recv == argf) {
    06964         return argf_gets(argc, argv, argf);
    06965     }
    06966     return rb_funcall2(argf, rb_intern("gets"), argc, argv);
    06967 }
    06968
    06969 /*
    06970  *  call-seq:
    06971  *     ARGF.gets(sep=$/)     -> string
    06972  *     ARGF.gets(limit)      -> string
    06973  *     ARGF.gets(sep, limit) -> string
    06974  *
    06975  *  Returns the next line from the current file in +ARGF+.
    06976  *
    06977  *  By default lines are assumed to be separated by +$/+; to use a different
    06978  *  character as a separator, supply it as a +String+ for the _sep_ argument.
    06979  *
    06980  *  The optional  _limit_ argument specifies how many characters of each line
    06981  *  to return. By default all characters are returned.
    06982  *
    06983  */
    06984 static VALUE
    06985 argf_gets(int argc, VALUE *argv, VALUE argf)
    06986 {
    06987     VALUE line;
    06988
    06989     line = argf_getline(argc, argv, argf);
    06990     rb_lastline_set(line);
    06991
    06992     return line;
    06993 }
    06994
    06995 VALUE
    06996 rb_gets(void)
    06997 {
    06998     VALUE line;
    06999
    07000     if (rb_rs != rb_default_rs) {
    07001         return rb_f_gets(0, 0, argf);
    07002     }
    07003
    07004   retry:
    07005     if (!next_argv()) return Qnil;
    07006     line = rb_io_gets(ARGF.current_file);
    07007     if (NIL_P(line) && ARGF.next_p != -1) {
    07008         rb_io_close(ARGF.current_file);
    07009         ARGF.next_p = 1;
    07010         goto retry;
    07011     }
    07012     rb_lastline_set(line);
    07013     if (!NIL_P(line)) {
    07014         ARGF.lineno++;
    07015         ARGF.last_lineno = ARGF.lineno;
    07016     }
    07017
    07018     return line;
    07019 }
    07020
    07021 static VALUE argf_readline(int, VALUE *, VALUE);
    07022
    07023 /*
    07024  *  call-seq:
    07025  *     readline(sep=$/)     -> string
    07026  *     readline(limit)      -> string
    07027  *     readline(sep, limit) -> string
    07028  *
    07029  *  Equivalent to <code>Kernel::gets</code>, except
    07030  *  +readline+ raises +EOFError+ at end of file.
    07031  */
    07032
    07033 static VALUE
    07034 rb_f_readline(int argc, VALUE *argv, VALUE recv)
    07035 {
    07036     if (recv == argf) {
    07037         return argf_readline(argc, argv, argf);
    07038     }
    07039     return rb_funcall2(argf, rb_intern("readline"), argc, argv);
    07040 }
    07041
    07042
    07043 /*
    07044  *  call-seq:
    07045  *     ARGF.readline(sep=$/)     -> string
    07046  *     ARGF.readline(limit)      -> string
    07047  *     ARGF.readline(sep, limit) -> string
    07048  *
    07049  *  Returns the next line from the current file in +ARGF+.
    07050  *
    07051  *  By default lines are assumed to be separated by +$/+; to use a different
    07052  *  character as a separator, supply it as a +String+ for the _sep_ argument.
    07053  *
    07054  *  The optional  _limit_ argument specifies how many characters of each line
    07055  *  to return. By default all characters are returned.
    07056  *
    07057  *  An +EOFError+ is raised at the end of the file.
    07058  */
    07059 static VALUE
    07060 argf_readline(int argc, VALUE *argv, VALUE argf)
    07061 {
    07062     VALUE line;
    07063
    07064     if (!next_argv()) rb_eof_error();
    07065     ARGF_FORWARD(argc, argv);
    07066     line = argf_gets(argc, argv, argf);
    07067     if (NIL_P(line)) {
    07068         rb_eof_error();
    07069     }
    07070
    07071     return line;
    07072 }
    07073
    07074 static VALUE argf_readlines(int, VALUE *, VALUE);
    07075
    07076 /*
    07077  *  call-seq:
    07078  *     readlines(sep=$/)    -> array
    07079  *     readlines(limit)     -> array
    07080  *     readlines(sep,limit) -> array
    07081  *
    07082  *  Returns an array containing the lines returned by calling
    07083  *  <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
    07084  */
    07085
    07086 static VALUE
    07087 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
    07088 {
    07089     if (recv == argf) {
    07090         return argf_readlines(argc, argv, argf);
    07091     }
    07092     return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
    07093 }
    07094
    07095 /*
    07096  *  call-seq:
    07097  *     ARGF.readlines(sep=$/)     -> array
    07098  *     ARGF.readlines(limit)      -> array
    07099  *     ARGF.readlines(sep, limit) -> array
    07100  *
    07101  *     ARGF.to_a(sep=$/)     -> array
    07102  *     ARGF.to_a(limit)      -> array
    07103  *     ARGF.to_a(sep, limit) -> array
    07104  *
    07105  *  Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
    07106  *  lines, one line per element. Lines are assumed to be separated by _sep_.
    07107  *
    07108  *     lines = ARGF.readlines
    07109  *     lines[0]                #=> "This is line one\n"
    07110  */
    07111 static VALUE
    07112 argf_readlines(int argc, VALUE *argv, VALUE argf)
    07113 {
    07114     VALUE line, ary;
    07115
    07116     ary = rb_ary_new();
    07117     while (!NIL_P(line = argf_getline(argc, argv, argf))) {
    07118         rb_ary_push(ary, line);
    07119     }
    07120
    07121     return ary;
    07122 }
    07123
    07124 /*
    07125  *  call-seq:
    07126  *     `cmd`    -> string
    07127  *
    07128  *  Returns the standard output of running _cmd_ in a subshell.
    07129  *  The built-in syntax <code>%x{...}</code> uses
    07130  *  this method. Sets <code>$?</code> to the process status.
    07131  *
    07132  *     `date`                   #=> "Wed Apr  9 08:56:30 CDT 2003\n"
    07133  *     `ls testdir`.split[1]    #=> "main.rb"
    07134  *     `echo oops && exit 99`   #=> "oops\n"
    07135  *     $?.exitstatus            #=> 99
    07136  */
    07137
    07138 static VALUE
    07139 rb_f_backquote(VALUE obj, VALUE str)
    07140 {
    07141     volatile VALUE port;
    07142     VALUE result;
    07143     rb_io_t *fptr;
    07144
    07145     SafeStringValue(str);
    07146     port = pipe_open_s(str, "r", FMODE_READABLE, NULL);
    07147     if (NIL_P(port)) return rb_str_new(0,0);
    07148
    07149     GetOpenFile(port, fptr);
    07150     result = read_all(fptr, remain_size(fptr), Qnil);
    07151     rb_io_close(port);
    07152
    07153     return result;
    07154 }
    07155
    07156 #ifdef HAVE_SYS_SELECT_H
    07157 #include <sys/select.h>
    07158 #endif
    07159
    07160 static VALUE
    07161 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
    07162 {
    07163     VALUE res, list;
    07164     rb_fdset_t *rp, *wp, *ep;
    07165     rb_io_t *fptr;
    07166     long i;
    07167     int max = 0, n;
    07168     int interrupt_flag = 0;
    07169     int pending = 0;
    07170     struct timeval timerec;
    07171
    07172     if (!NIL_P(read)) {
    07173         Check_Type(read, T_ARRAY);
    07174         for (i=0; i<RARRAY_LEN(read); i++) {
    07175             GetOpenFile(rb_io_get_io(RARRAY_PTR(read)[i]), fptr);
    07176             rb_fd_set(fptr->fd, &fds[0]);
    07177             if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
    07178                 pending++;
    07179                 rb_fd_set(fptr->fd, &fds[3]);
    07180             }
    07181             if (max < fptr->fd) max = fptr->fd;
    07182         }
    07183         if (pending) {          /* no blocking if there's buffered data */
    07184             timerec.tv_sec = timerec.tv_usec = 0;
    07185             tp = &timerec;
    07186         }
    07187         rp = &fds[0];
    07188     }
    07189     else
    07190         rp = 0;
    07191
    07192     if (!NIL_P(write)) {
    07193         Check_Type(write, T_ARRAY);
    07194         for (i=0; i<RARRAY_LEN(write); i++) {
    07195             VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_PTR(write)[i]));
    07196             GetOpenFile(write_io, fptr);
    07197             rb_fd_set(fptr->fd, &fds[1]);
    07198             if (max < fptr->fd) max = fptr->fd;
    07199         }
    07200         wp = &fds[1];
    07201     }
    07202     else
    07203         wp = 0;
    07204
    07205     if (!NIL_P(except)) {
    07206         Check_Type(except, T_ARRAY);
    07207         for (i=0; i<RARRAY_LEN(except); i++) {
    07208             VALUE io = rb_io_get_io(RARRAY_PTR(except)[i]);
    07209             VALUE write_io = GetWriteIO(io);
    07210             GetOpenFile(io, fptr);
    07211             rb_fd_set(fptr->fd, &fds[2]);
    07212             if (max < fptr->fd) max = fptr->fd;
    07213             if (io != write_io) {
    07214                 GetOpenFile(write_io, fptr);
    07215                 rb_fd_set(fptr->fd, &fds[2]);
    07216                 if (max < fptr->fd) max = fptr->fd;
    07217             }
    07218         }
    07219         ep = &fds[2];
    07220     }
    07221     else {
    07222         ep = 0;
    07223     }
    07224
    07225     max++;
    07226
    07227     n = rb_thread_fd_select(max, rp, wp, ep, tp);
    07228     if (n < 0) {
    07229         rb_sys_fail(0);
    07230     }
    07231     if (!pending && n == 0) return Qnil; /* returns nil on timeout */
    07232
    07233     res = rb_ary_new2(3);
    07234     rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
    07235     rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
    07236     rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
    07237
    07238     if (interrupt_flag == 0) {
    07239         if (rp) {
    07240             list = RARRAY_PTR(res)[0];
    07241             for (i=0; i< RARRAY_LEN(read); i++) {
    07242                 VALUE obj = rb_ary_entry(read, i);
    07243                 VALUE io = rb_io_get_io(obj);
    07244                 GetOpenFile(io, fptr);
    07245                 if (rb_fd_isset(fptr->fd, &fds[0]) ||
    07246                     rb_fd_isset(fptr->fd, &fds[3])) {
    07247                     rb_ary_push(list, obj);
    07248                 }
    07249             }
    07250         }
    07251
    07252         if (wp) {
    07253             list = RARRAY_PTR(res)[1];
    07254             for (i=0; i< RARRAY_LEN(write); i++) {
    07255                 VALUE obj = rb_ary_entry(write, i);
    07256                 VALUE io = rb_io_get_io(obj);
    07257                 VALUE write_io = GetWriteIO(io);
    07258                 GetOpenFile(write_io, fptr);
    07259                 if (rb_fd_isset(fptr->fd, &fds[1])) {
    07260                     rb_ary_push(list, obj);
    07261                 }
    07262             }
    07263         }
    07264
    07265         if (ep) {
    07266             list = RARRAY_PTR(res)[2];
    07267             for (i=0; i< RARRAY_LEN(except); i++) {
    07268                 VALUE obj = rb_ary_entry(except, i);
    07269                 VALUE io = rb_io_get_io(obj);
    07270                 VALUE write_io = GetWriteIO(io);
    07271                 GetOpenFile(io, fptr);
    07272                 if (rb_fd_isset(fptr->fd, &fds[2])) {
    07273                     rb_ary_push(list, obj);
    07274                 }
    07275                 else if (io != write_io) {
    07276                     GetOpenFile(write_io, fptr);
    07277                     if (rb_fd_isset(fptr->fd, &fds[2])) {
    07278                         rb_ary_push(list, obj);
    07279                     }
    07280                 }
    07281             }
    07282         }
    07283     }
    07284
    07285     return res;                 /* returns an empty array on interrupt */
    07286 }
    07287
    07288 struct select_args {
    07289     VALUE read, write, except;
    07290     struct timeval *timeout;
    07291     rb_fdset_t fdsets[4];
    07292 };
    07293
    07294 #ifdef HAVE_RB_FD_INIT
    07295 static VALUE
    07296 select_call(VALUE arg)
    07297 {
    07298     struct select_args *p = (struct select_args *)arg;
    07299
    07300     return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
    07301 }
    07302
    07303 static VALUE
    07304 select_end(VALUE arg)
    07305 {
    07306     struct select_args *p = (struct select_args *)arg;
    07307     int i;
    07308
    07309     for (i = 0; i < numberof(p->fdsets); ++i)
    07310         rb_fd_term(&p->fdsets[i]);
    07311     return Qnil;
    07312 }
    07313 #endif
    07314
    07315 /*
    07316  *  call-seq:
    07317  *     IO.select(read_array
    07318  *               [, write_array
    07319  *               [, error_array
    07320  *               [, timeout]]] )-> array  or  nil
    07321  *
    07322  *  See <code>Kernel#select</code>.
    07323  */
    07324
    07325 static VALUE
    07326 rb_f_select(int argc, VALUE *argv, VALUE obj)
    07327 {
    07328     VALUE timeout;
    07329     struct select_args args;
    07330     struct timeval timerec;
    07331     int i;
    07332
    07333     rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
    07334     if (NIL_P(timeout)) {
    07335         args.timeout = 0;
    07336     }
    07337     else {
    07338         timerec = rb_time_interval(timeout);
    07339         args.timeout = &timerec;
    07340     }
    07341
    07342     for (i = 0; i < numberof(args.fdsets); ++i)
    07343         rb_fd_init(&args.fdsets[i]);
    07344
    07345 #ifdef HAVE_RB_FD_INIT
    07346     return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
    07347 #else
    07348     return select_internal(args.read, args.write, args.except,
    07349                            args.timeout, args.fdsets);
    07350 #endif
    07351
    07352 }
    07353
    07354 static int
    07355 io_cntl(int fd, unsigned long cmd, long narg, int io_p)
    07356 {
    07357     int retval;
    07358
    07359 #ifdef HAVE_FCNTL
    07360 # if defined(__CYGWIN__)
    07361     retval = io_p?ioctl(fd, cmd, (void*)narg):fcntl(fd, cmd, narg);
    07362 # else
    07363     retval = io_p?ioctl(fd, cmd, narg):fcntl(fd, (int)cmd, narg);
    07364 # endif
    07365 # if defined(F_DUPFD)
    07366     if (!io_p && retval != -1 && cmd == F_DUPFD) {
    07367         UPDATE_MAXFD(retval);
    07368     }
    07369 # endif
    07370 #else
    07371     if (!io_p) {
    07372         rb_notimplement();
    07373     }
    07374     retval = ioctl(fd, cmd, narg);
    07375 #endif
    07376     return retval;
    07377 }
    07378
    07379 static VALUE
    07380 rb_io_ctl(VALUE io, VALUE req, VALUE arg, int io_p)
    07381 {
    07382     unsigned long cmd = NUM2ULONG(req);
    07383     rb_io_t *fptr;
    07384     long len = 0;
    07385     long narg = 0;
    07386     int retval;
    07387
    07388     rb_secure(2);
    07389
    07390     if (NIL_P(arg) || arg == Qfalse) {
    07391         narg = 0;
    07392     }
    07393     else if (FIXNUM_P(arg)) {
    07394         narg = FIX2LONG(arg);
    07395     }
    07396     else if (arg == Qtrue) {
    07397         narg = 1;
    07398     }
    07399     else {
    07400         VALUE tmp = rb_check_string_type(arg);
    07401
    07402         if (NIL_P(tmp)) {
    07403             narg = NUM2LONG(arg);
    07404         }
    07405         else {
    07406             arg = tmp;
    07407 #ifdef IOCPARM_MASK
    07408 #ifndef IOCPARM_LEN
    07409 #define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
    07410 #endif
    07411 #endif
    07412 #ifdef IOCPARM_LEN
    07413             len = IOCPARM_LEN(cmd);     /* on BSDish systems we're safe */
    07414 #else
    07415             len = 256;          /* otherwise guess at what's safe */
    07416 #endif
    07417             rb_str_modify(arg);
    07418
    07419             if (len <= RSTRING_LEN(arg)) {
    07420                 len = RSTRING_LEN(arg);
    07421             }
    07422             if (RSTRING_LEN(arg) < len) {
    07423                 rb_str_resize(arg, len+1);
    07424             }
    07425             RSTRING_PTR(arg)[len] = 17; /* a little sanity check here */
    07426             narg = (long)RSTRING_PTR(arg);
    07427         }
    07428     }
    07429     GetOpenFile(io, fptr);
    07430     retval = io_cntl(fptr->fd, cmd, narg, io_p);
    07431     if (retval < 0) rb_sys_fail_path(fptr->pathv);
    07432     if (TYPE(arg) == T_STRING && RSTRING_PTR(arg)[len] != 17) {
    07433         rb_raise(rb_eArgError, "return value overflowed string");
    07434     }
    07435
    07436     if (!io_p && cmd == F_SETFL) {
    07437         if (narg & O_NONBLOCK) {
    07438             fptr->mode |= FMODE_WSPLIT_INITIALIZED;
    07439             fptr->mode &= ~FMODE_WSPLIT;
    07440         }
    07441         else {
    07442             fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
    07443         }
    07444     }
    07445
    07446     return INT2NUM(retval);
    07447 }
    07448
    07449
    07450 /*
    07451  *  call-seq:
    07452  *     ios.ioctl(integer_cmd, arg)    -> integer
    07453  *
    07454  *  Provides a mechanism for issuing low-level commands to control or
    07455  *  query I/O devices. Arguments and results are platform dependent. If
    07456  *  <i>arg</i> is a number, its value is passed directly. If it is a
    07457  *  string, it is interpreted as a binary sequence of bytes. On Unix
    07458  *  platforms, see <code>ioctl(2)</code> for details. Not implemented on
    07459  *  all platforms.
    07460  */
    07461
    07462 static VALUE
    07463 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
    07464 {
    07465     VALUE req, arg;
    07466
    07467     rb_scan_args(argc, argv, "11", &req, &arg);
    07468     return rb_io_ctl(io, req, arg, 1);
    07469 }
    07470
    07471 #ifdef HAVE_FCNTL
    07472 /*
    07473  *  call-seq:
    07474  *     ios.fcntl(integer_cmd, arg)    -> integer
    07475  *
    07476  *  Provides a mechanism for issuing low-level commands to control or
    07477  *  query file-oriented I/O streams. Arguments and results are platform
    07478  *  dependent. If <i>arg</i> is a number, its value is passed
    07479  *  directly. If it is a string, it is interpreted as a binary sequence
    07480  *  of bytes (<code>Array#pack</code> might be a useful way to build this
    07481  *  string). On Unix platforms, see <code>fcntl(2)</code> for details.
    07482  *  Not implemented on all platforms.
    07483  */
    07484
    07485 static VALUE
    07486 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
    07487 {
    07488     VALUE req, arg;
    07489
    07490     rb_scan_args(argc, argv, "11", &req, &arg);
    07491     return rb_io_ctl(io, req, arg, 0);
    07492 }
    07493 #else
    07494 #define rb_io_fcntl rb_f_notimplement
    07495 #endif
    07496
    07497 #if defined(HAVE_SYSCALL) && SIZEOF_LONG == SIZEOF_INT
    07498 /*
    07499  *  call-seq:
    07500  *     syscall(fixnum [, args...])   -> integer
    07501  *
    07502  *  Calls the operating system function identified by _fixnum_,
    07503  *  passing in the arguments, which must be either +String+
    07504  *  objects, or +Integer+ objects that ultimately fit within
    07505  *  a native +long+. Up to nine parameters may be passed (14
    07506  *  on the Atari-ST). The function identified by _fixnum_ is system
    07507  *  dependent. On some Unix systems, the numbers may be obtained from a
    07508  *  header file called <code>syscall.h</code>.
    07509  *
    07510  *     syscall 4, 1, "hello\n", 6   # '4' is write(2) on our box
    07511  *
    07512  *  <em>produces:</em>
    07513  *
    07514  *     hello
    07515  */
    07516
    07517 static VALUE
    07518 rb_f_syscall(int argc, VALUE *argv)
    07519 {
    07520 #ifdef atarist
    07521     unsigned long arg[14]; /* yes, we really need that many ! */
    07522 #else
    07523     unsigned long arg[8];
    07524 #endif
    07525     int retval = -1;
    07526     int i = 1;
    07527     int items = argc - 1;
    07528
    07529     /* This probably won't work on machines where sizeof(long) != sizeof(int)
    07530      * or where sizeof(long) != sizeof(char*).  But such machines will
    07531      * not likely have syscall implemented either, so who cares?
    07532      */
    07533
    07534     rb_secure(2);
    07535     if (argc == 0)
    07536         rb_raise(rb_eArgError, "too few arguments for syscall");
    07537     if (argc > numberof(arg))
    07538         rb_raise(rb_eArgError, "too many arguments for syscall");
    07539     arg[0] = NUM2LONG(argv[0]); argv++;
    07540     while (items--) {
    07541         VALUE v = rb_check_string_type(*argv);
    07542
    07543         if (!NIL_P(v)) {
    07544             StringValue(v);
    07545             rb_str_modify(v);
    07546             arg[i] = (unsigned long)StringValueCStr(v);
    07547         }
    07548         else {
    07549             arg[i] = (unsigned long)NUM2LONG(*argv);
    07550         }
    07551         argv++;
    07552         i++;
    07553     }
    07554
    07555     switch (argc) {
    07556       case 1:
    07557         retval = syscall(arg[0]);
    07558         break;
    07559       case 2:
    07560         retval = syscall(arg[0],arg[1]);
    07561         break;
    07562       case 3:
    07563         retval = syscall(arg[0],arg[1],arg[2]);
    07564         break;
    07565       case 4:
    07566         retval = syscall(arg[0],arg[1],arg[2],arg[3]);
    07567         break;
    07568       case 5:
    07569         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
    07570         break;
    07571       case 6:
    07572         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
    07573         break;
    07574       case 7:
    07575         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
    07576         break;
    07577       case 8:
    07578         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
    07579           arg[7]);
    07580         break;
    07581 #ifdef atarist
    07582       case 9:
    07583         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
    07584           arg[7], arg[8]);
    07585         break;
    07586       case 10:
    07587         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
    07588           arg[7], arg[8], arg[9]);
    07589         break;
    07590       case 11:
    07591         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
    07592           arg[7], arg[8], arg[9], arg[10]);
    07593         break;
    07594       case 12:
    07595         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
    07596           arg[7], arg[8], arg[9], arg[10], arg[11]);
    07597         break;
    07598       case 13:
    07599         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
    07600           arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
    07601         break;
    07602       case 14:
    07603         retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
    07604           arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13]);
    07605         break;
    07606 #endif /* atarist */
    07607     }
    07608
    07609     if (retval < 0) rb_sys_fail(0);
    07610     return INT2NUM(retval);
    07611 }
    07612 #else
    07613 #define rb_f_syscall rb_f_notimplement
    07614 #endif
    07615
    07616 static VALUE
    07617 io_new_instance(VALUE args)
    07618 {
    07619     return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
    07620 }
    07621
    07622 static void
    07623 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
    07624 {
    07625     rb_encoding *enc, *enc2;
    07626     int ecflags;
    07627     VALUE ecopts, tmp;
    07628
    07629     if (!NIL_P(v2)) {
    07630         enc2 = rb_to_encoding(v1);
    07631         tmp = rb_check_string_type(v2);
    07632         if (!NIL_P(tmp)) {
    07633             if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
    07634                 /* Special case - "-" => no transcoding */
    07635                 enc = enc2;
    07636                 enc2 = NULL;
    07637             }
    07638             else
    07639                 enc = rb_to_encoding(v2);
    07640             if (enc == enc2) {
    07641                 /* Special case - "-" => no transcoding */
    07642                 enc2 = NULL;
    07643             }
    07644         }
    07645         else
    07646             enc = rb_to_encoding(v2);
    07647         ecflags = rb_econv_prepare_opts(opt, &ecopts);
    07648     }
    07649     else {
    07650         if (NIL_P(v1)) {
    07651             /* Set to default encodings */
    07652             rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2);
    07653             ecflags = 0;
    07654             ecopts = Qnil;
    07655         }
    07656         else {
    07657             tmp = rb_check_string_type(v1);
    07658             if (!NIL_P(tmp) && rb_enc_asciicompat(rb_enc_get(tmp))) {
    07659                 parse_mode_enc(RSTRING_PTR(tmp), &enc, &enc2, NULL);
    07660                 ecflags = rb_econv_prepare_opts(opt, &ecopts);
    07661             }
    07662             else {
    07663                 rb_io_ext_int_to_encs(rb_to_encoding(v1), NULL, &enc, &enc2);
    07664                 ecflags = 0;
    07665                 ecopts = Qnil;
    07666             }
    07667         }
    07668     }
    07669     validate_enc_binmode(fptr->mode, enc, enc2);
    07670     fptr->encs.enc = enc;
    07671     fptr->encs.enc2 = enc2;
    07672     fptr->encs.ecflags = ecflags;
    07673     fptr->encs.ecopts = ecopts;
    07674     clear_codeconv(fptr);
    07675
    07676 }
    07677
    07678 static VALUE
    07679 pipe_pair_close(VALUE rw)
    07680 {
    07681     VALUE *rwp = (VALUE *)rw;
    07682     return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
    07683 }
    07684
    07685 /*
    07686  *  call-seq:
    07687  *     IO.pipe                             ->  [read_io, write_io]
    07688  *     IO.pipe(ext_enc)                    ->  [read_io, write_io]
    07689  *     IO.pipe("ext_enc:int_enc" [, opt])  ->  [read_io, write_io]
    07690  *     IO.pipe(ext_enc, int_enc [, opt])   ->  [read_io, write_io]
    07691  *
    07692  *     IO.pipe(...) {|read_io, write_io| ... }
    07693  *
    07694  *  Creates a pair of pipe endpoints (connected to each other) and
    07695  *  returns them as a two-element array of <code>IO</code> objects:
    07696  *  <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
    07697  *
    07698  *  If a block is given, the block is called and
    07699  *  returns the value of the block.
    07700  *  <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
    07701  *  If read_io and write_io are not closed when the block exits, they are closed.
    07702  *  i.e. closing read_io and/or write_io doesn't cause an error.
    07703  *
    07704  *  Not available on all platforms.
    07705  *
    07706  *  If an encoding (encoding name or encoding object) is specified as an optional argument,
    07707  *  read string from pipe is tagged with the encoding specified.
    07708  *  If the argument is a colon separated two encoding names "A:B",
    07709  *  the read string is converted from encoding A (external encoding)
    07710  *  to encoding B (internal encoding), then tagged with B.
    07711  *  If two optional arguments are specified, those must be
    07712  *  encoding objects or encoding names,
    07713  *  and the first one is the external encoding,
    07714  *  and the second one is the internal encoding.
    07715  *  If the external encoding and the internal encoding is specified,
    07716  *  optional hash argument specify the conversion option.
    07717  *
    07718  *  In the example below, the two processes close the ends of the pipe
    07719  *  that they are not using. This is not just a cosmetic nicety. The
    07720  *  read end of a pipe will not generate an end of file condition if
    07721  *  there are any writers with the pipe still open. In the case of the
    07722  *  parent process, the <code>rd.read</code> will never return if it
    07723  *  does not first issue a <code>wr.close</code>.
    07724  *
    07725  *     rd, wr = IO.pipe
    07726  *
    07727  *     if fork
    07728  *       wr.close
    07729  *       puts "Parent got: <#{rd.read}>"
    07730  *       rd.close
    07731  *       Process.wait
    07732  *     else
    07733  *       rd.close
    07734  *       puts "Sending message to parent"
    07735  *       wr.write "Hi Dad"
    07736  *       wr.close
    07737  *     end
    07738  *
    07739  *  <em>produces:</em>
    07740  *
    07741  *     Sending message to parent
    07742  *     Parent got: <Hi Dad>
    07743  */
    07744
    07745 static VALUE
    07746 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
    07747 {
    07748     int pipes[2], state;
    07749     VALUE r, w, args[3], v1, v2;
    07750     VALUE opt;
    07751     rb_io_t *fptr, *fptr2;
    07752     int fmode = 0;
    07753     VALUE ret;
    07754
    07755     opt = pop_last_hash(&argc, argv);
    07756     rb_scan_args(argc, argv, "02", &v1, &v2);
    07757     if (rb_pipe(pipes) == -1)
    07758         rb_sys_fail(0);
    07759
    07760     args[0] = klass;
    07761     args[1] = INT2NUM(pipes[0]);
    07762     args[2] = INT2FIX(O_RDONLY);
    07763     r = rb_protect(io_new_instance, (VALUE)args, &state);
    07764     if (state) {
    07765         close(pipes[0]);
    07766         close(pipes[1]);
    07767         rb_jump_tag(state);
    07768     }
    07769     GetOpenFile(r, fptr);
    07770     io_encoding_set(fptr, v1, v2, opt);
    07771     args[1] = INT2NUM(pipes[1]);
    07772     args[2] = INT2FIX(O_WRONLY);
    07773     w = rb_protect(io_new_instance, (VALUE)args, &state);
    07774     if (state) {
    07775         close(pipes[1]);
    07776         if (!NIL_P(r)) rb_io_close(r);
    07777         rb_jump_tag(state);
    07778     }
    07779     GetOpenFile(w, fptr2);
    07780     rb_io_synchronized(fptr2);
    07781
    07782     extract_binmode(opt, &fmode);
    07783     fptr->mode |= fmode;
    07784     fptr2->mode |= fmode;
    07785
    07786     ret = rb_assoc_new(r, w);
    07787     if (rb_block_given_p()) {
    07788         VALUE rw[2];
    07789         rw[0] = r;
    07790         rw[1] = w;
    07791         return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
    07792     }
    07793     return ret;
    07794 }
    07795
    07796 struct foreach_arg {
    07797     int argc;
    07798     VALUE *argv;
    07799     VALUE io;
    07800 };
    07801
    07802 static void
    07803 open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
    07804 {
    07805     VALUE opt, v;
    07806
    07807     FilePathValue(argv[0]);
    07808     arg->io = 0;
    07809     arg->argc = argc - 1;
    07810     arg->argv = argv + 1;
    07811     if (argc == 1) {
    07812       no_key:
    07813         arg->io = rb_io_open(argv[0], INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
    07814         return;
    07815     }
    07816     opt = pop_last_hash(&arg->argc, arg->argv);
    07817     if (NIL_P(opt)) goto no_key;
    07818
    07819     v = rb_hash_aref(opt, sym_open_args);
    07820     if (!NIL_P(v)) {
    07821         VALUE args;
    07822         long n;
    07823
    07824         v = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
    07825         n = RARRAY_LEN(v) + 1;
    07826 #if SIZEOF_LONG > SIZEOF_INT
    07827         if (n > INT_MAX) {
    07828             rb_raise(rb_eArgError, "too many arguments");
    07829         }
    07830 #endif
    07831         args = rb_ary_tmp_new(n);
    07832         rb_ary_push(args, argv[0]);
    07833         rb_ary_concat(args, v);
    07834         arg->io = rb_io_open_with_args((int)n, RARRAY_PTR(args));
    07835         rb_ary_clear(args);     /* prevent from GC */
    07836         return;
    07837     }
    07838     arg->io = rb_io_open(argv[0], Qnil, Qnil, opt);
    07839 }
    07840
    07841 static VALUE
    07842 io_s_foreach(struct foreach_arg *arg)
    07843 {
    07844     VALUE str;
    07845
    07846     while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
    07847         rb_yield(str);
    07848     }
    07849     return Qnil;
    07850 }
    07851
    07852 /*
    07853  *  call-seq:
    07854  *     IO.foreach(name, sep=$/ [, open_args]) {|line| block }     -> nil
    07855  *     IO.foreach(name, limit [, open_args]) {|line| block }      -> nil
    07856  *     IO.foreach(name, sep, limit [, open_args]) {|line| block } -> nil
    07857  *     IO.foreach(...)                                            -> an_enumerator
    07858  *
    07859  *  Executes the block for every line in the named I/O port, where lines
    07860  *  are separated by <em>sep</em>.
    07861  *
    07862  *  If no block is given, an enumerator is returned instead.
    07863  *
    07864  *     IO.foreach("testfile") {|x| print "GOT ", x }
    07865  *
    07866  *  <em>produces:</em>
    07867  *
    07868  *     GOT This is line one
    07869  *     GOT This is line two
    07870  *     GOT This is line three
    07871  *     GOT And so on...
    07872  *
    07873  *  If the last argument is a hash, it's the keyword argument to open.
    07874  *  See <code>IO.read</code> for detail.
    07875  *
    07876  */
    07877
    07878 static VALUE
    07879 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
    07880 {
    07881     struct foreach_arg arg;
    07882
    07883     rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
    07884     RETURN_ENUMERATOR(self, argc, argv);
    07885     open_key_args(argc, argv, &arg);
    07886     if (NIL_P(arg.io)) return Qnil;
    07887     return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
    07888 }
    07889
    07890 static VALUE
    07891 io_s_readlines(struct foreach_arg *arg)
    07892 {
    07893     return rb_io_readlines(arg->argc, arg->argv, arg->io);
    07894 }
    07895
    07896 /*
    07897  *  call-seq:
    07898  *     IO.readlines(name, sep=$/ [, open_args])     -> array
    07899  *     IO.readlines(name, limit [, open_args])      -> array
    07900  *     IO.readlines(name, sep, limit [, open_args]) -> array
    07901  *
    07902  *  Reads the entire file specified by <i>name</i> as individual
    07903  *  lines, and returns those lines in an array. Lines are separated by
    07904  *  <i>sep</i>.
    07905  *
    07906  *     a = IO.readlines("testfile")
    07907  *     a[0]   #=> "This is line one\n"
    07908  *
    07909  *  If the last argument is a hash, it's the keyword argument to open.
    07910  *  See <code>IO.read</code> for detail.
    07911  *
    07912  */
    07913
    07914 static VALUE
    07915 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
    07916 {
    07917     struct foreach_arg arg;
    07918
    07919     rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
    07920     open_key_args(argc, argv, &arg);
    07921     if (NIL_P(arg.io)) return Qnil;
    07922     return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
    07923 }
    07924
    07925 static VALUE
    07926 io_s_read(struct foreach_arg *arg)
    07927 {
    07928     return io_read(arg->argc, arg->argv, arg->io);
    07929 }
    07930
    07931 struct seek_arg {
    07932     VALUE io;
    07933     VALUE offset;
    07934     int mode;
    07935 };
    07936
    07937 static VALUE
    07938 seek_before_access(VALUE argp)
    07939 {
    07940     struct seek_arg *arg = (struct seek_arg *)argp;
    07941     rb_io_binmode(arg->io);
    07942     return rb_io_seek(arg->io, arg->offset, arg->mode);
    07943 }
    07944
    07945 /*
    07946  *  call-seq:
    07947  *     IO.read(name, [length [, offset]] )   -> string
    07948  *     IO.read(name, [length [, offset]], open_args)   -> string
    07949  *
    07950  *  Opens the file, optionally seeks to the given <i>offset</i>, then returns
    07951  *  <i>length</i> bytes (defaulting to the rest of the file).
    07952  *  <code>read</code> ensures the file is closed before returning.
    07953  *
    07954  *  If the last argument is a hash, it specifies option for internal
    07955  *  open().  The key would be the following.  open_args: is exclusive
    07956  *  to others.
    07957  *
    07958  *   encoding: string or encoding
    07959  *
    07960  *    specifies encoding of the read string.  encoding will be ignored
    07961  *    if length is specified.
    07962  *
    07963  *   mode: string
    07964  *
    07965  *    specifies mode argument for open().  it should start with "r"
    07966  *    otherwise it would cause error.
    07967  *
    07968  *   open_args: array of strings
    07969  *
    07970  *    specifies arguments for open() as an array.
    07971  *
    07972  *     IO.read("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
    07973  *     IO.read("testfile", 20)       #=> "This is line one\nThi"
    07974  *     IO.read("testfile", 20, 10)   #=> "ne one\nThis is line "
    07975  */
    07976
    07977 static VALUE
    07978 rb_io_s_read(int argc, VALUE *argv, VALUE io)
    07979 {
    07980     VALUE offset;
    07981     struct foreach_arg arg;
    07982
    07983     rb_scan_args(argc, argv, "13", NULL, NULL, &offset, NULL);
    07984     open_key_args(argc, argv, &arg);
    07985     if (NIL_P(arg.io)) return Qnil;
    07986     if (!NIL_P(offset)) {
    07987         struct seek_arg sarg;
    07988         int state = 0;
    07989         sarg.io = arg.io;
    07990         sarg.offset = offset;
    07991         sarg.mode = SEEK_SET;
    07992         rb_protect(seek_before_access, (VALUE)&sarg, &state);
    07993         if (state) {
    07994             rb_io_close(arg.io);
    07995             rb_jump_tag(state);
    07996         }
    07997         if (arg.argc == 2) arg.argc = 1;
    07998     }
    07999     return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
    08000 }
    08001
    08002 /*
    08003  *  call-seq:
    08004  *     IO.binread(name, [length [, offset]] )   -> string
    08005  *
    08006  *  Opens the file, optionally seeks to the given <i>offset</i>, then returns
    08007  *  <i>length</i> bytes (defaulting to the rest of the file).
    08008  *  <code>binread</code> ensures the file is closed before returning.
    08009  *  The open mode would be "rb:ASCII-8BIT".
    08010  *
    08011  *     IO.binread("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
    08012  *     IO.binread("testfile", 20)       #=> "This is line one\nThi"
    08013  *     IO.binread("testfile", 20, 10)   #=> "ne one\nThis is line "
    08014  */
    08015
    08016 static VALUE
    08017 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
    08018 {
    08019     VALUE offset;
    08020     struct foreach_arg arg;
    08021
    08022     rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
    08023     FilePathValue(argv[0]);
    08024     arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
    08025     if (NIL_P(arg.io)) return Qnil;
    08026     arg.argv = argv+1;
    08027     arg.argc = (argc > 1) ? 1 : 0;
    08028     if (!NIL_P(offset)) {
    08029         rb_io_seek(arg.io, offset, SEEK_SET);
    08030     }
    08031     return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
    08032 }
    08033
    08034 struct copy_stream_struct {
    08035     VALUE src;
    08036     VALUE dst;
    08037     off_t copy_length; /* (off_t)-1 if not specified */
    08038     off_t src_offset; /* (off_t)-1 if not specified */
    08039
    08040     int src_fd;
    08041     int dst_fd;
    08042     int close_src;
    08043     int close_dst;
    08044     off_t total;
    08045     const char *syserr;
    08046     int error_no;
    08047     const char *notimp;
    08048     rb_fdset_t fds;
    08049     VALUE th;
    08050 };
    08051
    08052 static int
    08053 maygvl_copy_stream_wait_read(struct copy_stream_struct *stp)
    08054 {
    08055     int ret;
    08056     rb_fd_zero(&stp->fds);
    08057     rb_fd_set(stp->src_fd, &stp->fds);
    08058     ret = rb_fd_select(rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
    08059     if (ret == -1) {
    08060         stp->syserr = "select";
    08061         stp->error_no = errno;
    08062         return -1;
    08063     }
    08064     return 0;
    08065 }
    08066
    08067 static int
    08068 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
    08069 {
    08070     int ret;
    08071     rb_fd_zero(&stp->fds);
    08072     rb_fd_set(stp->dst_fd, &stp->fds);
    08073     ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
    08074     if (ret == -1) {
    08075         stp->syserr = "select";
    08076         stp->error_no = errno;
    08077         return -1;
    08078     }
    08079     return 0;
    08080 }
    08081
    08082 #ifdef HAVE_SENDFILE
    08083
    08084 #ifdef __linux__
    08085 #define USE_SENDFILE
    08086
    08087 #ifdef HAVE_SYS_SENDFILE_H
    08088 #include <sys/sendfile.h>
    08089 #endif
    08090
    08091 static ssize_t
    08092 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
    08093 {
    08094 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
    08095     /* we are limited by the 32-bit ssize_t return value on 32-bit */
    08096     if (count > (off_t)SSIZE_MAX)
    08097         count = SSIZE_MAX;
    08098 #endif
    08099     return sendfile(out_fd, in_fd, offset, (size_t)count);
    08100 }
    08101
    08102 #endif
    08103
    08104 #endif
    08105
    08106 #ifdef USE_SENDFILE
    08107 static int
    08108 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
    08109 {
    08110     struct stat src_stat, dst_stat;
    08111     ssize_t ss;
    08112     int ret;
    08113
    08114     off_t copy_length;
    08115     off_t src_offset;
    08116     int use_pread;
    08117
    08118     ret = fstat(stp->src_fd, &src_stat);
    08119     if (ret == -1) {
    08120         stp->syserr = "fstat";
    08121         stp->error_no = errno;
    08122         return -1;
    08123     }
    08124     if (!S_ISREG(src_stat.st_mode))
    08125         return 0;
    08126
    08127     ret = fstat(stp->dst_fd, &dst_stat);
    08128     if (ret == -1) {
    08129         stp->syserr = "fstat";
    08130         stp->error_no = errno;
    08131         return -1;
    08132     }
    08133     if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
    08134         return 0;
    08135
    08136     src_offset = stp->src_offset;
    08137     use_pread = src_offset != (off_t)-1;
    08138
    08139     copy_length = stp->copy_length;
    08140     if (copy_length == (off_t)-1) {
    08141         if (use_pread)
    08142             copy_length = src_stat.st_size - src_offset;
    08143         else {
    08144             off_t cur;
    08145             errno = 0;
    08146             cur = lseek(stp->src_fd, 0, SEEK_CUR);
    08147             if (cur == (off_t)-1 && errno) {
    08148                 stp->syserr = "lseek";
    08149                 stp->error_no = errno;
    08150                 return -1;
    08151             }
    08152             copy_length = src_stat.st_size - cur;
    08153         }
    08154     }
    08155
    08156   retry_sendfile:
    08157     if (use_pread) {
    08158         ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, copy_length);
    08159     }
    08160     else {
    08161         ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, copy_length);
    08162     }
    08163     if (0 < ss) {
    08164         stp->total += ss;
    08165         copy_length -= ss;
    08166         if (0 < copy_length) {
    08167             ss = -1;
    08168             errno = EAGAIN;
    08169         }
    08170     }
    08171     if (ss == -1) {
    08172         switch (errno) {
    08173           case EINVAL:
    08174 #ifdef ENOSYS
    08175           case ENOSYS:
    08176 #endif
    08177             return 0;
    08178           case EAGAIN:
    08179 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
    08180           case EWOULDBLOCK:
    08181 #endif
    08182             if (nogvl_copy_stream_wait_write(stp) == -1)
    08183                 return -1;
    08184             if (rb_thread_interrupted(stp->th))
    08185                 return -1;
    08186             goto retry_sendfile;
    08187         }
    08188         stp->syserr = "sendfile";
    08189         stp->error_no = errno;
    08190         return -1;
    08191     }
    08192     return 1;
    08193 }
    08194 #endif
    08195
    08196 static ssize_t
    08197 maygvl_copy_stream_read(struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
    08198 {
    08199     ssize_t ss;
    08200   retry_read:
    08201     if (offset == (off_t)-1)
    08202         ss = read(stp->src_fd, buf, len);
    08203     else {
    08204 #ifdef HAVE_PREAD
    08205         ss = pread(stp->src_fd, buf, len, offset);
    08206 #else
    08207         stp->notimp = "pread";
    08208         return -1;
    08209 #endif
    08210     }
    08211     if (ss == 0) {
    08212         return 0;
    08213     }
    08214     if (ss == -1) {
    08215         switch (errno) {
    08216           case EAGAIN:
    08217 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
    08218           case EWOULDBLOCK:
    08219 #endif
    08220             if (maygvl_copy_stream_wait_read(stp) == -1)
    08221                 return -1;
    08222             goto retry_read;
    08223 #ifdef ENOSYS
    08224           case ENOSYS:
    08225 #endif
    08226             stp->notimp = "pread";
    08227             return -1;
    08228         }
    08229         stp->syserr = offset == (off_t)-1 ?  "read" : "pread";
    08230         stp->error_no = errno;
    08231         return -1;
    08232     }
    08233     return ss;
    08234 }
    08235
    08236 static int
    08237 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
    08238 {
    08239     ssize_t ss;
    08240     int off = 0;
    08241     while (len) {
    08242         ss = write(stp->dst_fd, buf+off, len);
    08243         if (ss == -1) {
    08244             if (errno == EAGAIN || errno == EWOULDBLOCK) {
    08245                 if (nogvl_copy_stream_wait_write(stp) == -1)
    08246                     return -1;
    08247                 continue;
    08248             }
    08249             stp->syserr = "write";
    08250             stp->error_no = errno;
    08251             return -1;
    08252         }
    08253         off += (int)ss;
    08254         len -= (int)ss;
    08255         stp->total += ss;
    08256     }
    08257     return 0;
    08258 }
    08259
    08260 static void
    08261 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
    08262 {
    08263     char buf[1024*16];
    08264     size_t len;
    08265     ssize_t ss;
    08266     int ret;
    08267     off_t copy_length;
    08268     int use_eof;
    08269     off_t src_offset;
    08270     int use_pread;
    08271
    08272     copy_length = stp->copy_length;
    08273     use_eof = copy_length == (off_t)-1;
    08274     src_offset = stp->src_offset;
    08275     use_pread = src_offset != (off_t)-1;
    08276
    08277     if (use_pread && stp->close_src) {
    08278         off_t r;
    08279         errno = 0;
    08280         r = lseek(stp->src_fd, src_offset, SEEK_SET);
    08281         if (r == (off_t)-1 && errno) {
    08282             stp->syserr = "lseek";
    08283             stp->error_no = errno;
    08284             return;
    08285         }
    08286         src_offset = (off_t)-1;
    08287         use_pread = 0;
    08288     }
    08289
    08290     while (use_eof || 0 < copy_length) {
    08291         if (!use_eof && copy_length < (off_t)sizeof(buf)) {
    08292             len = (size_t)copy_length;
    08293         }
    08294         else {
    08295             len = sizeof(buf);
    08296         }
    08297         if (use_pread) {
    08298             ss = maygvl_copy_stream_read(stp, buf, len, src_offset);
    08299             if (0 < ss)
    08300                 src_offset += ss;
    08301         }
    08302         else {
    08303             ss = maygvl_copy_stream_read(stp, buf, len, (off_t)-1);
    08304         }
    08305         if (ss <= 0) /* EOF or error */
    08306             return;
    08307
    08308         ret = nogvl_copy_stream_write(stp, buf, ss);
    08309         if (ret < 0)
    08310             return;
    08311
    08312         if (!use_eof)
    08313             copy_length -= ss;
    08314
    08315         if (rb_thread_interrupted(stp->th))
    08316             return;
    08317     }
    08318 }
    08319
    08320 static VALUE
    08321 nogvl_copy_stream_func(void *arg)
    08322 {
    08323     struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
    08324 #ifdef USE_SENDFILE
    08325     int ret;
    08326 #endif
    08327
    08328 #ifdef USE_SENDFILE
    08329     ret = nogvl_copy_stream_sendfile(stp);
    08330     if (ret != 0)
    08331         goto finish; /* error or success */
    08332 #endif
    08333
    08334     nogvl_copy_stream_read_write(stp);
    08335
    08336 #ifdef USE_SENDFILE
    08337   finish:
    08338 #endif
    08339     return Qnil;
    08340 }
    08341
    08342 static VALUE
    08343 copy_stream_fallback_body(VALUE arg)
    08344 {
    08345     struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
    08346     const int buflen = 16*1024;
    08347     VALUE n;
    08348     VALUE buf = rb_str_buf_new(buflen);
    08349     off_t rest = stp->copy_length;
    08350     off_t off = stp->src_offset;
    08351     ID read_method = id_readpartial;
    08352
    08353     if (stp->src_fd == -1) {
    08354         if (!rb_respond_to(stp->src, read_method)) {
    08355             read_method = id_read;
    08356         }
    08357     }
    08358
    08359     while (1) {
    08360         long numwrote;
    08361         long l;
    08362         if (stp->copy_length == (off_t)-1) {
    08363             l = buflen;
    08364         }
    08365         else {
    08366             if (rest == 0)
    08367                 break;
    08368             l = buflen < rest ? buflen : (long)rest;
    08369         }
    08370         if (stp->src_fd == -1) {
    08371             rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
    08372         }
    08373         else {
    08374             ssize_t ss;
    08375             rb_thread_wait_fd(stp->src_fd);
    08376             rb_str_resize(buf, buflen);
    08377             ss = maygvl_copy_stream_read(stp, RSTRING_PTR(buf), l, off);
    08378             if (ss == -1)
    08379                 return Qnil;
    08380             if (ss == 0)
    08381                 rb_eof_error();
    08382             rb_str_resize(buf, ss);
    08383             if (off != (off_t)-1)
    08384                 off += ss;
    08385         }
    08386         n = rb_io_write(stp->dst, buf);
    08387         numwrote = NUM2LONG(n);
    08388         stp->total += numwrote;
    08389         rest -= numwrote;
    08390         if (read_method == id_read && RSTRING_LEN(buf) == 0) {
    08391             break;
    08392         }
    08393     }
    08394
    08395     return Qnil;
    08396 }
    08397
    08398 static VALUE
    08399 copy_stream_fallback(struct copy_stream_struct *stp)
    08400 {
    08401     if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
    08402         rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
    08403     }
    08404     rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
    08405                (VALUE (*) (ANYARGS))0, (VALUE)0,
    08406                rb_eEOFError, (VALUE)0);
    08407     return Qnil;
    08408 }
    08409
    08410 static VALUE
    08411 copy_stream_body(VALUE arg)
    08412 {
    08413     struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
    08414     VALUE src_io, dst_io;
    08415     rb_io_t *src_fptr = 0, *dst_fptr = 0;
    08416     int src_fd, dst_fd;
    08417
    08418     stp->th = rb_thread_current();
    08419
    08420     stp->total = 0;
    08421
    08422     if (stp->src == argf ||
    08423         !(TYPE(stp->src) == T_FILE ||
    08424           TYPE(stp->src) == T_STRING ||
    08425           rb_respond_to(stp->src, rb_intern("to_path")))) {
    08426         src_fd = -1;
    08427     }
    08428     else {
    08429         src_io = TYPE(stp->src) == T_FILE ? stp->src : Qnil;
    08430         if (NIL_P(src_io)) {
    08431             VALUE args[2];
    08432             int oflags = O_RDONLY;
    08433 #ifdef O_NOCTTY
    08434             oflags |= O_NOCTTY;
    08435 #endif
    08436             FilePathValue(stp->src);
    08437             args[0] = stp->src;
    08438             args[1] = INT2NUM(oflags);
    08439             src_io = rb_class_new_instance(2, args, rb_cFile);
    08440             stp->src = src_io;
    08441             stp->close_src = 1;
    08442         }
    08443         GetOpenFile(src_io, src_fptr);
    08444         rb_io_check_byte_readable(src_fptr);
    08445         src_fd = src_fptr->fd;
    08446     }
    08447     stp->src_fd = src_fd;
    08448
    08449     if (stp->dst == argf ||
    08450         !(TYPE(stp->dst) == T_FILE ||
    08451           TYPE(stp->dst) == T_STRING ||
    08452           rb_respond_to(stp->dst, rb_intern("to_path")))) {
    08453         dst_fd = -1;
    08454     }
    08455     else {
    08456         dst_io = TYPE(stp->dst) == T_FILE ? stp->dst : Qnil;
    08457         if (NIL_P(dst_io)) {
    08458             VALUE args[3];
    08459             int oflags = O_WRONLY|O_CREAT|O_TRUNC;
    08460 #ifdef O_NOCTTY
    08461             oflags |= O_NOCTTY;
    08462 #endif
    08463             FilePathValue(stp->dst);
    08464             args[0] = stp->dst;
    08465             args[1] = INT2NUM(oflags);
    08466             args[2] = INT2FIX(0600);
    08467             dst_io = rb_class_new_instance(3, args, rb_cFile);
    08468             stp->dst = dst_io;
    08469             stp->close_dst = 1;
    08470         }
    08471         else {
    08472             dst_io = GetWriteIO(dst_io);
    08473             stp->dst = dst_io;
    08474         }
    08475         GetOpenFile(dst_io, dst_fptr);
    08476         rb_io_check_writable(dst_fptr);
    08477         dst_fd = dst_fptr->fd;
    08478     }
    08479     stp->dst_fd = dst_fd;
    08480
    08481     if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf_len) {
    08482         size_t len = src_fptr->rbuf_len;
    08483         VALUE str;
    08484         if (stp->copy_length != (off_t)-1 && stp->copy_length < (off_t)len) {
    08485             len = (size_t)stp->copy_length;
    08486         }
    08487         str = rb_str_buf_new(len);
    08488         rb_str_resize(str,len);
    08489         read_buffered_data(RSTRING_PTR(str), len, src_fptr);
    08490         if (dst_fptr) { /* IO or filename */
    08491             if (io_binwrite(str, dst_fptr, 0) < 0)
    08492                 rb_sys_fail(0);
    08493         }
    08494         else /* others such as StringIO */
    08495             rb_io_write(stp->dst, str);
    08496         stp->total += len;
    08497         if (stp->copy_length != (off_t)-1)
    08498             stp->copy_length -= len;
    08499     }
    08500
    08501     if (dst_fptr && io_fflush(dst_fptr) < 0) {
    08502         rb_raise(rb_eIOError, "flush failed");
    08503     }
    08504
    08505     if (stp->copy_length == 0)
    08506         return Qnil;
    08507
    08508     if (src_fd == -1 || dst_fd == -1) {
    08509         return copy_stream_fallback(stp);
    08510     }
    08511
    08512     rb_fd_init(&stp->fds);
    08513     rb_fd_set(src_fd, &stp->fds);
    08514     rb_fd_set(dst_fd, &stp->fds);
    08515
    08516     return rb_thread_blocking_region(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
    08517 }
    08518
    08519 static VALUE
    08520 copy_stream_finalize(VALUE arg)
    08521 {
    08522     struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
    08523     if (stp->close_src) {
    08524         rb_io_close_m(stp->src);
    08525     }
    08526     if (stp->close_dst) {
    08527         rb_io_close_m(stp->dst);
    08528     }
    08529     rb_fd_term(&stp->fds);
    08530     if (stp->syserr) {
    08531         errno = stp->error_no;
    08532         rb_sys_fail(stp->syserr);
    08533     }
    08534     if (stp->notimp) {
    08535         rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
    08536     }
    08537     return Qnil;
    08538 }
    08539
    08540 /*
    08541  *  call-seq:
    08542  *     IO.copy_stream(src, dst)
    08543  *     IO.copy_stream(src, dst, copy_length)
    08544  *     IO.copy_stream(src, dst, copy_length, src_offset)
    08545  *
    08546  *  IO.copy_stream copies <i>src</i> to <i>dst</i>.
    08547  *  <i>src</i> and <i>dst</i> is either a filename or an IO.
    08548  *
    08549  *  This method returns the number of bytes copied.
    08550  *
    08551  *  If optional arguments are not given,
    08552  *  the start position of the copy is
    08553  *  the beginning of the filename or
    08554  *  the current file offset of the IO.
    08555  *  The end position of the copy is the end of file.
    08556  *
    08557  *  If <i>copy_length</i> is given,
    08558  *  No more than <i>copy_length</i> bytes are copied.
    08559  *
    08560  *  If <i>src_offset</i> is given,
    08561  *  it specifies the start position of the copy.
    08562  *
    08563  *  When <i>src_offset</i> is specified and
    08564  *  <i>src</i> is an IO,
    08565  *  IO.copy_stream doesn't move the current file offset.
    08566  *
    08567  */
    08568 static VALUE
    08569 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
    08570 {
    08571     VALUE src, dst, length, src_offset;
    08572     struct copy_stream_struct st;
    08573
    08574     MEMZERO(&st, struct copy_stream_struct, 1);
    08575
    08576     rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
    08577
    08578     st.src = src;
    08579     st.dst = dst;
    08580
    08581     if (NIL_P(length))
    08582         st.copy_length = (off_t)-1;
    08583     else
    08584         st.copy_length = NUM2OFFT(length);
    08585
    08586     if (NIL_P(src_offset))
    08587         st.src_offset = (off_t)-1;
    08588     else
    08589         st.src_offset = NUM2OFFT(src_offset);
    08590
    08591     rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
    08592
    08593     return OFFT2NUM(st.total);
    08594 }
    08595
    08596 /*
    08597  *  call-seq:
    08598  *     io.external_encoding   -> encoding
    08599  *
    08600  *  Returns the Encoding object that represents the encoding of the file.
    08601  *  If io is write mode and no encoding is specified, returns <code>nil</code>.
    08602  */
    08603
    08604 static VALUE
    08605 rb_io_external_encoding(VALUE io)
    08606 {
    08607     rb_io_t *fptr;
    08608
    08609     GetOpenFile(io, fptr);
    08610     if (fptr->encs.enc2) {
    08611         return rb_enc_from_encoding(fptr->encs.enc2);
    08612     }
    08613     if (fptr->mode & FMODE_WRITABLE) {
    08614         if (fptr->encs.enc)
    08615             return rb_enc_from_encoding(fptr->encs.enc);
    08616         return Qnil;
    08617     }
    08618     return rb_enc_from_encoding(io_read_encoding(fptr));
    08619 }
    08620
    08621 /*
    08622  *  call-seq:
    08623  *     io.internal_encoding   -> encoding
    08624  *
    08625  *  Returns the Encoding of the internal string if conversion is
    08626  *  specified.  Otherwise returns nil.
    08627  */
    08628
    08629 static VALUE
    08630 rb_io_internal_encoding(VALUE io)
    08631 {
    08632     rb_io_t *fptr;
    08633
    08634     GetOpenFile(io, fptr);
    08635     if (!fptr->encs.enc2) return Qnil;
    08636     return rb_enc_from_encoding(io_read_encoding(fptr));
    08637 }
    08638
    08639 /*
    08640  *  call-seq:
    08641  *     io.set_encoding(ext_enc)                -> io
    08642  *     io.set_encoding("ext_enc:int_enc")      -> io
    08643  *     io.set_encoding(ext_enc, int_enc)       -> io
    08644  *     io.set_encoding("ext_enc:int_enc", opt) -> io
    08645  *     io.set_encoding(ext_enc, int_enc, opt)  -> io
    08646  *
    08647  *  If single argument is specified, read string from io is tagged
    08648  *  with the encoding specified.  If encoding is a colon separated two
    08649  *  encoding names "A:B", the read string is converted from encoding A
    08650  *  (external encoding) to encoding B (internal encoding), then tagged
    08651  *  with B.  If two arguments are specified, those must be encoding
    08652  *  objects or encoding names, and the first one is the external encoding, and the
    08653  *  second one is the internal encoding.
    08654  *  If the external encoding and the internal encoding is specified,
    08655  *  optional hash argument specify the conversion option.
    08656  */
    08657
    08658 static VALUE
    08659 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
    08660 {
    08661     rb_io_t *fptr;
    08662     VALUE v1, v2, opt;
    08663
    08664     if (TYPE(io) != T_FILE) {
    08665         return rb_funcall2(io, id_set_encoding, argc, argv);
    08666     }
    08667
    08668     opt = pop_last_hash(&argc, argv);
    08669     rb_scan_args(argc, argv, "11", &v1, &v2);
    08670     GetOpenFile(io, fptr);
    08671     io_encoding_set(fptr, v1, v2, opt);
    08672     return io;
    08673 }
    08674
    08675 void
    08676 rb_stdio_set_default_encoding(void)
    08677 {
    08678     extern VALUE rb_stdin, rb_stdout, rb_stderr;
    08679     VALUE val = Qnil;
    08680
    08681     rb_io_set_encoding(1, &val, rb_stdin);
    08682     rb_io_set_encoding(1, &val, rb_stdout);
    08683     rb_io_set_encoding(1, &val, rb_stderr);
    08684 }
    08685
    08686 /*
    08687  *  call-seq:
    08688  *     ARGF.external_encoding   -> encoding
    08689  *
    08690  *  Returns the external encoding for files read from +ARGF+ as an +Encoding+
    08691  *  object. The external encoding is the encoding of the text as stored in a
    08692  *  file. Contrast with +ARGF.internal_encoding+, which is the encoding used
    08693  *  to represent this text within Ruby.
    08694  *
    08695  *  To set the external encoding use +ARGF.set_encoding+.
    08696  *
    08697  * For example:
    08698  *
    08699  *     ARGF.external_encoding  #=>  #<Encoding:UTF-8>
    08700  *
    08701  */
    08702 static VALUE
    08703 argf_external_encoding(VALUE argf)
    08704 {
    08705     if (!RTEST(ARGF.current_file)) {
    08706         return rb_enc_from_encoding(rb_default_external_encoding());
    08707     }
    08708     return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
    08709 }
    08710
    08711 /*
    08712  *  call-seq:
    08713  *     ARGF.internal_encoding   -> encoding
    08714  *
    08715  *  Returns the internal encoding for strings read from +ARGF+ as an
    08716  *  +Encoding+ object.
    08717  *
    08718  *  If +ARGF.set_encoding+ has been called with two encoding names, the second
    08719  *  is returned. Otherwise, if +Encoding.default_external+ has been set, that
    08720  *  value is returned. Failing that, if a default external encoding was
    08721  *  specified on the command-line, that value is used. If the encoding is
    08722  *  unknown, nil is returned.
    08723  */
    08724 static VALUE
    08725 argf_internal_encoding(VALUE argf)
    08726 {
    08727     if (!RTEST(ARGF.current_file)) {
    08728         return rb_enc_from_encoding(rb_default_external_encoding());
    08729     }
    08730     return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
    08731 }
    08732
    08733 /*
    08734  *  call-seq:
    08735  *     ARGF.set_encoding(ext_enc)                -> ARGF
    08736  *     ARGF.set_encoding("ext_enc:int_enc")      -> ARGF
    08737  *     ARGF.set_encoding(ext_enc, int_enc)       -> ARGF
    08738  *     ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
    08739  *     ARGF.set_encoding(ext_enc, int_enc, opt)  -> ARGF
    08740  *
    08741  *  If single argument is specified, strings read from ARGF are tagged with
    08742  *  the encoding specified.
    08743  *
    08744  *  If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
    08745  *  the read string is converted from the first encoding (external encoding)
    08746  *  to the second encoding (internal encoding), then tagged with the second
    08747  *  encoding.
    08748  *
    08749  *  If two arguments are specified, they must be encoding objects or encoding
    08750  *  names. Again, the first specifies the external encoding; the second
    08751  *  specifies the internal encoding.
    08752  *
    08753  *  If the external encoding and the internal encoding are specified, the
    08754  *  optional +Hash+ argument can be used to adjust the conversion process. The
    08755  *  structure of this hash is explained in the +String#encode+ documentation.
    08756  *
    08757  *  For example:
    08758  *
    08759  *      ARGF.set_encoding('ascii')         # Tag the input as US-ASCII text
    08760  *      ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
    08761  *      ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
    08762  *                                         # to UTF-8.
    08763  */
    08764 static VALUE
    08765 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
    08766 {
    08767     rb_io_t *fptr;
    08768
    08769     if (!next_argv()) {
    08770         rb_raise(rb_eArgError, "no stream to set encoding");
    08771     }
    08772     rb_io_set_encoding(argc, argv, ARGF.current_file);
    08773     GetOpenFile(ARGF.current_file, fptr);
    08774     ARGF.encs = fptr->encs;
    08775     return argf;
    08776 }
    08777
    08778 /*
    08779  *  call-seq:
    08780  *     ARGF.tell  -> Integer
    08781  *     ARGF.pos   -> Integer
    08782  *
    08783  *  Returns the current offset (in bytes) of the current file in +ARGF+.
    08784  *
    08785  *     ARGF.pos    #=> 0
    08786  *     ARGF.gets   #=> "This is line one\n"
    08787  *     ARGF.pos    #=> 17
    08788  *
    08789  */
    08790 static VALUE
    08791 argf_tell(VALUE argf)
    08792 {
    08793     if (!next_argv()) {
    08794         rb_raise(rb_eArgError, "no stream to tell");
    08795     }
    08796     ARGF_FORWARD(0, 0);
    08797     return rb_io_tell(ARGF.current_file);
    08798 }
    08799
    08800 /*
    08801  *  call-seq:
    08802  *     ARGF.seek(amount, whence=IO::SEEK_SET)  ->  0
    08803  *
    08804  *  Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
    08805  *  the value of _whence_. See +IO#seek+ for further details.
    08806  */
    08807 static VALUE
    08808 argf_seek_m(int argc, VALUE *argv, VALUE argf)
    08809 {
    08810     if (!next_argv()) {
    08811         rb_raise(rb_eArgError, "no stream to seek");
    08812     }
    08813     ARGF_FORWARD(argc, argv);
    08814     return rb_io_seek_m(argc, argv, ARGF.current_file);
    08815 }
    08816
    08817 /*
    08818  *  call-seq:
    08819  *     ARGF.pos = position  -> Integer
    08820  *
    08821  *  Seeks to the position given by _position_ (in bytes) in +ARGF+.
    08822  *
    08823  *  For example:
    08824  *
    08825  *      ARGF.pos = 17
    08826  *      ARGF.gets   #=> "This is line two\n"
    08827  */
    08828 static VALUE
    08829 argf_set_pos(VALUE argf, VALUE offset)
    08830 {
    08831     if (!next_argv()) {
    08832         rb_raise(rb_eArgError, "no stream to set position");
    08833     }
    08834     ARGF_FORWARD(1, &offset);
    08835     return rb_io_set_pos(ARGF.current_file, offset);
    08836 }
    08837
    08838 /*
    08839  *  call-seq:
    08840  *     ARGF.rewind   -> 0
    08841  *
    08842  *  Positions the current file to the beginning of input, resetting
    08843  *  +ARGF.lineno+ to zero.
    08844  *
    08845  *     ARGF.readline   #=> "This is line one\n"
    08846  *     ARGF.rewind     #=> 0
    08847  *     ARGF.lineno     #=> 0
    08848  *     ARGF.readline   #=> "This is line one\n"
    08849  */
    08850 static VALUE
    08851 argf_rewind(VALUE argf)
    08852 {
    08853     if (!next_argv()) {
    08854         rb_raise(rb_eArgError, "no stream to rewind");
    08855     }
    08856     ARGF_FORWARD(0, 0);
    08857     return rb_io_rewind(ARGF.current_file);
    08858 }
    08859
    08860 /*
    08861  *  call-seq:
    08862  *     ARGF.fileno    -> fixnum
    08863  *     ARGF.to_i      -> fixnum
    08864  *
    08865  *  Returns an integer representing the numeric file descriptor for
    08866  *  the current file. Raises an +ArgumentError+ if there isn't a current file.
    08867  *
    08868  *     ARGF.fileno    #=> 3
    08869  */
    08870 static VALUE
    08871 argf_fileno(VALUE argf)
    08872 {
    08873     if (!next_argv()) {
    08874         rb_raise(rb_eArgError, "no stream");
    08875     }
    08876     ARGF_FORWARD(0, 0);
    08877     return rb_io_fileno(ARGF.current_file);
    08878 }
    08879
    08880 /*
    08881  *  call-seq:
    08882  *     ARGF.to_io     -> IO
    08883  *
    08884  *  Returns an +IO+ object representing the current file. This will be a
    08885  *  +File+ object unless the current file is a stream such as STDIN.
    08886  *
    08887  *  For example:
    08888  *
    08889  *     ARGF.to_io    #=> #<File:glark.txt>
    08890  *     ARGF.to_io    #=> #<IO:<STDIN>>
    08891  */
    08892 static VALUE
    08893 argf_to_io(VALUE argf)
    08894 {
    08895     next_argv();
    08896     ARGF_FORWARD(0, 0);
    08897     return ARGF.current_file;
    08898 }
    08899
    08900 /*
    08901  *  call-seq:
    08902  *     ARGF.eof?  -> true or false
    08903  *     ARGF.eof   -> true or false
    08904  *
    08905  *  Returns true if the current file in +ARGF+ is at end of file, i.e. it has
    08906  *  no data to read. The stream must be opened for reading or an +IOError+
    08907  *  will be raised.
    08908  *
    08909  *     $ echo "eof" | ruby argf.rb
    08910  *
    08911  *     ARGF.eof?                 #=> false
    08912  *     3.times { ARGF.readchar }
    08913  *     ARGF.eof?                 #=> false
    08914  *     ARGF.readchar             #=> "\n"
    08915  *     ARGF.eof?                 #=> true
    08916  */
    08917
    08918 static VALUE
    08919 argf_eof(VALUE argf)
    08920 {
    08921     next_argv();
    08922     if (RTEST(ARGF.current_file)) {
    08923         if (ARGF.init_p == 0) return Qtrue;
    08924         next_argv();
    08925         ARGF_FORWARD(0, 0);
    08926         if (rb_io_eof(ARGF.current_file)) {
    08927             return Qtrue;
    08928         }
    08929     }
    08930     return Qfalse;
    08931 }
    08932
    08933 /*
    08934  *  call-seq:
    08935  *     ARGF.read([length [, buffer]])    -> string, buffer, or nil
    08936  *
    08937  *  Reads _length_ bytes from ARGF. The files named on the command line
    08938  *  are concatenated and treated as a single file by this method, so when
    08939  *  called without arguments the contents of this pseudo file are returned in
    08940  *  their entirety.
    08941  *
    08942  *  _length_ must be a non-negative integer or nil. If it is a positive
    08943  *  integer, +read+ tries to read at most _length_ bytes. It returns nil
    08944  *  if an EOF was encountered before anything could be read. Fewer than
    08945  *  _length_ bytes may be returned if an EOF is encountered during the read.
    08946  *
    08947  *  If _length_ is omitted or is _nil_, it reads until EOF. A String is
    08948  *  returned even if EOF is encountered before any data is read.
    08949  *
    08950  *  If _length_ is zero, it returns _""_.
    08951  *
    08952  *  If the optional _buffer_ argument is present, it must reference a String,
    08953  *  which will receive the data.
    08954  *
    08955  * For example:
    08956  *
    08957  *     $ echo "small" > small.txt
    08958  *     $ echo "large" > large.txt
    08959  *     $ ./glark.rb small.txt large.txt
    08960  *
    08961  *     ARGF.read      #=> "small\nlarge"
    08962  *     ARGF.read(200) #=> "small\nlarge"
    08963  *     ARGF.read(2)   #=> "sm"
    08964  *     ARGF.read(0)   #=> ""
    08965  *
    08966  *  Note that this method behaves like fread() function in C.  If you need the
    08967  *  behavior like read(2) system call, consider +ARGF.readpartial+.
    08968  */
    08969
    08970 static VALUE
    08971 argf_read(int argc, VALUE *argv, VALUE argf)
    08972 {
    08973     VALUE tmp, str, length;
    08974     long len = 0;
    08975
    08976     rb_scan_args(argc, argv, "02", &length, &str);
    08977     if (!NIL_P(length)) {
    08978         len = NUM2LONG(argv[0]);
    08979     }
    08980     if (!NIL_P(str)) {
    08981         StringValue(str);
    08982         rb_str_resize(str,0);
    08983         argv[1] = Qnil;
    08984     }
    08985
    08986   retry:
    08987     if (!next_argv()) {
    08988         return str;
    08989     }
    08990     if (ARGF_GENERIC_INPUT_P()) {
    08991         tmp = argf_forward(argc, argv, argf);
    08992     }
    08993     else {
    08994         tmp = io_read(argc, argv, ARGF.current_file);
    08995     }
    08996     if (NIL_P(str)) str = tmp;
    08997     else if (!NIL_P(tmp)) rb_str_append(str, tmp);
    08998     if (NIL_P(tmp) || NIL_P(length)) {
    08999         if (ARGF.next_p != -1) {
    09000             argf_close(ARGF.current_file);
    09001             ARGF.next_p = 1;
    09002             goto retry;
    09003         }
    09004     }
    09005     else if (argc >= 1) {
    09006         if (RSTRING_LEN(str) < len) {
    09007             len -= RSTRING_LEN(str);
    09008             argv[0] = INT2NUM(len);
    09009             goto retry;
    09010         }
    09011     }
    09012     return str;
    09013 }
    09014
    09015 struct argf_call_arg {
    09016     int argc;
    09017     VALUE *argv;
    09018     VALUE argf;
    09019 };
    09020
    09021 static VALUE
    09022 argf_forward_call(VALUE arg)
    09023 {
    09024     struct argf_call_arg *p = (struct argf_call_arg *)arg;
    09025     argf_forward(p->argc, p->argv, p->argf);
    09026     return Qnil;
    09027 }
    09028
    09029 /*
    09030  *  call-seq:
    09031  *     ARGF.readpartial(maxlen)              -> string
    09032  *     ARGF.readpartial(maxlen, outbuf)      -> outbuf
    09033  *
    09034  *  Reads at most _maxlen_ bytes from the ARGF stream. It blocks only if
    09035  *  +ARGF+ has no data immediately available. If the optional _outbuf_
    09036  *  argument is present, it must reference a String, which will receive the
    09037  *  data. It raises <code>EOFError</code> on end of file.
    09038  *
    09039  *  +readpartial+ is designed for streams such as pipes, sockets, and ttys. It
    09040  *  blocks only when no data is immediately available. This means that it
    09041  *  blocks only when following all conditions hold:
    09042  *
    09043  *  * The byte buffer in the +IO+ object is empty.
    09044  *  * The content of the stream is empty.
    09045  *  * The stream has not reached EOF.
    09046  *
    09047  *  When +readpartial+ blocks, it waits for data or EOF. If some data is read,
    09048  *  +readpartial+ returns with the data. If EOF is reached, readpartial raises
    09049  *  an +EOFError+.
    09050  *
    09051  *  When +readpartial+ doesn't block, it returns or raises immediately.  If
    09052  *  the byte buffer is not empty, it returns the data in the buffer. Otherwise, if
    09053  *  the stream has some content, it returns the data in the stream. If the
    09054  *  stream reaches EOF an +EOFError+ is raised.
    09055  */
    09056
    09057 static VALUE
    09058 argf_readpartial(int argc, VALUE *argv, VALUE argf)
    09059 {
    09060     VALUE tmp, str, length;
    09061
    09062     rb_scan_args(argc, argv, "11", &length, &str);
    09063     if (!NIL_P(str)) {
    09064         StringValue(str);
    09065         argv[1] = str;
    09066     }
    09067
    09068     if (!next_argv()) {
    09069         rb_str_resize(str, 0);
    09070         rb_eof_error();
    09071     }
    09072     if (ARGF_GENERIC_INPUT_P()) {
    09073         struct argf_call_arg arg;
    09074         arg.argc = argc;
    09075         arg.argv = argv;
    09076         arg.argf = argf;
    09077         tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
    09078                          RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
    09079     }
    09080     else {
    09081         tmp = io_getpartial(argc, argv, ARGF.current_file, 0);
    09082     }
    09083     if (NIL_P(tmp)) {
    09084         if (ARGF.next_p == -1) {
    09085             rb_eof_error();
    09086         }
    09087         argf_close(ARGF.current_file);
    09088         ARGF.next_p = 1;
    09089         if (RARRAY_LEN(ARGF.argv) == 0)
    09090             rb_eof_error();
    09091         if (NIL_P(str))
    09092             str = rb_str_new(NULL, 0);
    09093         return str;
    09094     }
    09095     return tmp;
    09096 }
    09097
    09098 /*
    09099  *  call-seq:
    09100  *     ARGF.getc  -> String or nil
    09101  *
    09102  *  Reads the next character from +ARGF+ and returns it as a +String+. Returns
    09103  *  +nil+ at the end of the stream.
    09104  *
    09105  *  +ARGF+ treats the files named on the command line as a single file created
    09106  *  by concatenating their contents. After returning the last character of the
    09107  *  first file, it returns the first character of the second file, and so on.
    09108  *
    09109  *  For example:
    09110  *
    09111  *     $ echo "foo" > file
    09112  *     $ ruby argf.rb file
    09113  *
    09114  *     ARGF.getc  #=> "f"
    09115  *     ARGF.getc  #=> "o"
    09116  *     ARGF.getc  #=> "o"
    09117  *     ARGF.getc  #=> "\n"
    09118  *     ARGF.getc  #=> nil
    09119  *     ARGF.getc  #=> nil
    09120  */
    09121 static VALUE
    09122 argf_getc(VALUE argf)
    09123 {
    09124     VALUE ch;
    09125
    09126   retry:
    09127     if (!next_argv()) return Qnil;
    09128     if (ARGF_GENERIC_INPUT_P()) {
    09129         ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
    09130     }
    09131     else {
    09132         ch = rb_io_getc(ARGF.current_file);
    09133     }
    09134     if (NIL_P(ch) && ARGF.next_p != -1) {
    09135         argf_close(ARGF.current_file);
    09136         ARGF.next_p = 1;
    09137         goto retry;
    09138     }
    09139
    09140     return ch;
    09141 }
    09142
    09143 /*
    09144  *  call-seq:
    09145  *     ARGF.getbyte  -> Fixnum or nil
    09146  *
    09147  *  Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
    09148  *  the end of the stream.
    09149  *
    09150  *  For example:
    09151  *
    09152  *     $ echo "foo" > file
    09153  *     $ ruby argf.rb file
    09154  *
    09155  *     ARGF.getbyte #=> 102
    09156  *     ARGF.getbyte #=> 111
    09157  *     ARGF.getbyte #=> 111
    09158  *     ARGF.getbyte #=> 10
    09159  *     ARGF.getbyte #=> nil
    09160  */
    09161 static VALUE
    09162 argf_getbyte(VALUE argf)
    09163 {
    09164     VALUE ch;
    09165
    09166   retry:
    09167     if (!next_argv()) return Qnil;
    09168     if (TYPE(ARGF.current_file) != T_FILE) {
    09169         ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
    09170     }
    09171     else {
    09172         ch = rb_io_getbyte(ARGF.current_file);
    09173     }
    09174     if (NIL_P(ch) && ARGF.next_p != -1) {
    09175         argf_close(ARGF.current_file);
    09176         ARGF.next_p = 1;
    09177         goto retry;
    09178     }
    09179
    09180     return ch;
    09181 }
    09182
    09183 /*
    09184  *  call-seq:
    09185  *     ARGF.readchar  -> String or nil
    09186  *
    09187  *  Reads the next character from +ARGF+ and returns it as a +String+. Raises
    09188  *  an +EOFError+ after the last character of the last file has been read.
    09189  *
    09190  *  For example:
    09191  *
    09192  *     $ echo "foo" > file
    09193  *     $ ruby argf.rb file
    09194  *
    09195  *     ARGF.readchar  #=> "f"
    09196  *     ARGF.readchar  #=> "o"
    09197  *     ARGF.readchar  #=> "o"
    09198  *     ARGF.readchar  #=> "\n"
    09199  *     ARGF.readchar  #=> end of file reached (EOFError)
    09200  */
    09201 static VALUE
    09202 argf_readchar(VALUE argf)
    09203 {
    09204     VALUE ch;
    09205
    09206   retry:
    09207     if (!next_argv()) rb_eof_error();
    09208     if (TYPE(ARGF.current_file) != T_FILE) {
    09209         ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
    09210     }
    09211     else {
    09212         ch = rb_io_getc(ARGF.current_file);
    09213     }
    09214     if (NIL_P(ch) && ARGF.next_p != -1) {
    09215         argf_close(ARGF.current_file);
    09216         ARGF.next_p = 1;
    09217         goto retry;
    09218     }
    09219
    09220     return ch;
    09221 }
    09222
    09223 /*
    09224  *  call-seq:
    09225  *     ARGF.readbyte  -> Fixnum
    09226  *
    09227  *  Reads the next 8-bit byte from ARGF and returns it as a +Fixnum+. Raises
    09228  *  an +EOFError+ after the last byte of the last file has been read.
    09229  *
    09230  *  For example:
    09231  *
    09232  *     $ echo "foo" > file
    09233  *     $ ruby argf.rb file
    09234  *
    09235  *     ARGF.readbyte  #=> 102
    09236  *     ARGF.readbyte  #=> 111
    09237  *     ARGF.readbyte  #=> 111
    09238  *     ARGF.readbyte  #=> 10
    09239  *     ARGF.readbyte  #=> end of file reached (EOFError)
    09240  */
    09241 static VALUE
    09242 argf_readbyte(VALUE argf)
    09243 {
    09244     VALUE c;
    09245
    09246     NEXT_ARGF_FORWARD(0, 0);
    09247     c = argf_getbyte(argf);
    09248     if (NIL_P(c)) {
    09249         rb_eof_error();
    09250     }
    09251     return c;
    09252 }
    09253
    09254 /*
    09255  *  call-seq:
    09256  *     ARGF.each(sep=$/)            {|line| block }  -> ARGF
    09257  *     ARGF.each(sep=$/,limit)      {|line| block }  -> ARGF
    09258  *     ARGF.each(...)                                -> an_enumerator
    09259  *
    09260  *     ARGF.each_line(sep=$/)       {|line| block }  -> ARGF
    09261  *     ARGF.each_line(sep=$/,limit) {|line| block }  -> ARGF
    09262  *     ARGF.each_line(...)                           -> an_enumerator
    09263  *
    09264  *     ARGF.lines(sep=$/)           {|line| block }   -> ARGF
    09265  *     ARGF.lines(sep=$/,limit)     {|line| block }   -> ARGF
    09266  *     ARGF.lines(...)                                -> an_enumerator
    09267  *
    09268  *  Returns an enumerator which iterates over each line (separated by _sep_,
    09269  *  which defaults to your platform's newline character) of each file in
    09270  *  +ARGV+. If a block is supplied, each line in turn will be yielded to the
    09271  *  block, otherwise an enumerator is returned.
    09272  *  The optional _limit_ argument is a +Fixnum+ specifying the maximum
    09273  *  length of each line; longer lines will be split according to this limit.
    09274  *
    09275  *  This method allows you to treat the files supplied on the command line as
    09276  *  a single file consisting of the concatenation of each named file. After
    09277  *  the last line of the first file has been returned, the first line of the
    09278  *  second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
    09279  *  be used to determine the filename and line number, respectively, of the
    09280  *  current line.
    09281  *
    09282  *  For example, the following code prints out each line of each named file
    09283  *  prefixed with its line number, displaying the filename once per file:
    09284  *
    09285  *     ARGF.lines do |line|
    09286  *       puts ARGF.filename if ARGF.lineno == 1
    09287  *       puts "#{ARGF.lineno}: #{line}"
    09288  *     end
    09289  */
    09290 static VALUE
    09291 argf_each_line(int argc, VALUE *argv, VALUE argf)
    09292 {
    09293     RETURN_ENUMERATOR(argf, argc, argv);
    09294     for (;;) {
    09295         if (!next_argv()) return argf;
    09296         rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
    09297         ARGF.next_p = 1;
    09298     }
    09299 }
    09300
    09301 /*
    09302  *  call-seq:
    09303  *     ARGF.bytes     {|byte| block }  -> ARGF
    09304  *     ARGF.bytes                      -> an_enumerator
    09305  *
    09306  *     ARGF.each_byte {|byte| block }  -> ARGF
    09307  *     ARGF.each_byte                  -> an_enumerator
    09308  *
    09309  *  Iterates over each byte of each file in +ARGV+.
    09310  *  A byte is returned as a +Fixnum+ in the range 0..255.
    09311  *
    09312  *  This method allows you to treat the files supplied on the command line as
    09313  *  a single file consisting of the concatenation of each named file. After
    09314  *  the last byte of the first file has been returned, the first byte of the
    09315  *  second file is returned. The +ARGF.filename+ method can be used to
    09316  *  determine the filename of the current byte.
    09317  *
    09318  *  If no block is given, an enumerator is returned instead.
    09319  *
    09320  * For example:
    09321  *
    09322  *     ARGF.bytes.to_a  #=> [35, 32, ... 95, 10]
    09323  *
    09324  */
    09325 static VALUE
    09326 argf_each_byte(VALUE argf)
    09327 {
    09328     RETURN_ENUMERATOR(argf, 0, 0);
    09329     for (;;) {
    09330         if (!next_argv()) return argf;
    09331         rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, 0, 0);
    09332         ARGF.next_p = 1;
    09333     }
    09334 }
    09335
    09336 /*
    09337  *  call-seq:
    09338  *     ARGF.chars      {|char| block }  -> ARGF
    09339  *     ARGF.chars                       -> an_enumerator
    09340  *
    09341  *     ARGF.each_char  {|char| block }  -> ARGF
    09342  *     ARGF.each_char                   -> an_enumerator
    09343  *
    09344  *  Iterates over each character of each file in +ARGF+.
    09345  *
    09346  *  This method allows you to treat the files supplied on the command line as
    09347  *  a single file consisting of the concatenation of each named file. After
    09348  *  the last character of the first file has been returned, the first
    09349  *  character of the second file is returned. The +ARGF.filename+ method can
    09350  *  be used to determine the name of the file in which the current character
    09351  *  appears.
    09352  *
    09353  *  If no block is given, an enumerator is returned instead.
    09354  */
    09355 static VALUE
    09356 argf_each_char(VALUE argf)
    09357 {
    09358     RETURN_ENUMERATOR(argf, 0, 0);
    09359     for (;;) {
    09360         if (!next_argv()) return argf;
    09361         rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, 0, 0);
    09362         ARGF.next_p = 1;
    09363     }
    09364 }
    09365
    09366 /*
    09367  *  call-seq:
    09368  *     ARGF.filename  -> String
    09369  *     ARGF.path      -> String
    09370  *
    09371  *  Returns the current filename. "-" is returned when the current file is
    09372  *  STDIN.
    09373  *
    09374  *  For example:
    09375  *
    09376  *     $ echo "foo" > foo
    09377  *     $ echo "bar" > bar
    09378  *     $ echo "glark" > glark
    09379  *
    09380  *     $ ruby argf.rb foo bar glark
    09381  *
    09382  *     ARGF.filename  #=> "foo"
    09383  *     ARGF.read(5)   #=> "foo\nb"
    09384  *     ARGF.filename  #=> "bar"
    09385  *     ARGF.skip
    09386  *     ARGF.filename  #=> "glark"
    09387  */
    09388 static VALUE
    09389 argf_filename(VALUE argf)
    09390 {
    09391     next_argv();
    09392     return ARGF.filename;
    09393 }
    09394
    09395 static VALUE
    09396 argf_filename_getter(ID id, VALUE *var)
    09397 {
    09398     return argf_filename(*var);
    09399 }
    09400
    09401 /*
    09402  *  call-seq:
    09403  *     ARGF.file  -> IO or File object
    09404  *
    09405  *  Returns the current file as an +IO+ or +File+ object. #<IO:<STDIN>> is
    09406  *  returned when the current file is STDIN.
    09407  *
    09408  *  For example:
    09409  *
    09410  *     $ echo "foo" > foo
    09411  *     $ echo "bar" > bar
    09412  *
    09413  *     $ ruby argf.rb foo bar
    09414  *
    09415  *     ARGF.file      #=> #<File:foo>
    09416  *     ARGF.read(5)   #=> "foo\nb"
    09417  *     ARGF.file      #=> #<File:bar>
    09418  */
    09419 static VALUE
    09420 argf_file(VALUE argf)
    09421 {
    09422     next_argv();
    09423     return ARGF.current_file;
    09424 }
    09425
    09426 /*
    09427  *  call-seq:
    09428  *     ARGF.binmode  -> ARGF
    09429  *
    09430  *  Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
    09431  *  be reset to non-binary mode. This option has the following effects:
    09432  *
    09433  *  *  Newline conversion is disabled.
    09434  *  *  Encoding conversion is disabled.
    09435  *  *  Content is treated as ASCII-8BIT.
    09436  */
    09437 static VALUE
    09438 argf_binmode_m(VALUE argf)
    09439 {
    09440     ARGF.binmode = 1;
    09441     next_argv();
    09442     ARGF_FORWARD(0, 0);
    09443     rb_io_ascii8bit_binmode(ARGF.current_file);
    09444     return argf;
    09445 }
    09446
    09447 /*
    09448  *  call-seq:
    09449  *     ARGF.binmode?  -> true or false
    09450  *
    09451  *  Returns true if +ARGF+ is being read in binary mode; false otherwise. (To
    09452  *  enable binary mode use +ARGF.binmode+.
    09453  *
    09454  * For example:
    09455  *
    09456  *     ARGF.binmode?  #=> false
    09457  *     ARGF.binmode
    09458  *     ARGF.binmode?  #=> true
    09459  */
    09460 static VALUE
    09461 argf_binmode_p(VALUE argf)
    09462 {
    09463     return ARGF.binmode ? Qtrue : Qfalse;
    09464 }
    09465
    09466 /*
    09467  *  call-seq:
    09468  *     ARGF.skip  -> ARGF
    09469  *
    09470  *  Sets the current file to the next file in ARGV. If there aren't any more
    09471  *  files it has no effect.
    09472  *
    09473  * For example:
    09474  *
    09475  *     $ ruby argf.rb foo bar
    09476  *     ARGF.filename  #=> "foo"
    09477  *     ARGF.skip
    09478  *     ARGF.filename  #=> "bar"
    09479  */
    09480 static VALUE
    09481 argf_skip(VALUE argf)
    09482 {
    09483     if (ARGF.init_p && ARGF.next_p == 0) {
    09484         argf_close(ARGF.current_file);
    09485         ARGF.next_p = 1;
    09486     }
    09487     return argf;
    09488 }
    09489
    09490 /*
    09491  *  call-seq:
    09492  *     ARGF.close  -> ARGF
    09493  *
    09494  *  Closes the current file and skips to the next in the stream. Trying to
    09495  *  close a file that has already been closed causes an +IOError+ to be
    09496  *  raised.
    09497  *
    09498  * For example:
    09499  *
    09500  *     $ ruby argf.rb foo bar
    09501  *
    09502  *     ARGF.filename  #=> "foo"
    09503  *     ARGF.close
    09504  *     ARGF.filename  #=> "bar"
    09505  *     ARGF.close
    09506  *     ARGF.close     #=> closed stream (IOError)
    09507  */
    09508 static VALUE
    09509 argf_close_m(VALUE argf)
    09510 {
    09511     next_argv();
    09512     argf_close(ARGF.current_file);
    09513     if (ARGF.next_p != -1) {
    09514         ARGF.next_p = 1;
    09515     }
    09516     ARGF.lineno = 0;
    09517     return argf;
    09518 }
    09519
    09520 /*
    09521  *  call-seq:
    09522  *     ARGF.closed?  -> true or false
    09523  *
    09524  *  Returns _true_ if the current file has been closed; _false_ otherwise. Use
    09525  *  +ARGF.close+ to actually close the current file.
    09526  */
    09527 static VALUE
    09528 argf_closed(VALUE argf)
    09529 {
    09530     next_argv();
    09531     ARGF_FORWARD(0, 0);
    09532     return rb_io_closed(ARGF.current_file);
    09533 }
    09534
    09535 /*
    09536  *  call-seq:
    09537  *     ARGF.to_s  -> String
    09538  *
    09539  *  Returns "ARGF".
    09540  */
    09541 static VALUE
    09542 argf_to_s(VALUE argf)
    09543 {
    09544     return rb_str_new2("ARGF");
    09545 }
    09546
    09547 /*
    09548  *  call-seq:
    09549  *     ARGF.inplace_mode  -> String
    09550  *
    09551  *  Returns the file extension appended to the names of modified files under
    09552  *  inplace-edit mode. This value can be set using +ARGF.inplace_mode=+ or
    09553  *  passing the +-i+ switch to the Ruby binary.
    09554  */
    09555 static VALUE
    09556 argf_inplace_mode_get(VALUE argf)
    09557 {
    09558     if (!ARGF.inplace) return Qnil;
    09559     return rb_str_new2(ARGF.inplace);
    09560 }
    09561
    09562 static VALUE
    09563 opt_i_get(ID id, VALUE *var)
    09564 {
    09565     return argf_inplace_mode_get(*var);
    09566 }
    09567
    09568 /*
    09569  *  call-seq:
    09570  *     ARGF.inplace_mode = ext  -> ARGF
    09571  *
    09572  *  Sets the filename extension for inplace editing mode to the given String.
    09573  *  Each file being edited has this value appended to its filename. The
    09574  *  modified file is saved under this new name.
    09575  *
    09576  *  For example:
    09577  *
    09578  *      $ ruby argf.rb file.txt
    09579  *
    09580  *      ARGF.inplace_mode = '.bak'
    09581  *      ARGF.lines do |line|
    09582  *        print line.sub("foo","bar")
    09583  *      end
    09584  *
    09585  * Each line of _file.txt_ has the first occurrence of "foo" replaced with
    09586  * "bar", then the new line is written out to _file.txt.bak_.
    09587  */
    09588 static VALUE
    09589 argf_inplace_mode_set(VALUE argf, VALUE val)
    09590 {
    09591     if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
    09592         rb_insecure_operation();
    09593
    09594     if (!RTEST(val)) {
    09595         if (ARGF.inplace) free(ARGF.inplace);
    09596         ARGF.inplace = 0;
    09597     }
    09598     else {
    09599         StringValue(val);
    09600         if (ARGF.inplace) free(ARGF.inplace);
    09601         ARGF.inplace = 0;
    09602         ARGF.inplace = strdup(RSTRING_PTR(val));
    09603     }
    09604     return argf;
    09605 }
    09606
    09607 static void
    09608 opt_i_set(VALUE val, ID id, VALUE *var)
    09609 {
    09610     argf_inplace_mode_set(*var, val);
    09611 }
    09612
    09613 const char *
    09614 ruby_get_inplace_mode(void)
    09615 {
    09616     return ARGF.inplace;
    09617 }
    09618
    09619 void
    09620 ruby_set_inplace_mode(const char *suffix)
    09621 {
    09622     if (ARGF.inplace) free(ARGF.inplace);
    09623     ARGF.inplace = 0;
    09624     if (suffix) ARGF.inplace = strdup(suffix);
    09625 }
    09626
    09627 /*
    09628  *  call-seq:
    09629  *     ARGF.argv  -> ARGV
    09630  *
    09631  *  Returns the +ARGV+ array, which contains the arguments passed to your
    09632  *  script, one per element.
    09633  *
    09634  *  For example:
    09635  *
    09636  *      $ ruby argf.rb -v glark.txt
    09637  *
    09638  *      ARGF.argv   #=> ["-v", "glark.txt"]
    09639  *
    09640  */
    09641 static VALUE
    09642 argf_argv(VALUE argf)
    09643 {
    09644     return ARGF.argv;
    09645 }
    09646
    09647 static VALUE
    09648 argf_argv_getter(ID id, VALUE *var)
    09649 {
    09650     return argf_argv(*var);
    09651 }
    09652
    09653 VALUE
    09654 rb_get_argv(void)
    09655 {
    09656     return ARGF.argv;
    09657 }
    09658
    09659 /*
    09660  * Document-class: IOError
    09661  *
    09662  * Raised when an IO operation fails.
    09663  *
    09664  *    File.open("/etc/hosts") {|f| f << "example"}
    09665  *      #=> IOError: not opened for writing
    09666  *
    09667  *    File.open("/etc/hosts") {|f| f.close; f.read }
    09668  *      #=> IOError: closed stream
    09669  *
    09670  * Note that some IO failures raise +SystemCallError+s and these are not
    09671  * subclasses of IOError:
    09672  *
    09673  *    File.open("does/not/exist")
    09674  *      #=> Errno::ENOENT: No such file or directory - does/not/exist
    09675  */
    09676
    09677 /*
    09678 * Document-class: EOFError
    09679 *
    09680  * Raised by some IO operations when reaching the end of file. Many IO
    09681  * methods exist in two forms,
    09682  *
    09683  * one that returns +nil+ when the end of file is reached, the other
    09684  * raises EOFError +EOFError+.
    09685  *
    09686  * +EOFError+ is a subclass of +IOError+.
    09687  *
    09688  *    file = File.open("/etc/hosts")
    09689  *    file.read
    09690  *    file.gets     #=> nil
    09691  *    file.readline #=> EOFError: end of file reached
    09692  */
    09693
    09694 /*
    09695  * Document-class:  ARGF
    09696  *
    09697  * +ARGF+ is a stream designed for use in scripts that process files given as
    09698  * command-line arguments, or passed in via STDIN.
    09699  *
    09700  * The arguments passed to your script are stored in the +ARGV+ Array, one
    09701  * argument per element. +ARGF+ assumes that any arguments that aren't
    09702  * filenames have been removed from +ARGV+. For example:
    09703  *
    09704  *     $ ruby argf.rb --verbose file1 file2
    09705  *
    09706  *     ARGV  #=> ["--verbose", "file1", "file2"]
    09707  *     option = ARGV.shift #=> "--verbose"
    09708  *     ARGV  #=> ["file1", "file2"]
    09709  *
    09710  * You can now use +ARGF+ to work with a concatenation of each of these named
    09711  * files. For instance, +ARGF.read+ will return the contents of _file1_
    09712  * followed by the contents of _file2_.
    09713  *
    09714  * After a file in +ARGV+ has been read, +ARGF+ removes it from the Array.
    09715  * Thus, after all files have been read +ARGV+ will be empty.
    09716  *
    09717  * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
    09718  * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
    09719  * +ARGV+, they are treated as if they were named on the command line. For
    09720  * example:
    09721  *
    09722  *     ARGV.replace ["file1"]
    09723  *     ARGF.readlines # Returns the contents of file1 as an Array
    09724  *     ARGV           #=> []
    09725  *     ARGV.replace ["file2", "file3"]
    09726  *     ARGF.read      # Returns the contents of file2 and file3
    09727  *
    09728  * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
    09729  * piped to your script. For example:
    09730  *
    09731  *     $ echo "glark" | ruby -e 'p ARGF.read'
    09732  *     "glark\n"
    09733  */
    09734
    09735 /*
    09736  *  Class <code>IO</code> is the basis for all input and output in Ruby.
    09737  *  An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
    09738  *  so may use more than one native operating system stream.
    09739  *
    09740  *  Many of the examples in this section use class <code>File</code>,
    09741  *  the only standard subclass of <code>IO</code>. The two classes are
    09742  *  closely associated.
    09743  *
    09744  *  As used in this section, <em>portname</em> may take any of the
    09745  *  following forms.
    09746  *
    09747  *  * A plain string represents a filename suitable for the underlying
    09748  *    operating system.
    09749  *
    09750  *  * A string starting with ``<code>|</code>'' indicates a subprocess.
    09751  *    The remainder of the string following the ``<code>|</code>'' is
    09752  *    invoked as a process with appropriate input/output channels
    09753  *    connected to it.
    09754  *
    09755  *  * A string equal to ``<code>|-</code>'' will create another Ruby
    09756  *    instance as a subprocess.
    09757  *
    09758  *  Ruby will convert pathnames between different operating system
    09759  *  conventions if possible. For instance, on a Windows system the
    09760  *  filename ``<code>/gumby/ruby/test.rb</code>'' will be opened as
    09761  *  ``<code>\gumby\ruby\test.rb</code>''. When specifying a
    09762  *  Windows-style filename in a Ruby string, remember to escape the
    09763  *  backslashes:
    09764  *
    09765  *     "c:\\gumby\\ruby\\test.rb"
    09766  *
    09767  *  Our examples here will use the Unix-style forward slashes;
    09768  *  <code>File::SEPARATOR</code> can be used to get the
    09769  *  platform-specific separator character.
    09770  *
    09771  *  I/O ports may be opened in any one of several different modes, which
    09772  *  are shown in this section as <em>mode</em>. The mode may
    09773  *  either be a Fixnum or a String. If numeric, it should be
    09774  *  one of the operating system specific constants (O_RDONLY,
    09775  *  O_WRONLY, O_RDWR, O_APPEND and so on). See man open(2) for
    09776  *  more information.
    09777  *
    09778  *  If the mode is given as a String, it must be one of the
    09779  *  values listed in the following table.
    09780  *
    09781  *    Mode |  Meaning
    09782  *    -----+--------------------------------------------------------
    09783  *    "r"  |  Read-only, starts at beginning of file  (default mode).
    09784  *    -----+--------------------------------------------------------
    09785  *    "r+" |  Read-write, starts at beginning of file.
    09786  *    -----+--------------------------------------------------------
    09787  *    "w"  |  Write-only, truncates existing file
    09788  *         |  to zero length or creates a new file for writing.
    09789  *    -----+--------------------------------------------------------
    09790  *    "w+" |  Read-write, truncates existing file to zero length
    09791  *         |  or creates a new file for reading and writing.
    09792  *    -----+--------------------------------------------------------
    09793  *    "a"  |  Write-only, starts at end of file if file exists,
    09794  *         |  otherwise creates a new file for writing.
    09795  *    -----+--------------------------------------------------------
    09796  *    "a+" |  Read-write, starts at end of file if file exists,
    09797  *         |  otherwise creates a new file for reading and
    09798  *         |  writing.
    09799  *    -----+--------------------------------------------------------
    09800  *     "b" |  Binary file mode (may appear with
    09801  *         |  any of the key letters listed above).
    09802  *         |  Suppresses EOL <-> CRLF conversion on Windows. And
    09803  *         |  sets external encoding to ASCII-8BIT unless explicitly
    09804  *         |  specified.
    09805  *    -----+--------------------------------------------------------
    09806  *     "t" |  Text file mode (may appear with
    09807  *         |  any of the key letters listed above except "b").
    09808  *
    09809  *
    09810  *  The global constant ARGF (also accessible as $<) provides an
    09811  *  IO-like stream which allows access to all files mentioned on the
    09812  *  command line (or STDIN if no files are mentioned). ARGF provides
    09813  *  the methods <code>#path</code> and <code>#filename</code> to access
    09814  *  the name of the file currently being read.
    09815  */
    09816
    09817 void
    09818 Init_IO(void)
    09819 {
    09820 #undef rb_intern
    09821 #define rb_intern(str) rb_intern_const(str)
    09822
    09823     VALUE rb_cARGF;
    09824 #ifdef __CYGWIN__
    09825 #include <sys/cygwin.h>
    09826     static struct __cygwin_perfile pf[] =
    09827     {
    09828         {"", O_RDONLY | O_BINARY},
    09829         {"", O_WRONLY | O_BINARY},
    09830         {"", O_RDWR | O_BINARY},
    09831         {"", O_APPEND | O_BINARY},
    09832         {NULL, 0}
    09833     };
    09834     cygwin_internal(CW_PERFILE, pf);
    09835 #endif
    09836
    09837     rb_eIOError = rb_define_class("IOError", rb_eStandardError);
    09838     rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
    09839
    09840     id_write = rb_intern("write");
    09841     id_read = rb_intern("read");
    09842     id_getc = rb_intern("getc");
    09843     id_flush = rb_intern("flush");
    09844     id_readpartial = rb_intern("readpartial");
    09845     id_set_encoding = rb_intern("set_encoding");
    09846
    09847     rb_define_global_function("syscall", rb_f_syscall, -1);
    09848
    09849     rb_define_global_function("open", rb_f_open, -1);
    09850     rb_define_global_function("printf", rb_f_printf, -1);
    09851     rb_define_global_function("print", rb_f_print, -1);
    09852     rb_define_global_function("putc", rb_f_putc, 1);
    09853     rb_define_global_function("puts", rb_f_puts, -1);
    09854     rb_define_global_function("gets", rb_f_gets, -1);
    09855     rb_define_global_function("readline", rb_f_readline, -1);
    09856     rb_define_global_function("select", rb_f_select, -1);
    09857
    09858     rb_define_global_function("readlines", rb_f_readlines, -1);
    09859
    09860     rb_define_global_function("`", rb_f_backquote, 1);
    09861
    09862     rb_define_global_function("p", rb_f_p, -1);
    09863     rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
    09864
    09865     rb_cIO = rb_define_class("IO", rb_cObject);
    09866     rb_include_module(rb_cIO, rb_mEnumerable);
    09867
    09868     rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
    09869     rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
    09870
    09871 #if 0
    09872     /* This is necessary only for forcing rdoc handle File::open */
    09873     rb_define_singleton_method(rb_cFile, "open",  rb_io_s_open, -1);
    09874 #endif
    09875
    09876     rb_define_alloc_func(rb_cIO, io_alloc);
    09877     rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
    09878     rb_define_singleton_method(rb_cIO, "open",  rb_io_s_open, -1);
    09879     rb_define_singleton_method(rb_cIO, "sysopen",  rb_io_s_sysopen, -1);
    09880     rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
    09881     rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
    09882     rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
    09883     rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
    09884     rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
    09885     rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
    09886     rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
    09887     rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
    09888     rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
    09889     rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
    09890
    09891     rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
    09892
    09893     rb_output_fs = Qnil;
    09894     rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
    09895
    09896     rb_rs = rb_default_rs = rb_usascii_str_new2("\n");
    09897     rb_gc_register_mark_object(rb_default_rs);
    09898     rb_output_rs = Qnil;
    09899     OBJ_FREEZE(rb_default_rs);  /* avoid modifying RS_default */
    09900     rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
    09901     rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
    09902     rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
    09903
    09904     rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
    09905
    09906     rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
    09907     rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
    09908
    09909     rb_define_method(rb_cIO, "print", rb_io_print, -1);
    09910     rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
    09911     rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
    09912     rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
    09913
    09914     rb_define_method(rb_cIO, "each",  rb_io_each_line, -1);
    09915     rb_define_method(rb_cIO, "each_line",  rb_io_each_line, -1);
    09916     rb_define_method(rb_cIO, "each_byte",  rb_io_each_byte, 0);
    09917     rb_define_method(rb_cIO, "each_char",  rb_io_each_char, 0);
    09918     rb_define_method(rb_cIO, "each_codepoint",  rb_io_each_codepoint, 0);
    09919     rb_define_method(rb_cIO, "lines",  rb_io_each_line, -1);
    09920     rb_define_method(rb_cIO, "bytes",  rb_io_each_byte, 0);
    09921     rb_define_method(rb_cIO, "chars",  rb_io_each_char, 0);
    09922     rb_define_method(rb_cIO, "codepoints",  rb_io_each_codepoint, 0);
    09923
    09924     rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
    09925     rb_define_method(rb_cIO, "sysread",  rb_io_sysread, -1);
    09926
    09927     rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
    09928     rb_define_alias(rb_cIO, "to_i", "fileno");
    09929     rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
    09930
    09931     rb_define_method(rb_cIO, "fsync",   rb_io_fsync, 0);
    09932     rb_define_method(rb_cIO, "fdatasync",   rb_io_fdatasync, 0);
    09933     rb_define_method(rb_cIO, "sync",   rb_io_sync, 0);
    09934     rb_define_method(rb_cIO, "sync=",  rb_io_set_sync, 1);
    09935
    09936     rb_define_method(rb_cIO, "lineno",   rb_io_lineno, 0);
    09937     rb_define_method(rb_cIO, "lineno=",  rb_io_set_lineno, 1);
    09938
    09939     rb_define_method(rb_cIO, "readlines",  rb_io_readlines, -1);
    09940
    09941     rb_define_method(rb_cIO, "read_nonblock",  io_read_nonblock, -1);
    09942     rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
    09943     rb_define_method(rb_cIO, "readpartial",  io_readpartial, -1);
    09944     rb_define_method(rb_cIO, "read",  io_read, -1);
    09945     rb_define_method(rb_cIO, "write", io_write_m, 1);
    09946     rb_define_method(rb_cIO, "gets",  rb_io_gets_m, -1);
    09947     rb_define_method(rb_cIO, "readline",  rb_io_readline, -1);
    09948     rb_define_method(rb_cIO, "getc",  rb_io_getc, 0);
    09949     rb_define_method(rb_cIO, "getbyte",  rb_io_getbyte, 0);
    09950     rb_define_method(rb_cIO, "readchar",  rb_io_readchar, 0);
    09951     rb_define_method(rb_cIO, "readbyte",  rb_io_readbyte, 0);
    09952     rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
    09953     rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
    09954     rb_define_method(rb_cIO, "<<",    rb_io_addstr, 1);
    09955     rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
    09956     rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
    09957     rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
    09958     rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
    09959     rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
    09960     rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
    09961     rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
    09962     rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
    09963     rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
    09964     rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
    09965     rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
    09966
    09967     rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
    09968     rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
    09969
    09970     rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
    09971     rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
    09972     rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
    09973     rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
    09974
    09975     rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
    09976     rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
    09977     rb_define_method(rb_cIO, "binmode",  rb_io_binmode_m, 0);
    09978     rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
    09979     rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
    09980
    09981     rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
    09982     rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
    09983     rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
    09984     rb_define_method(rb_cIO, "inspect",  rb_io_inspect, 0);
    09985
    09986     rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
    09987     rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
    09988     rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
    09989
    09990     rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
    09991     rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
    09992
    09993     rb_define_variable("$stdin", &rb_stdin);
    09994     rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
    09995     rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
    09996     rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
    09997     rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
    09998     rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
    09999     rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
    10000     orig_stdout = rb_stdout;
    10001     rb_deferr = orig_stderr = rb_stderr;
    10002
    10003     /* constants to hold original stdin/stdout/stderr */
    10004     rb_define_global_const("STDIN", rb_stdin);
    10005     rb_define_global_const("STDOUT", rb_stdout);
    10006     rb_define_global_const("STDERR", rb_stderr);
    10007
    10008     /*
    10009      * Hack to get rdoc to regard ARGF as a class:
    10010      * rb_cARGF = rb_define_class("ARGF", rb_cObject);
    10011      */
    10012     rb_cARGF = rb_class_new(rb_cObject);
    10013     rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
    10014     rb_define_alloc_func(rb_cARGF, argf_alloc);
    10015
    10016     rb_include_module(rb_cARGF, rb_mEnumerable);
    10017
    10018     rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
    10019     rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
    10020     rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
    10021     rb_define_method(rb_cARGF, "argv", argf_argv, 0);
    10022
    10023     rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
    10024     rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
    10025     rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
    10026     rb_define_method(rb_cARGF, "each",  argf_each_line, -1);
    10027     rb_define_method(rb_cARGF, "each_line",  argf_each_line, -1);
    10028     rb_define_method(rb_cARGF, "each_byte",  argf_each_byte, 0);
    10029     rb_define_method(rb_cARGF, "each_char",  argf_each_char, 0);
    10030     rb_define_method(rb_cARGF, "lines", argf_each_line, -1);
    10031     rb_define_method(rb_cARGF, "bytes", argf_each_byte, 0);
    10032     rb_define_method(rb_cARGF, "chars", argf_each_char, 0);
    10033
    10034     rb_define_method(rb_cARGF, "read",  argf_read, -1);
    10035     rb_define_method(rb_cARGF, "readpartial",  argf_readpartial, -1);
    10036     rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
    10037     rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
    10038     rb_define_method(rb_cARGF, "gets", argf_gets, -1);
    10039     rb_define_method(rb_cARGF, "readline", argf_readline, -1);
    10040     rb_define_method(rb_cARGF, "getc", argf_getc, 0);
    10041     rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
    10042     rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
    10043     rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
    10044     rb_define_method(rb_cARGF, "tell", argf_tell, 0);
    10045     rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
    10046     rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
    10047     rb_define_method(rb_cARGF, "pos", argf_tell, 0);
    10048     rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
    10049     rb_define_method(rb_cARGF, "eof", argf_eof, 0);
    10050     rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
    10051     rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
    10052     rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
    10053
    10054     rb_define_method(rb_cARGF, "filename", argf_filename, 0);
    10055     rb_define_method(rb_cARGF, "path", argf_filename, 0);
    10056     rb_define_method(rb_cARGF, "file", argf_file, 0);
    10057     rb_define_method(rb_cARGF, "skip", argf_skip, 0);
    10058     rb_define_method(rb_cARGF, "close", argf_close_m, 0);
    10059     rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
    10060
    10061     rb_define_method(rb_cARGF, "lineno",   argf_lineno, 0);
    10062     rb_define_method(rb_cARGF, "lineno=",  argf_set_lineno, 1);
    10063
    10064     rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
    10065     rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
    10066
    10067     rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
    10068     rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
    10069     rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
    10070
    10071     argf = rb_class_new_instance(0, 0, rb_cARGF);
    10072
    10073     rb_define_readonly_variable("$<", &argf);
    10074     rb_define_global_const("ARGF", argf);
    10075
    10076     rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
    10077     rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
    10078     ARGF.filename = rb_str_new2("-");
    10079
    10080     rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
    10081     rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
    10082
    10083 #if defined (_WIN32) || defined(__CYGWIN__)
    10084     atexit(pipe_atexit);
    10085 #endif
    10086
    10087     Init_File();
    10088
    10089     rb_define_method(rb_cFile, "initialize",  rb_file_initialize, -1);
    10090
    10091     /* open for reading only */
    10092     rb_file_const("RDONLY", INT2FIX(O_RDONLY));
    10093     /* open for writing only */
    10094     rb_file_const("WRONLY", INT2FIX(O_WRONLY));
    10095     /* open for reading and writing */
    10096     rb_file_const("RDWR", INT2FIX(O_RDWR));
    10097     /* append on each write */
    10098     rb_file_const("APPEND", INT2FIX(O_APPEND));
    10099     /* create file if it does not exist */
    10100     rb_file_const("CREAT", INT2FIX(O_CREAT));
    10101     /* error if CREAT and the file exists */
    10102     rb_file_const("EXCL", INT2FIX(O_EXCL));
    10103 #if defined(O_NDELAY) || defined(O_NONBLOCK)
    10104 # ifndef O_NONBLOCK
    10105 #   define O_NONBLOCK O_NDELAY
    10106 # endif
    10107     /* do not block on open or for data to become available */
    10108     rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
    10109 #endif
    10110     /* truncate size to 0 */
    10111     rb_file_const("TRUNC", INT2FIX(O_TRUNC));
    10112 #ifdef O_NOCTTY
    10113     /* not to make opened IO the controlling terminal device */
    10114     rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
    10115 #endif
    10116 #ifndef O_BINARY
    10117 # define  O_BINARY 0
    10118 #endif
    10119     /* disable line code conversion and make ASCII-8BIT */
    10120     rb_file_const("BINARY", INT2FIX(O_BINARY));
    10121 #ifdef O_SYNC
    10122     rb_file_const("SYNC", INT2FIX(O_SYNC));
    10123 #endif
    10124 #ifdef O_DSYNC
    10125     rb_file_const("DSYNC", INT2FIX(O_DSYNC));
    10126 #endif
    10127 #ifdef O_RSYNC
    10128     rb_file_const("RSYNC", INT2FIX(O_RSYNC));
    10129 #endif
    10130 #ifdef O_NOFOLLOW
    10131     /* do not follow symlinks */
    10132     rb_file_const("NOFOLLOW", INT2FIX(O_NOFOLLOW)); /* FreeBSD, Linux */
    10133 #endif
    10134 #ifdef O_NOATIME
    10135     /* do not change atime */
    10136     rb_file_const("NOATIME", INT2FIX(O_NOATIME)); /* Linux */
    10137 #endif
    10138
    10139     sym_mode = ID2SYM(rb_intern("mode"));
    10140     sym_perm = ID2SYM(rb_intern("perm"));
    10141     sym_extenc = ID2SYM(rb_intern("external_encoding"));
    10142     sym_intenc = ID2SYM(rb_intern("internal_encoding"));
    10143     sym_encoding = ID2SYM(rb_intern("encoding"));
    10144     sym_open_args = ID2SYM(rb_intern("open_args"));
    10145     sym_textmode = ID2SYM(rb_intern("textmode"));
    10146     sym_binmode = ID2SYM(rb_intern("binmode"));
    10147     sym_autoclose = ID2SYM(rb_intern("autoclose"));
    10148 }
    10149