rename rb_pipe_internal to rb_pipe.
[ruby-svn.git] / io.c
blobcac73d784bf6971c33830fd4eb1f1c9dd08faf52
1 /**********************************************************************
3 io.c -
5 $Author$
6 created at: Fri Oct 15 18:08:59 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "ruby/ruby.h"
15 #include "ruby/io.h"
16 #include "ruby/signal.h"
17 #include "vm_core.h"
18 #include <ctype.h>
19 #include <errno.h>
21 #define free(x) xfree(x)
23 #if defined(DOSISH) || defined(__CYGWIN__)
24 #include <io.h>
25 #endif
27 #include <sys/types.h>
28 #if !defined(_WIN32) && !defined(__DJGPP__)
29 # if defined(__BEOS__)
30 # include <net/socket.h>
31 # else
32 # include <sys/socket.h>
33 # endif
34 #endif
36 #if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__) || defined(__BEOS__)
37 # define NO_SAFE_RENAME
38 #endif
40 #if defined(MSDOS) || defined(__CYGWIN__) || defined(_WIN32)
41 # define NO_LONG_FNAME
42 #endif
44 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(sun) || defined(_nec_ews)
45 # define USE_SETVBUF
46 #endif
48 #ifdef __QNXNTO__
49 #include "unix.h"
50 #endif
52 #include <sys/types.h>
53 #if defined(HAVE_SYS_IOCTL_H) && !defined(DJGPP) && !defined(_WIN32) && !defined(__human68k__)
54 #include <sys/ioctl.h>
55 #endif
56 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
57 #include <fcntl.h>
58 #elif defined(HAVE_SYS_FCNTL_H)
59 #include <sys/fcntl.h>
60 #endif
62 #if !HAVE_OFF_T && !defined(off_t)
63 # define off_t long
64 #endif
66 #include <sys/stat.h>
68 /* EMX has sys/param.h, but.. */
69 #if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
70 # include <sys/param.h>
71 #endif
73 #if !defined NOFILE
74 # define NOFILE 64
75 #endif
77 #ifdef HAVE_UNISTD_H
78 #include <unistd.h>
79 #endif
81 #ifdef HAVE_SYSCALL_H
82 #include <syscall.h>
83 #elif defined HAVE_SYS_SYSCALL_H
84 #include <sys/syscall.h>
85 #endif
87 extern void Init_File(void);
89 #ifdef __BEOS__
90 # ifndef NOFILE
91 # define NOFILE (OPEN_MAX)
92 # endif
93 #include <net/socket.h>
94 #endif
96 #include "ruby/util.h"
98 #ifndef O_ACCMODE
99 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
100 #endif
102 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
103 # error off_t is bigger than long, but you have no long long...
104 #endif
106 #ifndef PIPE_BUF
107 # ifdef _POSIX_PIPE_BUF
108 # define PIPE_BUF _POSIX_PIPE_BUF
109 # else
110 # define PIPE_BUF 512 /* is this ok? */
111 # endif
112 #endif
114 VALUE rb_cIO;
115 VALUE rb_eEOFError;
116 VALUE rb_eIOError;
118 VALUE rb_stdin, rb_stdout, rb_stderr;
119 VALUE rb_deferr; /* rescue VIM plugin */
120 static VALUE orig_stdout, orig_stderr;
122 VALUE rb_output_fs;
123 VALUE rb_rs;
124 VALUE rb_output_rs;
125 VALUE rb_default_rs;
127 static VALUE argf;
129 static ID id_write, id_read, id_getc, id_flush, id_encode, id_readpartial;
130 static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
132 struct timeval rb_time_interval(VALUE);
134 struct argf {
135 VALUE filename, current_file;
136 int gets_lineno;
137 int init_p, next_p;
138 VALUE lineno;
139 VALUE argv;
140 char *inplace;
141 int binmode;
142 rb_encoding *enc, *enc2;
145 static int max_file_descriptor = NOFILE;
146 #define UPDATE_MAXFD(fd) \
147 do { \
148 if (max_file_descriptor < (fd)) max_file_descriptor = (fd); \
149 } while (0)
151 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
152 #define ARGF argf_of(argf)
154 #ifdef _STDIO_USES_IOSTREAM /* GNU libc */
155 # ifdef _IO_fpos_t
156 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
157 # else
158 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
159 # endif
160 #elif defined(FILE_COUNT)
161 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
162 #elif defined(FILE_READEND)
163 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
164 #elif defined(__BEOS__)
165 # define STDIO_READ_DATA_PENDING(fp) (fp->_state._eof == 0)
166 #elif defined(__VMS)
167 # define STDIO_READ_DATA_PENDING(fp) (((unsigned int)(*(fp))->_cnt) > 0)
168 #else
169 # define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
170 #endif
172 #if defined(__VMS)
173 #define fopen(file_spec, mode) fopen(file_spec, mode, "rfm=stmlf")
174 #define open(file_spec, flags, mode) open(file_spec, flags, mode, "rfm=stmlf")
175 #endif
177 #define GetWriteIO(io) rb_io_get_write_io(io)
179 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf_len)
180 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf_len)
181 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off)
182 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
184 #define READ_CHECK(fptr) do {\
185 if (!READ_DATA_PENDING(fptr)) {\
186 rb_thread_wait_fd((fptr)->fd);\
187 rb_io_check_closed(fptr);\
189 } while(0)
191 #ifndef S_ISSOCK
192 # ifdef _S_ISSOCK
193 # define S_ISSOCK(m) _S_ISSOCK(m)
194 # else
195 # ifdef _S_IFSOCK
196 # define S_ISSOCK(m) ((m & S_IFMT) == _S_IFSOCK)
197 # else
198 # ifdef S_IFSOCK
199 # define S_ISSOCK(m) ((m & S_IFMT) == S_IFSOCK)
200 # endif
201 # endif
202 # endif
203 #endif
205 #if defined(_WIN32)
206 #define is_socket(fd, path) rb_w32_is_socket(fd)
207 #elif !defined(S_ISSOCK)
208 #define is_socket(fd, path) 0
209 #define shutdown(a,b) 0
210 #else
211 static int
212 is_socket(int fd, const char *path)
214 struct stat sbuf;
215 if (fstat(fd, &sbuf) < 0)
216 rb_sys_fail(path);
217 return S_ISSOCK(sbuf.st_mode);
219 #endif
221 void
222 rb_eof_error(void)
224 rb_raise(rb_eEOFError, "end of file reached");
227 VALUE
228 rb_io_taint_check(VALUE io)
230 if (!OBJ_TAINTED(io) && rb_safe_level() >= 4)
231 rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
232 rb_check_frozen(io);
233 return io;
236 void
237 rb_io_check_initialized(rb_io_t *fptr)
239 if (!fptr) {
240 rb_raise(rb_eIOError, "uninitialized stream");
244 void
245 rb_io_check_closed(rb_io_t *fptr)
247 rb_io_check_initialized(fptr);
248 if (fptr->fd < 0) {
249 rb_raise(rb_eIOError, "closed stream");
253 static int io_fflush(rb_io_t *);
255 VALUE
256 rb_io_get_io(VALUE io)
258 return rb_convert_type(io, T_FILE, "IO", "to_io");
261 static VALUE
262 rb_io_check_io(VALUE io)
264 return rb_check_convert_type(io, T_FILE, "IO", "to_io");
267 VALUE
268 rb_io_get_write_io(VALUE io)
270 VALUE write_io;
271 rb_io_check_initialized(RFILE(io)->fptr);
272 write_io = RFILE(io)->fptr->tied_io_for_writing;
273 if (write_io) {
274 return write_io;
276 return io;
280 * call-seq:
281 * IO.try_convert(obj) -> io or nil
283 * Try to convert <i>obj</i> into an IO, using to_io method.
284 * Returns converted IO or nil if <i>obj</i> cannot be converted
285 * for any reason.
287 * IO.try_convert(STDOUT) # => STDOUT
288 * IO.try_convert("STDOUT") # => nil
290 static VALUE
291 rb_io_s_try_convert(VALUE dummy, VALUE io)
293 return rb_io_check_io(io);
296 static void
297 io_unread(rb_io_t *fptr)
299 off_t r;
300 rb_io_check_closed(fptr);
301 if (fptr->rbuf_len == 0 || fptr->mode & FMODE_DUPLEX)
302 return;
303 /* xxx: target position may be negative if buffer is filled by ungetc */
304 #if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__)
305 if (!(fptr->mode & FMODE_BINMODE)) {
306 int len = fptr->rbuf_len;
307 while (fptr->rbuf_len-- > 0) {
308 if (fptr->rbuf[fptr->rbuf_len] == '\n')
309 ++len;
311 r = lseek(fptr->fd, -len, SEEK_CUR);
313 else
314 #endif
315 r = lseek(fptr->fd, -fptr->rbuf_len, SEEK_CUR);
316 if (r < 0) {
317 if (errno == ESPIPE)
318 fptr->mode |= FMODE_DUPLEX;
319 return;
321 fptr->rbuf_off = 0;
322 fptr->rbuf_len = 0;
323 return;
326 static void
327 io_ungetc(VALUE str, rb_io_t *fptr)
329 int len = RSTRING_LEN(str);
331 if (fptr->rbuf == NULL) {
332 fptr->rbuf_off = 0;
333 fptr->rbuf_len = 0;
334 if (len > 8192)
335 fptr->rbuf_capa = len;
336 else
337 fptr->rbuf_capa = 8192;
338 fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
340 if (fptr->rbuf_capa < len + fptr->rbuf_len) {
341 rb_raise(rb_eIOError, "ungetc failed");
343 if (fptr->rbuf_off < len) {
344 MEMMOVE(fptr->rbuf+fptr->rbuf_capa-fptr->rbuf_len,
345 fptr->rbuf+fptr->rbuf_off,
346 char, fptr->rbuf_len);
347 fptr->rbuf_off = fptr->rbuf_capa-fptr->rbuf_len;
349 fptr->rbuf_off-=len;
350 fptr->rbuf_len+=len;
351 MEMMOVE(fptr->rbuf+fptr->rbuf_off, RSTRING_PTR(str), char, len);
354 static rb_io_t *
355 flush_before_seek(rb_io_t *fptr)
357 io_fflush(fptr);
358 io_unread(fptr);
359 errno = 0;
360 return fptr;
363 #define io_seek(fptr, ofs, whence) lseek(flush_before_seek(fptr)->fd, ofs, whence)
364 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
366 #ifndef SEEK_CUR
367 # define SEEK_SET 0
368 # define SEEK_CUR 1
369 # define SEEK_END 2
370 #endif
372 #define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
374 void
375 rb_io_check_readable(rb_io_t *fptr)
377 rb_io_check_closed(fptr);
378 if (!(fptr->mode & FMODE_READABLE)) {
379 rb_raise(rb_eIOError, "not opened for reading");
381 if (fptr->wbuf_len) {
382 io_fflush(fptr);
384 if (fptr->tied_io_for_writing) {
385 rb_io_t *wfptr;
386 GetOpenFile(fptr->tied_io_for_writing, wfptr);
387 io_fflush(wfptr);
389 if (!fptr->enc && fptr->fd == 0) {
390 fptr->enc = rb_default_external_encoding();
394 static rb_encoding*
395 io_read_encoding(rb_io_t *fptr)
397 if (fptr->enc) {
398 return fptr->enc;
400 return rb_default_external_encoding();
403 static rb_encoding*
404 io_input_encoding(rb_io_t *fptr)
406 if (fptr->enc2) {
407 return fptr->enc2;
409 return io_read_encoding(fptr);
412 void
413 rb_io_check_writable(rb_io_t *fptr)
415 rb_io_check_closed(fptr);
416 if (!(fptr->mode & FMODE_WRITABLE)) {
417 rb_raise(rb_eIOError, "not opened for writing");
419 if (fptr->rbuf_len) {
420 io_unread(fptr);
425 rb_read_pending(FILE *fp)
427 return STDIO_READ_DATA_PENDING(fp);
431 rb_io_read_pending(rb_io_t *fptr)
433 return READ_DATA_PENDING(fptr);
436 void
437 rb_read_check(FILE *fp)
439 if (!STDIO_READ_DATA_PENDING(fp)) {
440 rb_thread_wait_fd(fileno(fp));
444 void
445 rb_io_read_check(rb_io_t *fptr)
447 if (!READ_DATA_PENDING(fptr)) {
448 rb_thread_wait_fd(fptr->fd);
450 return;
453 static int
454 ruby_dup(int orig)
456 int fd;
458 fd = dup(orig);
459 if (fd < 0) {
460 if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
461 rb_gc();
462 fd = dup(orig);
464 if (fd < 0) {
465 rb_sys_fail(0);
468 return fd;
471 static VALUE
472 io_alloc(VALUE klass)
474 NEWOBJ(io, struct RFile);
475 OBJSETUP(io, klass, T_FILE);
477 io->fptr = 0;
479 return (VALUE)io;
482 #ifndef S_ISREG
483 # define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
484 #endif
486 static int
487 wsplit_p(rb_io_t *fptr)
489 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
490 int r;
491 #endif
493 if (!(fptr->mode & FMODE_WSPLIT_INITIALIZED)) {
494 struct stat buf;
495 if (fstat(fptr->fd, &buf) == 0 &&
496 !S_ISREG(buf.st_mode)
497 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
498 && (r = fcntl(fptr->fd, F_GETFL)) != -1 &&
499 !(r & O_NONBLOCK)
500 #endif
502 fptr->mode |= FMODE_WSPLIT;
504 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
506 return fptr->mode & FMODE_WSPLIT;
509 struct io_internal_struct {
510 int fd;
511 void *buf;
512 size_t capa;
515 static VALUE
516 internal_read_func(void *ptr)
518 struct io_internal_struct *iis = (struct io_internal_struct*)ptr;
519 return read(iis->fd, iis->buf, iis->capa);
522 static VALUE
523 internal_write_func(void *ptr)
525 struct io_internal_struct *iis = (struct io_internal_struct*)ptr;
526 return write(iis->fd, iis->buf, iis->capa);
529 static int
530 rb_read_internal(int fd, void *buf, size_t count)
532 struct io_internal_struct iis;
533 iis.fd = fd;
534 iis.buf = buf;
535 iis.capa = count;
537 return rb_thread_blocking_region(internal_read_func, &iis, RB_UBF_DFL, 0);
540 static int
541 rb_write_internal(int fd, void *buf, size_t count)
543 struct io_internal_struct iis;
544 iis.fd = fd;
545 iis.buf = buf;
546 iis.capa = count;
548 return rb_thread_blocking_region(internal_write_func, &iis, RB_UBF_DFL, 0);
551 static int
552 io_fflush(rb_io_t *fptr)
554 int r, l;
555 int wbuf_off, wbuf_len;
557 rb_io_check_closed(fptr);
558 if (fptr->wbuf_len == 0)
559 return 0;
560 if (!rb_thread_fd_writable(fptr->fd)) {
561 rb_io_check_closed(fptr);
563 retry:
564 if (fptr->wbuf_len == 0)
565 return 0;
566 wbuf_off = fptr->wbuf_off;
567 wbuf_len = fptr->wbuf_len;
568 l = wbuf_len;
569 if (PIPE_BUF < l &&
570 !rb_thread_critical &&
571 !rb_thread_alone() &&
572 wsplit_p(fptr)) {
573 l = PIPE_BUF;
575 r = rb_write_internal(fptr->fd, fptr->wbuf+wbuf_off, l);
576 /* xxx: Other threads may modify wbuf.
577 * A lock is required, definitely. */
578 rb_io_check_closed(fptr);
579 if (fptr->wbuf_len <= r) {
580 fptr->wbuf_off = 0;
581 fptr->wbuf_len = 0;
582 return 0;
584 if (0 <= r) {
585 fptr->wbuf_off += r;
586 fptr->wbuf_len -= r;
587 errno = EAGAIN;
589 if (rb_io_wait_writable(fptr->fd)) {
590 rb_io_check_closed(fptr);
591 goto retry;
593 return -1;
596 #ifdef HAVE_RB_FD_INIT
597 static VALUE
598 wait_readable(VALUE p)
600 rb_fdset_t *rfds = (rb_fdset_t *)p;
602 return rb_thread_select(rb_fd_max(rfds), rb_fd_ptr(rfds), NULL, NULL, NULL);
604 #endif
607 rb_io_wait_readable(int f)
609 rb_fdset_t rfds;
611 switch (errno) {
612 case EINTR:
613 #if defined(ERESTART)
614 case ERESTART:
615 #endif
616 rb_thread_wait_fd(f);
617 return Qtrue;
619 case EAGAIN:
620 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
621 case EWOULDBLOCK:
622 #endif
623 rb_fd_init(&rfds);
624 rb_fd_set(f, &rfds);
625 #ifdef HAVE_RB_FD_INIT
626 rb_ensure(wait_readable, (VALUE)&rfds,
627 (VALUE (*)(VALUE))rb_fd_term, (VALUE)&rfds);
628 #else
629 rb_thread_select(f + 1, &rfds, NULL, NULL, NULL);
630 #endif
631 return Qtrue;
633 default:
634 return Qfalse;
638 #ifdef HAVE_RB_FD_INIT
639 static VALUE
640 wait_writable(VALUE p)
642 rb_fdset_t *wfds = (rb_fdset_t *)p;
644 return rb_thread_select(rb_fd_max(wfds), NULL, rb_fd_ptr(wfds), NULL, NULL);
646 #endif
649 rb_io_wait_writable(int f)
651 rb_fdset_t wfds;
653 switch (errno) {
654 case EINTR:
655 #if defined(ERESTART)
656 case ERESTART:
657 #endif
658 rb_thread_fd_writable(f);
659 return Qtrue;
661 case EAGAIN:
662 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
663 case EWOULDBLOCK:
664 #endif
665 rb_fd_init(&wfds);
666 rb_fd_set(f, &wfds);
667 #ifdef HAVE_RB_FD_INIT
668 rb_ensure(wait_writable, (VALUE)&wfds,
669 (VALUE (*)(VALUE))rb_fd_term, (VALUE)&wfds);
670 #else
671 rb_thread_select(f + 1, NULL, &wfds, NULL, NULL);
672 #endif
673 return Qtrue;
675 default:
676 return Qfalse;
680 /* writing functions */
681 static long
682 io_fwrite(VALUE str, rb_io_t *fptr)
684 long len, n, r, l, offset = 0;
687 * If an external encoding was specified and it differs from
688 * the strings encoding then we must transcode before writing.
689 * We must also transcode if two encodings were specified
691 if (fptr->enc) {
692 /* transcode str before output */
693 /* the methods in transcode.c are static, so call indirectly */
694 /* Can't use encode! because puts writes a frozen newline */
695 if (fptr->enc2) {
696 str = rb_funcall(str, id_encode, 2,
697 rb_enc_from_encoding(fptr->enc2),
698 rb_enc_from_encoding(fptr->enc));
700 else {
701 str = rb_funcall(str, id_encode, 1,
702 rb_enc_from_encoding(fptr->enc));
706 len = RSTRING_LEN(str);
707 if ((n = len) <= 0) return n;
708 if (fptr->wbuf == NULL && !(fptr->mode & FMODE_SYNC)) {
709 fptr->wbuf_off = 0;
710 fptr->wbuf_len = 0;
711 fptr->wbuf_capa = 8192;
712 fptr->wbuf = ALLOC_N(char, fptr->wbuf_capa);
714 if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) ||
715 (fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len)) {
716 /* xxx: use writev to avoid double write if available */
717 if (fptr->wbuf_len && fptr->wbuf_len+len <= fptr->wbuf_capa) {
718 if (fptr->wbuf_capa < fptr->wbuf_off+fptr->wbuf_len+len) {
719 MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len);
720 fptr->wbuf_off = 0;
722 MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING_PTR(str)+offset, char, len);
723 fptr->wbuf_len += len;
724 n = 0;
726 if (io_fflush(fptr) < 0)
727 return -1L;
728 if (n == 0)
729 return len;
730 /* avoid context switch between "a" and "\n" in STDERR.puts "a".
731 [ruby-dev:25080] */
732 if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) {
733 rb_io_check_closed(fptr);
735 retry:
736 l = n;
737 if (PIPE_BUF < l &&
738 !rb_thread_critical &&
739 !rb_thread_alone() &&
740 wsplit_p(fptr)) {
741 l = PIPE_BUF;
743 r = rb_write_internal(fptr->fd, RSTRING_PTR(str)+offset, l);
744 /* xxx: other threads may modify given string. */
745 if (r == n) return len;
746 if (0 <= r) {
747 offset += r;
748 n -= r;
749 errno = EAGAIN;
751 if (rb_io_wait_writable(fptr->fd)) {
752 rb_io_check_closed(fptr);
753 if (offset < RSTRING_LEN(str))
754 goto retry;
756 return -1L;
759 if (fptr->wbuf_off) {
760 if (fptr->wbuf_len)
761 MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len);
762 fptr->wbuf_off = 0;
764 MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING_PTR(str)+offset, char, len);
765 fptr->wbuf_len += len;
766 return len;
769 long
770 rb_io_fwrite(const char *ptr, long len, FILE *f)
772 rb_io_t of;
774 of.fd = fileno(f);
775 of.stdio_file = f;
776 of.mode = FMODE_WRITABLE;
777 of.path = NULL;
778 return io_fwrite(rb_str_new(ptr, len), &of);
782 * call-seq:
783 * ios.write(string) => integer
785 * Writes the given string to <em>ios</em>. The stream must be opened
786 * for writing. If the argument is not a string, it will be converted
787 * to a string using <code>to_s</code>. Returns the number of bytes
788 * written.
790 * count = $stdout.write( "This is a test\n" )
791 * puts "That was #{count} bytes of data"
793 * <em>produces:</em>
795 * This is a test
796 * That was 15 bytes of data
799 static VALUE
800 io_write(VALUE io, VALUE str)
802 rb_io_t *fptr;
803 long n;
804 VALUE tmp;
806 rb_secure(4);
807 io = GetWriteIO(io);
808 str = rb_obj_as_string(str);
809 tmp = rb_io_check_io(io);
810 if (NIL_P(tmp)) {
811 /* port is not IO, call write method for it. */
812 return rb_funcall(io, id_write, 1, str);
814 io = tmp;
815 if (RSTRING_LEN(str) == 0) return INT2FIX(0);
817 GetOpenFile(io, fptr);
818 rb_io_check_writable(fptr);
820 n = io_fwrite(str, fptr);
821 if (n == -1L) rb_sys_fail(fptr->path);
823 return LONG2FIX(n);
826 VALUE
827 rb_io_write(VALUE io, VALUE str)
829 return rb_funcall(io, id_write, 1, str);
833 * call-seq:
834 * ios << obj => ios
836 * String Output---Writes <i>obj</i> to <em>ios</em>.
837 * <i>obj</i> will be converted to a string using
838 * <code>to_s</code>.
840 * $stdout << "Hello " << "world!\n"
842 * <em>produces:</em>
844 * Hello world!
848 VALUE
849 rb_io_addstr(VALUE io, VALUE str)
851 rb_io_write(io, str);
852 return io;
856 * call-seq:
857 * ios.flush => ios
859 * Flushes any buffered data within <em>ios</em> to the underlying
860 * operating system (note that this is Ruby internal buffering only;
861 * the OS may buffer the data as well).
863 * $stdout.print "no newline"
864 * $stdout.flush
866 * <em>produces:</em>
868 * no newline
871 VALUE
872 rb_io_flush(VALUE io)
874 rb_io_t *fptr;
876 if (TYPE(io) != T_FILE) {
877 return rb_funcall(io, id_flush, 0);
880 io = GetWriteIO(io);
881 GetOpenFile(io, fptr);
883 if (fptr->mode & FMODE_WRITABLE) {
884 io_fflush(fptr);
886 if (fptr->mode & FMODE_READABLE) {
887 io_unread(fptr);
890 return io;
894 * call-seq:
895 * ios.pos => integer
896 * ios.tell => integer
898 * Returns the current offset (in bytes) of <em>ios</em>.
900 * f = File.new("testfile")
901 * f.pos #=> 0
902 * f.gets #=> "This is line one\n"
903 * f.pos #=> 17
906 static VALUE
907 rb_io_tell(VALUE io)
909 rb_io_t *fptr;
910 off_t pos;
912 GetOpenFile(io, fptr);
913 pos = io_tell(fptr);
914 if (pos < 0 && errno) rb_sys_fail(fptr->path);
915 return OFFT2NUM(pos);
918 static VALUE
919 rb_io_seek(VALUE io, VALUE offset, int whence)
921 rb_io_t *fptr;
922 off_t pos;
924 pos = NUM2OFFT(offset);
925 GetOpenFile(io, fptr);
926 pos = io_seek(fptr, pos, whence);
927 if (pos < 0 && errno) rb_sys_fail(fptr->path);
929 return INT2FIX(0);
933 * call-seq:
934 * ios.seek(amount, whence=SEEK_SET) -> 0
936 * Seeks to a given offset <i>anInteger</i> in the stream according to
937 * the value of <i>whence</i>:
939 * IO::SEEK_CUR | Seeks to _amount_ plus current position
940 * --------------+----------------------------------------------------
941 * IO::SEEK_END | Seeks to _amount_ plus end of stream (you probably
942 * | want a negative value for _amount_)
943 * --------------+----------------------------------------------------
944 * IO::SEEK_SET | Seeks to the absolute location given by _amount_
946 * Example:
948 * f = File.new("testfile")
949 * f.seek(-13, IO::SEEK_END) #=> 0
950 * f.readline #=> "And so on...\n"
953 static VALUE
954 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
956 VALUE offset, ptrname;
957 int whence = SEEK_SET;
959 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
960 whence = NUM2INT(ptrname);
963 return rb_io_seek(io, offset, whence);
967 * call-seq:
968 * ios.pos = integer => integer
970 * Seeks to the given position (in bytes) in <em>ios</em>.
972 * f = File.new("testfile")
973 * f.pos = 17
974 * f.gets #=> "This is line two\n"
977 static VALUE
978 rb_io_set_pos(VALUE io, VALUE offset)
980 rb_io_t *fptr;
981 off_t pos;
983 pos = NUM2OFFT(offset);
984 GetOpenFile(io, fptr);
985 pos = io_seek(fptr, pos, SEEK_SET);
986 if (pos < 0) rb_sys_fail(fptr->path);
988 return OFFT2NUM(pos);
992 * call-seq:
993 * ios.rewind => 0
995 * Positions <em>ios</em> to the beginning of input, resetting
996 * <code>lineno</code> to zero.
998 * f = File.new("testfile")
999 * f.readline #=> "This is line one\n"
1000 * f.rewind #=> 0
1001 * f.lineno #=> 0
1002 * f.readline #=> "This is line one\n"
1005 static VALUE
1006 rb_io_rewind(VALUE io)
1008 rb_io_t *fptr;
1010 GetOpenFile(io, fptr);
1011 if (io_seek(fptr, 0L, 0) < 0) rb_sys_fail(fptr->path);
1012 if (io == ARGF.current_file) {
1013 ARGF.gets_lineno -= fptr->lineno;
1015 fptr->lineno = 0;
1017 return INT2FIX(0);
1020 static int
1021 io_fillbuf(rb_io_t *fptr)
1023 int r;
1025 if (fptr->rbuf == NULL) {
1026 fptr->rbuf_off = 0;
1027 fptr->rbuf_len = 0;
1028 fptr->rbuf_capa = 8192;
1029 fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
1031 if (fptr->rbuf_len == 0) {
1032 retry:
1034 r = rb_read_internal(fptr->fd, fptr->rbuf, fptr->rbuf_capa);
1036 if (r < 0) {
1037 if (rb_io_wait_readable(fptr->fd))
1038 goto retry;
1039 rb_sys_fail(fptr->path);
1041 fptr->rbuf_off = 0;
1042 fptr->rbuf_len = r;
1043 if (r == 0)
1044 return -1; /* EOF */
1046 return 0;
1050 * call-seq:
1051 * ios.eof => true or false
1052 * ios.eof? => true or false
1054 * Returns true if <em>ios</em> is at end of file that means
1055 * there are no more data to read.
1056 * The stream must be opened for reading or an <code>IOError</code> will be
1057 * raised.
1059 * f = File.new("testfile")
1060 * dummy = f.readlines
1061 * f.eof #=> true
1063 * If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
1064 * blocks until the other end sends some data or closes it.
1066 * r, w = IO.pipe
1067 * Thread.new { sleep 1; w.close }
1068 * r.eof? #=> true after 1 second blocking
1070 * r, w = IO.pipe
1071 * Thread.new { sleep 1; w.puts "a" }
1072 * r.eof? #=> false after 1 second blocking
1074 * r, w = IO.pipe
1075 * r.eof? # blocks forever
1077 * Note that <code>IO#eof?</code> reads data to a input buffer.
1078 * So <code>IO#sysread</code> doesn't work with <code>IO#eof?</code>.
1081 VALUE
1082 rb_io_eof(VALUE io)
1084 rb_io_t *fptr;
1086 GetOpenFile(io, fptr);
1087 rb_io_check_readable(fptr);
1089 if (READ_DATA_PENDING(fptr)) return Qfalse;
1090 READ_CHECK(fptr);
1091 if (io_fillbuf(fptr) < 0) {
1092 return Qtrue;
1094 return Qfalse;
1098 * call-seq:
1099 * ios.sync => true or false
1101 * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
1102 * true, all output is immediately flushed to the underlying operating
1103 * system and is not buffered by Ruby internally. See also
1104 * <code>IO#fsync</code>.
1106 * f = File.new("testfile")
1107 * f.sync #=> false
1110 static VALUE
1111 rb_io_sync(VALUE io)
1113 rb_io_t *fptr;
1115 io = GetWriteIO(io);
1116 GetOpenFile(io, fptr);
1117 return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
1121 * call-seq:
1122 * ios.sync = boolean => boolean
1124 * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
1125 * When sync mode is true, all output is immediately flushed to the
1126 * underlying operating system and is not buffered internally. Returns
1127 * the new state. See also <code>IO#fsync</code>.
1129 * f = File.new("testfile")
1130 * f.sync = true
1132 * <em>(produces no output)</em>
1135 static VALUE
1136 rb_io_set_sync(VALUE io, VALUE mode)
1138 rb_io_t *fptr;
1140 io = GetWriteIO(io);
1141 GetOpenFile(io, fptr);
1142 if (RTEST(mode)) {
1143 fptr->mode |= FMODE_SYNC;
1145 else {
1146 fptr->mode &= ~FMODE_SYNC;
1148 return mode;
1152 * call-seq:
1153 * ios.fsync => 0 or nil
1155 * Immediately writes all buffered data in <em>ios</em> to disk.
1156 * Returns <code>nil</code> if the underlying operating system does not
1157 * support <em>fsync(2)</em>. Note that <code>fsync</code> differs from
1158 * using <code>IO#sync=</code>. The latter ensures that data is flushed
1159 * from Ruby's buffers, but doesn't not guarantee that the underlying
1160 * operating system actually writes it to disk.
1163 static VALUE
1164 rb_io_fsync(VALUE io)
1166 #ifdef HAVE_FSYNC
1167 rb_io_t *fptr;
1169 io = GetWriteIO(io);
1170 GetOpenFile(io, fptr);
1172 io_fflush(fptr);
1173 if (fsync(fptr->fd) < 0)
1174 rb_sys_fail(fptr->path);
1175 return INT2FIX(0);
1176 #else
1177 rb_notimplement();
1178 return Qnil; /* not reached */
1179 #endif
1183 * call-seq:
1184 * ios.fileno => fixnum
1185 * ios.to_i => fixnum
1187 * Returns an integer representing the numeric file descriptor for
1188 * <em>ios</em>.
1190 * $stdin.fileno #=> 0
1191 * $stdout.fileno #=> 1
1194 static VALUE
1195 rb_io_fileno(VALUE io)
1197 rb_io_t *fptr;
1198 int fd;
1200 GetOpenFile(io, fptr);
1201 fd = fptr->fd;
1202 return INT2FIX(fd);
1207 * call-seq:
1208 * ios.pid => fixnum
1210 * Returns the process ID of a child process associated with
1211 * <em>ios</em>. This will be set by <code>IO::popen</code>.
1213 * pipe = IO.popen("-")
1214 * if pipe
1215 * $stderr.puts "In parent, child pid is #{pipe.pid}"
1216 * else
1217 * $stderr.puts "In child, pid is #{$$}"
1218 * end
1220 * <em>produces:</em>
1222 * In child, pid is 26209
1223 * In parent, child pid is 26209
1226 static VALUE
1227 rb_io_pid(VALUE io)
1229 rb_io_t *fptr;
1231 GetOpenFile(io, fptr);
1232 if (!fptr->pid)
1233 return Qnil;
1234 return INT2FIX(fptr->pid);
1239 * call-seq:
1240 * ios.inspect => string
1242 * Return a string describing this IO object.
1245 static VALUE
1246 rb_io_inspect(VALUE obj)
1248 rb_io_t *fptr;
1249 const char *cname;
1250 const char *st = "";
1252 fptr = RFILE(rb_io_taint_check(obj))->fptr;
1253 if (!fptr || !fptr->path) return rb_any_to_s(obj);
1254 cname = rb_obj_classname(obj);
1255 if (fptr->fd < 0) {
1256 st = " (closed)";
1258 return rb_sprintf("#<%s:%s%s>", cname, fptr->path, st);
1262 * call-seq:
1263 * ios.to_io -> ios
1265 * Returns <em>ios</em>.
1268 static VALUE
1269 rb_io_to_io(VALUE io)
1271 return io;
1274 /* reading functions */
1275 static long
1276 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
1278 long n;
1280 n = READ_DATA_PENDING_COUNT(fptr);
1281 if (n <= 0) return 0;
1282 if (n > len) n = len;
1283 MEMMOVE(ptr, fptr->rbuf+fptr->rbuf_off, char, n);
1284 fptr->rbuf_off += n;
1285 fptr->rbuf_len -= n;
1286 return n;
1289 static long
1290 io_fread(VALUE str, long offset, rb_io_t *fptr)
1292 long len = RSTRING_LEN(str) - offset;
1293 long n = len;
1294 int c;
1296 if (READ_DATA_PENDING(fptr) == 0) {
1297 while (n > 0) {
1298 c = rb_read_internal(fptr->fd, RSTRING_PTR(str)+offset, n);
1299 if (c == 0) break;
1300 if (c < 0) {
1301 rb_sys_fail(fptr->path);
1303 offset += c;
1304 if ((n -= c) <= 0) break;
1305 rb_thread_wait_fd(fptr->fd);
1307 return len - n;
1310 while (n > 0) {
1311 c = read_buffered_data(RSTRING_PTR(str)+offset, n, fptr);
1312 if (c > 0) {
1313 offset += c;
1314 if ((n -= c) <= 0) break;
1316 rb_thread_wait_fd(fptr->fd);
1317 rb_io_check_closed(fptr);
1318 if (io_fillbuf(fptr) < 0) {
1319 break;
1322 return len - n;
1325 long
1326 rb_io_fread(char *ptr, long len, FILE *f)
1328 rb_io_t of;
1329 VALUE str;
1330 long n;
1332 of.fd = fileno(f);
1333 of.stdio_file = f;
1334 of.mode = FMODE_READABLE;
1335 str = rb_str_new(ptr, len);
1336 n = io_fread(str, 0, &of);
1337 MEMCPY(ptr, RSTRING_PTR(str), char, n);
1338 return n;
1341 #define SMALLBUF 100
1343 static long
1344 remain_size(rb_io_t *fptr)
1346 struct stat st;
1347 off_t siz = READ_DATA_PENDING_COUNT(fptr);
1348 off_t pos;
1350 if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
1351 #ifdef __BEOS__
1352 && (st.st_dev > 3)
1353 #endif
1356 io_fflush(fptr);
1357 pos = lseek(fptr->fd, 0, SEEK_CUR);
1358 if (st.st_size >= pos && pos >= 0) {
1359 siz += st.st_size - pos;
1360 if (siz > LONG_MAX) {
1361 rb_raise(rb_eIOError, "file too big for single read");
1365 else {
1366 siz += BUFSIZ;
1368 return (long)siz;
1371 static VALUE
1372 io_enc_str(VALUE str, rb_io_t *fptr)
1374 OBJ_TAINT(str);
1375 if (fptr->enc2) {
1376 /* two encodings, so transcode from enc2 to enc */
1377 /* the methods in transcode.c are static, so call indirectly */
1378 str = rb_funcall(str, id_encode, 2,
1379 rb_enc_from_encoding(fptr->enc),
1380 rb_enc_from_encoding(fptr->enc2));
1382 else {
1383 /* just one encoding, so associate it with the string */
1384 rb_enc_associate(str, io_read_encoding(fptr));
1386 return str;
1389 static VALUE
1390 read_all(rb_io_t *fptr, long siz, VALUE str)
1392 long bytes = 0;
1393 long n;
1394 long pos = 0;
1395 rb_encoding *enc = io_read_encoding(fptr);
1396 int cr = fptr->enc2 ? ENC_CODERANGE_BROKEN : 0;
1398 if (siz == 0) siz = BUFSIZ;
1399 if (NIL_P(str)) {
1400 str = rb_str_new(0, siz);
1402 else {
1403 rb_str_resize(str, siz);
1405 for (;;) {
1406 READ_CHECK(fptr);
1407 n = io_fread(str, bytes, fptr);
1408 if (n == 0 && bytes == 0) {
1409 break;
1411 bytes += n;
1412 if (cr != ENC_CODERANGE_BROKEN)
1413 pos = rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
1414 if (bytes < siz) break;
1415 siz += BUFSIZ;
1416 rb_str_resize(str, siz);
1418 if (bytes != siz) rb_str_resize(str, bytes);
1419 str = io_enc_str(str, fptr);
1420 if (!fptr->enc2) {
1421 ENC_CODERANGE_SET(str, cr);
1423 return str;
1426 void
1427 rb_io_set_nonblock(rb_io_t *fptr)
1429 int flags;
1430 #ifdef F_GETFL
1431 flags = fcntl(fptr->fd, F_GETFL);
1432 if (flags == -1) {
1433 rb_sys_fail(fptr->path);
1435 #else
1436 flags = 0;
1437 #endif
1438 if ((flags & O_NONBLOCK) == 0) {
1439 flags |= O_NONBLOCK;
1440 if (fcntl(fptr->fd, F_SETFL, flags) == -1) {
1441 rb_sys_fail(fptr->path);
1446 static VALUE
1447 io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
1449 rb_io_t *fptr;
1450 VALUE length, str;
1451 long n, len;
1453 rb_scan_args(argc, argv, "11", &length, &str);
1455 if ((len = NUM2LONG(length)) < 0) {
1456 rb_raise(rb_eArgError, "negative length %ld given", len);
1459 if (NIL_P(str)) {
1460 str = rb_str_new(0, len);
1462 else {
1463 StringValue(str);
1464 rb_str_modify(str);
1465 rb_str_resize(str, len);
1467 OBJ_TAINT(str);
1469 GetOpenFile(io, fptr);
1470 rb_io_check_readable(fptr);
1472 if (len == 0)
1473 return str;
1475 if (!nonblock)
1476 READ_CHECK(fptr);
1477 if (RSTRING_LEN(str) != len) {
1478 modified:
1479 rb_raise(rb_eRuntimeError, "buffer string modified");
1481 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
1482 if (n <= 0) {
1483 again:
1484 if (RSTRING_LEN(str) != len) goto modified;
1485 if (nonblock) {
1486 rb_io_set_nonblock(fptr);
1487 n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
1489 else {
1490 n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
1492 if (n < 0) {
1493 if (!nonblock && rb_io_wait_readable(fptr->fd))
1494 goto again;
1495 rb_sys_fail(fptr->path);
1498 rb_str_resize(str, n);
1500 if (n == 0)
1501 return Qnil;
1502 else
1503 return str;
1507 * call-seq:
1508 * ios.readpartial(maxlen) => string
1509 * ios.readpartial(maxlen, outbuf) => outbuf
1511 * Reads at most <i>maxlen</i> bytes from the I/O stream.
1512 * It blocks only if <em>ios</em> has no data immediately available.
1513 * It doesn't block if some data available.
1514 * If the optional <i>outbuf</i> argument is present,
1515 * it must reference a String, which will receive the data.
1516 * It raises <code>EOFError</code> on end of file.
1518 * readpartial is designed for streams such as pipe, socket, tty, etc.
1519 * It blocks only when no data immediately available.
1520 * This means that it blocks only when following all conditions hold.
1521 * * the buffer in the IO object is empty.
1522 * * the content of the stream is empty.
1523 * * the stream is not reached to EOF.
1525 * When readpartial blocks, it waits data or EOF on the stream.
1526 * If some data is reached, readpartial returns with the data.
1527 * If EOF is reached, readpartial raises EOFError.
1529 * When readpartial doesn't blocks, it returns or raises immediately.
1530 * If the buffer is not empty, it returns the data in the buffer.
1531 * Otherwise if the stream has some content,
1532 * it returns the data in the stream.
1533 * Otherwise if the stream is reached to EOF, it raises EOFError.
1535 * r, w = IO.pipe # buffer pipe content
1536 * w << "abc" # "" "abc".
1537 * r.readpartial(4096) #=> "abc" "" ""
1538 * r.readpartial(4096) # blocks because buffer and pipe is empty.
1540 * r, w = IO.pipe # buffer pipe content
1541 * w << "abc" # "" "abc"
1542 * w.close # "" "abc" EOF
1543 * r.readpartial(4096) #=> "abc" "" EOF
1544 * r.readpartial(4096) # raises EOFError
1546 * r, w = IO.pipe # buffer pipe content
1547 * w << "abc\ndef\n" # "" "abc\ndef\n"
1548 * r.gets #=> "abc\n" "def\n" ""
1549 * w << "ghi\n" # "def\n" "ghi\n"
1550 * r.readpartial(4096) #=> "def\n" "" "ghi\n"
1551 * r.readpartial(4096) #=> "ghi\n" "" ""
1553 * Note that readpartial behaves similar to sysread.
1554 * The differences are:
1555 * * If the buffer is not empty, read from the buffer instead of "sysread for buffered IO (IOError)".
1556 * * It doesn't cause Errno::EAGAIN and Errno::EINTR. When readpartial meets EAGAIN and EINTR by read system call, readpartial retry the system call.
1558 * The later means that readpartial is nonblocking-flag insensitive.
1559 * It blocks on the situation IO#sysread causes Errno::EAGAIN as if the fd is blocking mode.
1563 static VALUE
1564 io_readpartial(int argc, VALUE *argv, VALUE io)
1566 VALUE ret;
1568 ret = io_getpartial(argc, argv, io, 0);
1569 if (NIL_P(ret))
1570 rb_eof_error();
1571 else
1572 return ret;
1576 * call-seq:
1577 * ios.read_nonblock(maxlen) => string
1578 * ios.read_nonblock(maxlen, outbuf) => outbuf
1580 * Reads at most <i>maxlen</i> bytes from <em>ios</em> using
1581 * read(2) system call after O_NONBLOCK is set for
1582 * the underlying file descriptor.
1584 * If the optional <i>outbuf</i> argument is present,
1585 * it must reference a String, which will receive the data.
1587 * read_nonblock just calls read(2).
1588 * It causes all errors read(2) causes: EAGAIN, EINTR, etc.
1589 * The caller should care such errors.
1591 * read_nonblock causes EOFError on EOF.
1593 * If the read buffer is not empty,
1594 * read_nonblock reads from the buffer like readpartial.
1595 * In this case, read(2) is not called.
1599 static VALUE
1600 io_read_nonblock(int argc, VALUE *argv, VALUE io)
1602 VALUE ret;
1604 ret = io_getpartial(argc, argv, io, 1);
1605 if (NIL_P(ret))
1606 rb_eof_error();
1607 else
1608 return ret;
1612 * call-seq:
1613 * ios.write_nonblock(string) => integer
1615 * Writes the given string to <em>ios</em> using
1616 * write(2) system call after O_NONBLOCK is set for
1617 * the underlying file descriptor.
1619 * write_nonblock just calls write(2).
1620 * It causes all errors write(2) causes: EAGAIN, EINTR, etc.
1621 * The result may also be smaller than string.length (partial write).
1622 * The caller should care such errors and partial write.
1624 * If the write buffer is not empty, it is flushed at first.
1628 static VALUE
1629 rb_io_write_nonblock(VALUE io, VALUE str)
1631 rb_io_t *fptr;
1632 long n;
1634 rb_secure(4);
1635 if (TYPE(str) != T_STRING)
1636 str = rb_obj_as_string(str);
1638 io = GetWriteIO(io);
1639 GetOpenFile(io, fptr);
1640 rb_io_check_writable(fptr);
1642 io_fflush(fptr);
1644 rb_io_set_nonblock(fptr);
1645 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
1647 if (n == -1) rb_sys_fail(fptr->path);
1649 return LONG2FIX(n);
1653 * call-seq:
1654 * ios.read([length [, buffer]]) => string, buffer, or nil
1656 * Reads at most <i>length</i> bytes from the I/O stream, or to the
1657 * end of file if <i>length</i> is omitted or is <code>nil</code>.
1658 * <i>length</i> must be a non-negative integer or nil.
1659 * If the optional <i>buffer</i> argument is present, it must reference
1660 * a String, which will receive the data.
1662 * At end of file, it returns <code>nil</code> or <code>""</code>
1663 * depend on <i>length</i>.
1664 * <code><i>ios</i>.read()</code> and
1665 * <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
1666 * <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns nil.
1668 * <code><i>ios</i>.read(0)</code> returns <code>""</code>.
1670 * f = File.new("testfile")
1671 * f.read(16) #=> "This is line one"
1674 static VALUE
1675 io_read(int argc, VALUE *argv, VALUE io)
1677 rb_io_t *fptr;
1678 long n, len;
1679 VALUE length, str;
1681 rb_scan_args(argc, argv, "02", &length, &str);
1683 if (NIL_P(length)) {
1684 if (!NIL_P(str)) StringValue(str);
1685 GetOpenFile(io, fptr);
1686 rb_io_check_readable(fptr);
1687 return read_all(fptr, remain_size(fptr), str);
1689 len = NUM2LONG(length);
1690 if (len < 0) {
1691 rb_raise(rb_eArgError, "negative length %ld given", len);
1694 if (NIL_P(str)) {
1695 str = rb_str_new(0, len);
1697 else {
1698 StringValue(str);
1699 rb_str_modify(str);
1700 rb_str_resize(str,len);
1703 GetOpenFile(io, fptr);
1704 rb_io_check_readable(fptr);
1705 if (len == 0) return str;
1707 READ_CHECK(fptr);
1708 if (RSTRING_LEN(str) != len) {
1709 rb_raise(rb_eRuntimeError, "buffer string modified");
1711 n = io_fread(str, 0, fptr);
1712 if (n == 0) {
1713 if (fptr->fd < 0) return Qnil;
1714 rb_str_resize(str, 0);
1715 return Qnil;
1717 rb_str_resize(str, n);
1719 return str;
1722 static void
1723 rscheck(const char *rsptr, long rslen, VALUE rs)
1725 if (!rs) return;
1726 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
1727 rb_raise(rb_eRuntimeError, "rs modified");
1730 static int
1731 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
1733 VALUE str = *strp;
1734 int c = EOF;
1735 long limit = *lp;
1737 do {
1738 long pending = READ_DATA_PENDING_COUNT(fptr);
1739 if (pending > 0) {
1740 const char *p = READ_DATA_PENDING_PTR(fptr);
1741 const char *e;
1742 long last = 0, len = (c != EOF);
1743 rb_encoding *enc = io_read_encoding(fptr);
1745 if (limit > 0 && pending > limit) pending = limit;
1746 e = memchr(p, delim, pending);
1747 if (e) pending = e - p + 1;
1748 len += pending;
1749 if (!NIL_P(str)) {
1750 last = RSTRING_LEN(str);
1751 rb_str_resize(str, last + len);
1753 else {
1754 *strp = str = rb_str_buf_new(len);
1755 rb_str_set_len(str, len);
1757 if (c != EOF) {
1758 RSTRING_PTR(str)[last++] = c;
1760 if (limit > 0 && limit == pending) {
1761 char *p = fptr->rbuf+fptr->rbuf_off;
1762 char *pp = p + limit;
1763 char *pl = rb_enc_left_char_head(p, pp, enc);
1765 if (pl < pp) {
1766 int diff = pp - pl;
1767 pending -= diff;
1768 limit = pending;
1769 rb_str_set_len(str, RSTRING_LEN(str)-diff);
1772 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
1773 limit -= pending;
1774 *lp = limit;
1775 if (limit == 0) return RSTRING_PTR(str)[RSTRING_LEN(str)-1];
1776 if (e) return delim;
1778 else if (c != EOF) {
1779 if (!NIL_P(str)) {
1780 char ch = c;
1781 rb_str_buf_cat(str, &ch, 1);
1783 else {
1784 *strp = str = rb_str_buf_new(1);
1785 rb_str_resize(str, 1);
1786 RSTRING_PTR(str)[0] = c;
1789 rb_thread_wait_fd(fptr->fd);
1790 rb_io_check_closed(fptr);
1791 if (io_fillbuf(fptr) < 0) {
1792 *lp = limit;
1793 return c;
1795 } while (c != delim);
1798 char ch = c;
1799 if (!NIL_P(str)) {
1800 rb_str_cat(str, &ch, 1);
1802 else {
1803 *strp = str = rb_str_new(&ch, 1);
1807 return c;
1810 static inline int
1811 swallow(rb_io_t *fptr, int term)
1813 do {
1814 long cnt;
1815 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
1816 char buf[1024];
1817 const char *p = READ_DATA_PENDING_PTR(fptr);
1818 int i;
1819 if (cnt > sizeof buf) cnt = sizeof buf;
1820 if (*p != term) return Qtrue;
1821 i = cnt;
1822 while (--i && *++p == term);
1823 if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
1824 rb_sys_fail(fptr->path);
1826 rb_thread_wait_fd(fptr->fd);
1827 rb_io_check_closed(fptr);
1828 } while (io_fillbuf(fptr) == 0);
1829 return Qfalse;
1832 static VALUE
1833 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc)
1835 VALUE str = Qnil;
1836 int len = 0;
1837 long pos = 0;
1838 int cr = fptr->enc2 ? ENC_CODERANGE_BROKEN : 0;
1840 for (;;) {
1841 long pending = READ_DATA_PENDING_COUNT(fptr);
1843 if (pending > 0) {
1844 const char *p = READ_DATA_PENDING_PTR(fptr);
1845 const char *e;
1847 e = memchr(p, '\n', pending);
1848 if (e) {
1849 pending = e - p + 1;
1851 if (NIL_P(str)) {
1852 str = rb_str_new(p, pending);
1853 fptr->rbuf_off += pending;
1854 fptr->rbuf_len -= pending;
1856 else {
1857 rb_str_resize(str, len + pending);
1858 read_buffered_data(RSTRING_PTR(str)+len, pending, fptr);
1860 len += pending;
1861 if (cr != ENC_CODERANGE_BROKEN)
1862 pos = rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
1863 if (e) break;
1865 rb_thread_wait_fd(fptr->fd);
1866 rb_io_check_closed(fptr);
1867 if (io_fillbuf(fptr) < 0) {
1868 if (NIL_P(str)) return Qnil;
1869 break;
1873 str = io_enc_str(str, fptr);
1874 if (!fptr->enc2) ENC_CODERANGE_SET(str, cr);
1875 fptr->lineno++;
1876 ARGF.lineno = INT2FIX(fptr->lineno);
1877 return str;
1880 static void
1881 prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
1883 VALUE lim, rs;
1884 rb_io_t *fptr;
1886 if (argc == 0) {
1887 rs = rb_rs;
1888 lim = Qnil;
1890 else {
1891 rb_scan_args(argc, argv, "11", &rs, &lim);
1892 if (NIL_P(lim) && !NIL_P(rs) && TYPE(rs) != T_STRING) {
1893 VALUE tmp = rb_check_string_type(rs);
1895 if (NIL_P(tmp)) {
1896 lim = rs;
1897 rs = rb_rs;
1899 else {
1900 rs = tmp;
1904 if (!NIL_P(rs)) {
1905 rb_encoding *enc_rs, *enc_io;
1907 GetOpenFile(io, fptr);
1908 enc_rs = rb_enc_get(rs);
1909 enc_io = io_read_encoding(fptr);
1910 if (enc_io != enc_rs &&
1911 (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
1912 !rb_enc_asciicompat(enc_io))) {
1913 if (rs == rb_default_rs) {
1914 rs = rb_enc_str_new(0, 0, enc_io);
1915 rb_str_buf_cat_ascii(rs, "\n");
1917 else {
1918 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
1919 rb_enc_name(enc_io),
1920 rb_enc_name(enc_rs));
1923 if (fptr->enc2) {
1924 VALUE rs2;
1925 rs2 = rb_funcall(rs, id_encode, 2,
1926 rb_enc_from_encoding(fptr->enc2),
1927 rb_enc_from_encoding(fptr->enc));
1928 if (!RTEST(rb_str_equal(rs, rs2))) {
1929 rs = rs2;
1933 *rsp = rs;
1934 *limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
1937 static VALUE
1938 rb_io_getline_1(VALUE rs, long limit, VALUE io)
1940 VALUE str = Qnil;
1941 rb_io_t *fptr;
1942 int nolimit = 0;
1943 rb_encoding *enc;
1945 GetOpenFile(io, fptr);
1946 rb_io_check_readable(fptr);
1947 if (NIL_P(rs)) {
1948 str = read_all(fptr, 0, Qnil);
1949 if (RSTRING_LEN(str) == 0) return Qnil;
1951 else if (limit == 0) {
1952 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
1954 else if (rs == rb_default_rs && limit < 0 &&
1955 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
1956 return rb_io_getline_fast(fptr, enc);
1958 else {
1959 int c, newline;
1960 const char *rsptr;
1961 long rslen;
1962 int rspara = 0;
1964 rslen = RSTRING_LEN(rs);
1965 if (rslen == 0) {
1966 rsptr = "\n\n";
1967 rslen = 2;
1968 rspara = 1;
1969 swallow(fptr, '\n');
1970 rs = 0;
1972 else {
1973 rsptr = RSTRING_PTR(rs);
1975 newline = rsptr[rslen - 1];
1977 enc = io_input_encoding(fptr);
1978 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
1979 if (c == newline) {
1980 const char *s, *p, *pp;
1982 if (RSTRING_LEN(str) < rslen) continue;
1983 s = RSTRING_PTR(str);
1984 p = s + RSTRING_LEN(str) - rslen;
1985 pp = rb_enc_left_char_head(s, p, enc);
1986 if (pp != p) continue;
1987 if (!rspara) rscheck(rsptr, rslen, rs);
1988 if (memcmp(p, rsptr, rslen) == 0) break;
1990 if (limit == 0) {
1991 nolimit = 1;
1992 break;
1996 if (rspara) {
1997 if (c != EOF) {
1998 swallow(fptr, '\n');
2001 if (!NIL_P(str)) str = io_enc_str(str, fptr);
2004 if (!NIL_P(str)) {
2005 if (!nolimit) {
2006 fptr->lineno++;
2007 ARGF.lineno = INT2FIX(fptr->lineno);
2011 return str;
2014 static VALUE
2015 rb_io_getline(int argc, VALUE *argv, VALUE io)
2017 VALUE rs;
2018 long limit;
2020 prepare_getline_args(argc, argv, &rs, &limit, io);
2021 return rb_io_getline_1(rs, limit, io);
2024 VALUE
2025 rb_io_gets(VALUE io)
2027 rb_io_t *fptr;
2029 GetOpenFile(io, fptr);
2030 rb_io_check_readable(fptr);
2031 return rb_io_getline_fast(fptr, io_read_encoding(fptr));
2035 * call-seq:
2036 * ios.gets(sep=$/) => string or nil
2037 * ios.gets(limit) => string or nil
2038 * ios.gets(sep, limit) => string or nil
2040 * Reads the next ``line'' from the I/O stream; lines are separated by
2041 * <i>sep</i>. A separator of <code>nil</code> reads the entire
2042 * contents, and a zero-length separator reads the input a paragraph at
2043 * a time (two successive newlines in the input separate paragraphs).
2044 * The stream must be opened for reading or an <code>IOError</code>
2045 * will be raised. The line read in will be returned and also assigned
2046 * to <code>$_</code>. Returns <code>nil</code> if called at end of
2047 * file. If the first argument is an integer, or optional second
2048 * argument is given, the returning string would not be longer than the
2049 * given value.
2051 * File.new("testfile").gets #=> "This is line one\n"
2052 * $_ #=> "This is line one\n"
2055 static VALUE
2056 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
2058 VALUE str;
2060 str = rb_io_getline(argc, argv, io);
2061 rb_lastline_set(str);
2063 return str;
2067 * call-seq:
2068 * ios.lineno => integer
2070 * Returns the current line number in <em>ios</em>. The stream must be
2071 * opened for reading. <code>lineno</code> counts the number of times
2072 * <code>gets</code> is called, rather than the number of newlines
2073 * encountered. The two values will differ if <code>gets</code> is
2074 * called with a separator other than newline. See also the
2075 * <code>$.</code> variable.
2077 * f = File.new("testfile")
2078 * f.lineno #=> 0
2079 * f.gets #=> "This is line one\n"
2080 * f.lineno #=> 1
2081 * f.gets #=> "This is line two\n"
2082 * f.lineno #=> 2
2085 static VALUE
2086 rb_io_lineno(VALUE io)
2088 rb_io_t *fptr;
2090 GetOpenFile(io, fptr);
2091 rb_io_check_readable(fptr);
2092 return INT2NUM(fptr->lineno);
2096 * call-seq:
2097 * ios.lineno = integer => integer
2099 * Manually sets the current line number to the given value.
2100 * <code>$.</code> is updated only on the next read.
2102 * f = File.new("testfile")
2103 * f.gets #=> "This is line one\n"
2104 * $. #=> 1
2105 * f.lineno = 1000
2106 * f.lineno #=> 1000
2107 * $. #=> 1 # lineno of last read
2108 * f.gets #=> "This is line two\n"
2109 * $. #=> 1001 # lineno of last read
2112 static VALUE
2113 rb_io_set_lineno(VALUE io, VALUE lineno)
2115 rb_io_t *fptr;
2117 GetOpenFile(io, fptr);
2118 rb_io_check_readable(fptr);
2119 fptr->lineno = NUM2INT(lineno);
2120 return lineno;
2124 * call-seq:
2125 * ios.readline(sep=$/) => string
2126 * ios.readline(limit) => string
2127 * ios.readline(sep, limit) => string
2129 * Reads a line as with <code>IO#gets</code>, but raises an
2130 * <code>EOFError</code> on end of file.
2133 static VALUE
2134 rb_io_readline(int argc, VALUE *argv, VALUE io)
2136 VALUE line = rb_io_gets_m(argc, argv, io);
2138 if (NIL_P(line)) {
2139 rb_eof_error();
2141 return line;
2145 * call-seq:
2146 * ios.readlines(sep=$/) => array
2147 * ios.readlines(limit) => array
2148 * ios.readlines(sep, limit) => array
2150 * Reads all of the lines in <em>ios</em>, and returns them in
2151 * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
2152 * <i>sep</i> is <code>nil</code>, the rest of the stream is returned
2153 * as a single record. If the first argument is an integer, or
2154 * optional second argument is given, the returning string would not be
2155 * longer than the given value. The stream must be opened for reading
2156 * or an <code>IOError</code> will be raised.
2158 * f = File.new("testfile")
2159 * f.readlines[0] #=> "This is line one\n"
2162 static VALUE
2163 rb_io_readlines(int argc, VALUE *argv, VALUE io)
2165 VALUE line, ary, rs;
2166 long limit;
2168 prepare_getline_args(argc, argv, &rs, &limit, io);
2169 ary = rb_ary_new();
2170 while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
2171 rb_ary_push(ary, line);
2173 return ary;
2177 * call-seq:
2178 * ios.each(sep=$/) {|line| block } => ios
2179 * ios.each(limit) {|line| block } => ios
2180 * ios.each(sep,limit) {|line| block } => ios
2181 * ios.each_line(sep=$/) {|line| block } => ios
2182 * ios.each_line(limit) {|line| block } => ios
2183 * ios.each_line(sep,limit) {|line| block } => ios
2185 * Executes the block for every line in <em>ios</em>, where lines are
2186 * separated by <i>sep</i>. <em>ios</em> must be opened for
2187 * reading or an <code>IOError</code> will be raised.
2189 * f = File.new("testfile")
2190 * f.each {|line| puts "#{f.lineno}: #{line}" }
2192 * <em>produces:</em>
2194 * 1: This is line one
2195 * 2: This is line two
2196 * 3: This is line three
2197 * 4: And so on...
2200 static VALUE
2201 rb_io_each_line(int argc, VALUE *argv, VALUE io)
2203 VALUE str, rs;
2204 long limit;
2206 RETURN_ENUMERATOR(io, argc, argv);
2207 prepare_getline_args(argc, argv, &rs, &limit, io);
2208 while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
2209 rb_yield(str);
2211 return io;
2215 * call-seq:
2216 * ios.each_byte {|byte| block } => ios
2218 * Calls the given block once for each byte (0..255) in <em>ios</em>,
2219 * passing the byte as an argument. The stream must be opened for
2220 * reading or an <code>IOError</code> will be raised.
2222 * f = File.new("testfile")
2223 * checksum = 0
2224 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
2225 * checksum #=> 12
2228 static VALUE
2229 rb_io_each_byte(VALUE io)
2231 rb_io_t *fptr;
2232 char *p, *e;
2234 RETURN_ENUMERATOR(io, 0, 0);
2235 GetOpenFile(io, fptr);
2237 for (;;) {
2238 p = fptr->rbuf+fptr->rbuf_off;
2239 e = p + fptr->rbuf_len;
2240 while (p < e) {
2241 fptr->rbuf_off++;
2242 fptr->rbuf_len--;
2243 rb_yield(INT2FIX(*p & 0xff));
2244 p++;
2245 errno = 0;
2247 rb_io_check_readable(fptr);
2248 READ_CHECK(fptr);
2249 if (io_fillbuf(fptr) < 0) {
2250 break;
2253 return io;
2256 static VALUE
2257 io_getc(rb_io_t *fptr, rb_encoding *enc)
2259 int r, n, cr = 0;
2260 VALUE str;
2262 if (io_fillbuf(fptr) < 0) {
2263 return Qnil;
2265 if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf[fptr->rbuf_off])) {
2266 str = rb_str_new(fptr->rbuf+fptr->rbuf_off, 1);
2267 fptr->rbuf_off += 1;
2268 fptr->rbuf_len -= 1;
2269 cr = ENC_CODERANGE_7BIT;
2271 else {
2272 r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off, fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc);
2273 if (MBCLEN_CHARFOUND_P(r) &&
2274 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf_len) {
2275 str = rb_str_new(fptr->rbuf+fptr->rbuf_off, n);
2276 fptr->rbuf_off += n;
2277 fptr->rbuf_len -= n;
2278 cr = ENC_CODERANGE_VALID;
2280 else if (MBCLEN_NEEDMORE_P(r)) {
2281 str = rb_str_new(fptr->rbuf+fptr->rbuf_off, fptr->rbuf_len);
2282 fptr->rbuf_len = 0;
2283 getc_needmore:
2284 if (io_fillbuf(fptr) != -1) {
2285 rb_str_cat(str, fptr->rbuf+fptr->rbuf_off, 1);
2286 fptr->rbuf_off++;
2287 fptr->rbuf_len--;
2288 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
2289 if (MBCLEN_NEEDMORE_P(r)) {
2290 goto getc_needmore;
2292 else if (MBCLEN_CHARFOUND_P(r)) {
2293 cr = ENC_CODERANGE_VALID;
2297 else {
2298 str = rb_str_new(fptr->rbuf+fptr->rbuf_off, 1);
2299 fptr->rbuf_off++;
2300 fptr->rbuf_len--;
2303 if (!cr) cr = ENC_CODERANGE_BROKEN;
2304 str = io_enc_str(str, fptr);
2305 if (!fptr->enc2) {
2306 ENC_CODERANGE_SET(str, cr);
2308 return str;
2312 * call-seq:
2313 * ios.each_char {|c| block } => ios
2315 * Calls the given block once for each character in <em>ios</em>,
2316 * passing the character as an argument. The stream must be opened for
2317 * reading or an <code>IOError</code> will be raised.
2319 * f = File.new("testfile")
2320 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
2323 static VALUE
2324 rb_io_each_char(VALUE io)
2326 rb_io_t *fptr;
2327 rb_encoding *enc;
2328 VALUE c;
2330 RETURN_ENUMERATOR(io, 0, 0);
2331 GetOpenFile(io, fptr);
2332 rb_io_check_readable(fptr);
2334 enc = io_input_encoding(fptr);
2335 READ_CHECK(fptr);
2336 while (!NIL_P(c = io_getc(fptr, enc))) {
2337 rb_yield(c);
2339 return io;
2345 * call-seq:
2346 * ios.lines(sep=$/) => anEnumerator
2347 * ios.lines(limit) => anEnumerator
2348 * ios.lines(sep, limit) => anEnumerator
2350 * Returns an enumerator that gives each line in <em>ios</em>.
2351 * The stream must be opened for reading or an <code>IOError</code>
2352 * will be raised.
2354 * f = File.new("testfile")
2355 * f.lines.to_a #=> ["foo\n", "bar\n"]
2356 * f.rewind
2357 * f.lines.sort #=> ["bar\n", "foo\n"]
2360 static VALUE
2361 rb_io_lines(int argc, VALUE *argv, VALUE io)
2363 return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
2367 * call-seq:
2368 * ios.bytes => anEnumerator
2370 * Returns an enumerator that gives each byte (0..255) in <em>ios</em>.
2371 * The stream must be opened for reading or an <code>IOError</code>
2372 * will be raised.
2374 * f = File.new("testfile")
2375 * f.bytes.to_a #=> [104, 101, 108, 108, 111]
2376 * f.rewind
2377 * f.bytes.sort #=> [101, 104, 108, 108, 111]
2380 static VALUE
2381 rb_io_bytes(VALUE io)
2383 return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
2387 * call-seq:
2388 * ios.chars => anEnumerator
2390 * Returns an enumerator that gives each character in <em>ios</em>.
2391 * The stream must be opened for reading or an <code>IOError</code>
2392 * will be raised.
2394 * f = File.new("testfile")
2395 * f.chars.to_a #=> ["h", "e", "l", "l", "o"]
2396 * f.rewind
2397 * f.chars.sort #=> ["e", "h", "l", "l", "o"]
2400 static VALUE
2401 rb_io_chars(VALUE io)
2403 return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
2407 * call-seq:
2408 * ios.getc => fixnum or nil
2410 * Reads a one-character string from <em>ios</em>. Returns
2411 * <code>nil</code> if called at end of file.
2413 * f = File.new("testfile")
2414 * f.getc #=> "8"
2415 * f.getc #=> "1"
2418 static VALUE
2419 rb_io_getc(VALUE io)
2421 rb_io_t *fptr;
2422 rb_encoding *enc;
2424 GetOpenFile(io, fptr);
2425 rb_io_check_readable(fptr);
2427 enc = io_input_encoding(fptr);
2428 READ_CHECK(fptr);
2429 return io_getc(fptr, enc);
2432 rb_getc(FILE *f)
2434 int c;
2436 rb_read_check(f);
2437 TRAP_BEG;
2438 c = getc(f);
2439 TRAP_END;
2441 return c;
2445 * call-seq:
2446 * ios.readchar => string
2448 * Reads a one-character string from <em>ios</em>. Raises an
2449 * <code>EOFError</code> on end of file.
2451 * f = File.new("testfile")
2452 * f.readchar #=> "8"
2453 * f.readchar #=> "1"
2456 static VALUE
2457 rb_io_readchar(VALUE io)
2459 VALUE c = rb_io_getc(io);
2461 if (NIL_P(c)) {
2462 rb_eof_error();
2464 return c;
2468 * call-seq:
2469 * ios.getbyte => fixnum or nil
2471 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
2472 * <code>nil</code> if called at end of file.
2474 * f = File.new("testfile")
2475 * f.getbyte #=> 84
2476 * f.getbyte #=> 104
2479 VALUE
2480 rb_io_getbyte(VALUE io)
2482 rb_io_t *fptr;
2483 int c;
2485 GetOpenFile(io, fptr);
2486 rb_io_check_readable(fptr);
2487 READ_CHECK(fptr);
2488 if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
2489 rb_io_t *ofp;
2490 GetOpenFile(rb_stdout, ofp);
2491 if (ofp->mode & FMODE_TTY) {
2492 rb_io_flush(rb_stdout);
2495 if (io_fillbuf(fptr) < 0) {
2496 return Qnil;
2498 fptr->rbuf_off++;
2499 fptr->rbuf_len--;
2500 c = (unsigned char)fptr->rbuf[fptr->rbuf_off-1];
2501 return INT2FIX(c & 0xff);
2505 * call-seq:
2506 * ios.readbyte => fixnum
2508 * Reads a character as with <code>IO#getc</code>, but raises an
2509 * <code>EOFError</code> on end of file.
2512 static VALUE
2513 rb_io_readbyte(VALUE io)
2515 VALUE c = rb_io_getbyte(io);
2517 if (NIL_P(c)) {
2518 rb_eof_error();
2520 return c;
2524 * call-seq:
2525 * ios.ungetc(string) => nil
2527 * Pushes back one character (passed as a parameter) onto <em>ios</em>,
2528 * such that a subsequent buffered read will return it. Only one character
2529 * may be pushed back before a subsequent read operation (that is,
2530 * you will be able to read only the last of several characters that have been pushed
2531 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
2533 * f = File.new("testfile") #=> #<File:testfile>
2534 * c = f.getc #=> "8"
2535 * f.ungetc(c) #=> nil
2536 * f.getc #=> "8"
2539 VALUE
2540 rb_io_ungetc(VALUE io, VALUE c)
2542 rb_io_t *fptr;
2544 GetOpenFile(io, fptr);
2545 rb_io_check_readable(fptr);
2546 if (NIL_P(c)) return Qnil;
2547 if (FIXNUM_P(c)) {
2548 int cc = FIX2INT(c);
2549 rb_encoding *enc = io_read_encoding(fptr);
2550 char buf[16];
2552 c = rb_str_new(buf, rb_enc_mbcput(cc, buf, enc));
2554 else {
2555 SafeStringValue(c);
2557 io_ungetc(c, fptr);
2558 return Qnil;
2562 * call-seq:
2563 * ios.isatty => true or false
2564 * ios.tty? => true or false
2566 * Returns <code>true</code> if <em>ios</em> is associated with a
2567 * terminal device (tty), <code>false</code> otherwise.
2569 * File.new("testfile").isatty #=> false
2570 * File.new("/dev/tty").isatty #=> true
2573 static VALUE
2574 rb_io_isatty(VALUE io)
2576 rb_io_t *fptr;
2578 GetOpenFile(io, fptr);
2579 if (isatty(fptr->fd) == 0)
2580 return Qfalse;
2581 return Qtrue;
2585 * call-seq:
2586 * ios.close_on_exec? => true or false
2588 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
2590 * f = open("/dev/null")
2591 * f.close_on_exec? #=> false
2592 * f.close_on_exec = true
2593 * f.close_on_exec? #=> true
2594 * f.close_on_exec = false
2595 * f.close_on_exec? #=> false
2598 static VALUE
2599 rb_io_close_on_exec_p(VALUE io)
2601 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
2602 rb_io_t *fptr;
2603 VALUE write_io;
2604 int fd, ret;
2606 write_io = GetWriteIO(io);
2607 if (io != write_io) {
2608 GetOpenFile(write_io, fptr);
2609 if (fptr && 0 <= (fd = fptr->fd)) {
2610 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail(fptr->path);
2611 if (!(ret & FD_CLOEXEC)) return Qfalse;
2615 GetOpenFile(io, fptr);
2616 if (fptr && 0 <= (fd = fptr->fd)) {
2617 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail(fptr->path);
2618 if (!(ret & FD_CLOEXEC)) return Qfalse;
2620 return Qtrue;
2621 #else
2622 rb_notimplement();
2623 return Qnil; /* not reached */
2624 #endif
2628 * call-seq:
2629 * ios.close_on_exec = bool => true or false
2631 * Sets a close-on-exec flag.
2633 * f = open("/dev/null")
2634 * f.close_on_exec = true
2635 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
2636 * f.closed? #=> false
2639 static VALUE
2640 rb_io_set_close_on_exec(VALUE io, VALUE arg)
2642 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
2643 int flag = RTEST(arg) ? FD_CLOEXEC : 0;
2644 rb_io_t *fptr;
2645 VALUE write_io;
2646 int fd, ret;
2648 write_io = GetWriteIO(io);
2649 if (io != write_io) {
2650 GetOpenFile(write_io, fptr);
2651 if (fptr && 0 <= (fd = fptr->fd)) {
2652 if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail(fptr->path);
2653 if ((ret & FD_CLOEXEC) != flag) {
2654 ret = (ret & ~FD_CLOEXEC) | flag;
2655 ret = fcntl(fd, F_SETFD, ret);
2656 if (ret == -1) rb_sys_fail(fptr->path);
2662 GetOpenFile(io, fptr);
2663 if (fptr && 0 <= (fd = fptr->fd)) {
2664 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail(fptr->path);
2665 if ((ret & FD_CLOEXEC) != flag) {
2666 ret = (ret & ~FD_CLOEXEC) | flag;
2667 ret = fcntl(fd, F_SETFD, ret);
2668 if (ret == -1) rb_sys_fail(fptr->path);
2671 #else
2672 rb_notimplement();
2673 #endif
2674 return Qnil;
2677 #define FMODE_PREP (1<<16)
2678 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
2679 #define PREP_STDIO_NAME(f) ((f)->path)
2681 static void
2682 fptr_finalize(rb_io_t *fptr, int noraise)
2684 int ebadf = 0;
2685 if (fptr->wbuf_len) {
2686 io_fflush(fptr);
2688 if (IS_PREP_STDIO(fptr) ||
2689 fptr->fd <= 2) {
2690 return;
2692 if (fptr->stdio_file) {
2693 if (fclose(fptr->stdio_file) < 0 && !noraise) {
2694 /* fptr->stdio_file is deallocated anyway */
2695 fptr->stdio_file = 0;
2696 fptr->fd = -1;
2697 rb_sys_fail(fptr->path);
2700 else if (0 <= fptr->fd) {
2701 if (close(fptr->fd) < 0 && !noraise) {
2702 if (errno != EBADF) {
2703 /* fptr->fd is still not closed */
2704 rb_sys_fail(fptr->path);
2706 else {
2707 /* fptr->fd is already closed. */
2708 ebadf = 1;
2712 fptr->fd = -1;
2713 fptr->stdio_file = 0;
2714 fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
2715 if (ebadf) {
2716 rb_sys_fail(fptr->path);
2720 static void
2721 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
2723 if (fptr->finalize) {
2724 (*fptr->finalize)(fptr, noraise);
2726 else {
2727 fptr_finalize(fptr, noraise);
2732 rb_io_fptr_finalize(rb_io_t *fptr)
2734 if (!fptr) return 0;
2735 if (fptr->refcnt <= 0 || --fptr->refcnt) return 0;
2736 if (fptr->path) {
2737 free(fptr->path);
2738 fptr->path = 0;
2740 if (0 <= fptr->fd)
2741 rb_io_fptr_cleanup(fptr, Qtrue);
2742 if (fptr->rbuf) {
2743 free(fptr->rbuf);
2744 fptr->rbuf = 0;
2746 if (fptr->wbuf) {
2747 free(fptr->wbuf);
2748 fptr->wbuf = 0;
2750 free(fptr);
2751 return 1;
2754 VALUE
2755 rb_io_close(VALUE io)
2757 rb_io_t *fptr;
2758 int fd;
2759 VALUE write_io;
2760 rb_io_t *write_fptr;
2762 write_io = GetWriteIO(io);
2763 if (io != write_io) {
2764 write_fptr = RFILE(write_io)->fptr;
2765 if (write_fptr && 0 <= write_fptr->fd) {
2766 rb_io_fptr_cleanup(write_fptr, Qtrue);
2770 fptr = RFILE(io)->fptr;
2771 if (!fptr) return Qnil;
2772 if (fptr->fd < 0) return Qnil;
2774 fd = fptr->fd;
2775 rb_io_fptr_cleanup(fptr, Qfalse);
2776 rb_thread_fd_close(fd);
2778 if (fptr->pid) {
2779 rb_syswait(fptr->pid);
2780 fptr->pid = 0;
2783 return Qnil;
2787 * call-seq:
2788 * ios.close => nil
2790 * Closes <em>ios</em> and flushes any pending writes to the operating
2791 * system. The stream is unavailable for any further data operations;
2792 * an <code>IOError</code> is raised if such an attempt is made. I/O
2793 * streams are automatically closed when they are claimed by the
2794 * garbage collector.
2796 * If <em>ios</em> is opened by <code>IO.popen</code>,
2797 * <code>close</code> sets <code>$?</code>.
2800 static VALUE
2801 rb_io_close_m(VALUE io)
2803 if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
2804 rb_raise(rb_eSecurityError, "Insecure: can't close");
2806 rb_io_check_closed(RFILE(io)->fptr);
2807 rb_io_close(io);
2808 return Qnil;
2811 static VALUE
2812 io_call_close(VALUE io)
2814 return rb_funcall(io, rb_intern("close"), 0, 0);
2817 static VALUE
2818 io_close(VALUE io)
2820 return rb_rescue(io_call_close, io, 0, 0);
2824 * call-seq:
2825 * ios.closed? => true or false
2827 * Returns <code>true</code> if <em>ios</em> is completely closed (for
2828 * duplex streams, both reader and writer), <code>false</code>
2829 * otherwise.
2831 * f = File.new("testfile")
2832 * f.close #=> nil
2833 * f.closed? #=> true
2834 * f = IO.popen("/bin/sh","r+")
2835 * f.close_write #=> nil
2836 * f.closed? #=> false
2837 * f.close_read #=> nil
2838 * f.closed? #=> true
2842 static VALUE
2843 rb_io_closed(VALUE io)
2845 rb_io_t *fptr;
2846 VALUE write_io;
2847 rb_io_t *write_fptr;
2849 write_io = GetWriteIO(io);
2850 if (io != write_io) {
2851 write_fptr = RFILE(write_io)->fptr;
2852 if (write_fptr && 0 <= write_fptr->fd) {
2853 return Qfalse;
2857 fptr = RFILE(io)->fptr;
2858 rb_io_check_initialized(fptr);
2859 return 0 <= fptr->fd ? Qfalse : Qtrue;
2863 * call-seq:
2864 * ios.close_read => nil
2866 * Closes the read end of a duplex I/O stream (i.e., one that contains
2867 * both a read and a write stream, such as a pipe). Will raise an
2868 * <code>IOError</code> if the stream is not duplexed.
2870 * f = IO.popen("/bin/sh","r+")
2871 * f.close_read
2872 * f.readlines
2874 * <em>produces:</em>
2876 * prog.rb:3:in `readlines': not opened for reading (IOError)
2877 * from prog.rb:3
2880 static VALUE
2881 rb_io_close_read(VALUE io)
2883 rb_io_t *fptr;
2884 VALUE write_io;
2886 if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
2887 rb_raise(rb_eSecurityError, "Insecure: can't close");
2889 GetOpenFile(io, fptr);
2890 if (is_socket(fptr->fd, fptr->path)) {
2891 #ifndef SHUT_RD
2892 # define SHUT_RD 0
2893 #endif
2894 if (shutdown(fptr->fd, SHUT_RD) < 0)
2895 rb_sys_fail(fptr->path);
2896 fptr->mode &= ~FMODE_READABLE;
2897 if (!(fptr->mode & FMODE_WRITABLE))
2898 return rb_io_close(io);
2899 return Qnil;
2902 write_io = GetWriteIO(io);
2903 if (io != write_io) {
2904 rb_io_t *wfptr;
2905 fptr_finalize(fptr, Qfalse);
2906 GetOpenFile(write_io, wfptr);
2907 if (fptr->refcnt < LONG_MAX) {
2908 wfptr->refcnt++;
2909 RFILE(io)->fptr = wfptr;
2910 rb_io_fptr_finalize(fptr);
2912 return Qnil;
2915 if (fptr->mode & FMODE_WRITABLE) {
2916 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
2918 return rb_io_close(io);
2922 * call-seq:
2923 * ios.close_write => nil
2925 * Closes the write end of a duplex I/O stream (i.e., one that contains
2926 * both a read and a write stream, such as a pipe). Will raise an
2927 * <code>IOError</code> if the stream is not duplexed.
2929 * f = IO.popen("/bin/sh","r+")
2930 * f.close_write
2931 * f.print "nowhere"
2933 * <em>produces:</em>
2935 * prog.rb:3:in `write': not opened for writing (IOError)
2936 * from prog.rb:3:in `print'
2937 * from prog.rb:3
2940 static VALUE
2941 rb_io_close_write(VALUE io)
2943 rb_io_t *fptr;
2944 VALUE write_io;
2946 if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
2947 rb_raise(rb_eSecurityError, "Insecure: can't close");
2949 write_io = GetWriteIO(io);
2950 GetOpenFile(write_io, fptr);
2951 if (is_socket(fptr->fd, fptr->path)) {
2952 #ifndef SHUT_WR
2953 # define SHUT_WR 1
2954 #endif
2955 if (shutdown(fptr->fd, SHUT_WR) < 0)
2956 rb_sys_fail(fptr->path);
2957 fptr->mode &= ~FMODE_WRITABLE;
2958 if (!(fptr->mode & FMODE_READABLE))
2959 return rb_io_close(write_io);
2960 return Qnil;
2963 if (fptr->mode & FMODE_READABLE) {
2964 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
2967 rb_io_close(write_io);
2968 if (io != write_io) {
2969 GetOpenFile(io, fptr);
2970 fptr->tied_io_for_writing = 0;
2971 fptr->mode &= ~FMODE_DUPLEX;
2973 return Qnil;
2977 * call-seq:
2978 * ios.sysseek(offset, whence=SEEK_SET) => integer
2980 * Seeks to a given <i>offset</i> in the stream according to the value
2981 * of <i>whence</i> (see <code>IO#seek</code> for values of
2982 * <i>whence</i>). Returns the new offset into the file.
2984 * f = File.new("testfile")
2985 * f.sysseek(-13, IO::SEEK_END) #=> 53
2986 * f.sysread(10) #=> "And so on."
2989 static VALUE
2990 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
2992 VALUE offset, ptrname;
2993 int whence = SEEK_SET;
2994 rb_io_t *fptr;
2995 off_t pos;
2997 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
2998 whence = NUM2INT(ptrname);
3000 pos = NUM2OFFT(offset);
3001 GetOpenFile(io, fptr);
3002 if ((fptr->mode & FMODE_READABLE) && READ_DATA_BUFFERED(fptr)) {
3003 rb_raise(rb_eIOError, "sysseek for buffered IO");
3005 if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf_len) {
3006 rb_warn("sysseek for buffered IO");
3008 pos = lseek(fptr->fd, pos, whence);
3009 if (pos == -1) rb_sys_fail(fptr->path);
3011 return OFFT2NUM(pos);
3015 * call-seq:
3016 * ios.syswrite(string) => integer
3018 * Writes the given string to <em>ios</em> using a low-level write.
3019 * Returns the number of bytes written. Do not mix with other methods
3020 * that write to <em>ios</em> or you may get unpredictable results.
3021 * Raises <code>SystemCallError</code> on error.
3023 * f = File.new("out", "w")
3024 * f.syswrite("ABCDEF") #=> 6
3027 static VALUE
3028 rb_io_syswrite(VALUE io, VALUE str)
3030 rb_io_t *fptr;
3031 long n;
3033 rb_secure(4);
3034 if (TYPE(str) != T_STRING)
3035 str = rb_obj_as_string(str);
3037 io = GetWriteIO(io);
3038 GetOpenFile(io, fptr);
3039 rb_io_check_writable(fptr);
3041 if (fptr->wbuf_len) {
3042 rb_warn("syswrite for buffered IO");
3044 if (!rb_thread_fd_writable(fptr->fd)) {
3045 rb_io_check_closed(fptr);
3047 TRAP_BEG;
3048 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
3049 TRAP_END;
3051 if (n == -1) rb_sys_fail(fptr->path);
3053 return LONG2FIX(n);
3057 * call-seq:
3058 * ios.sysread(integer[, outbuf]) => string
3060 * Reads <i>integer</i> bytes from <em>ios</em> using a low-level
3061 * read and returns them as a string. Do not mix with other methods
3062 * that read from <em>ios</em> or you may get unpredictable results.
3063 * If the optional <i>outbuf</i> argument is present, it must reference
3064 * a String, which will receive the data.
3065 * Raises <code>SystemCallError</code> on error and
3066 * <code>EOFError</code> at end of file.
3068 * f = File.new("testfile")
3069 * f.sysread(16) #=> "This is line one"
3072 static VALUE
3073 rb_io_sysread(int argc, VALUE *argv, VALUE io)
3075 VALUE len, str;
3076 rb_io_t *fptr;
3077 long n, ilen;
3079 rb_scan_args(argc, argv, "11", &len, &str);
3080 ilen = NUM2LONG(len);
3082 if (NIL_P(str)) {
3083 str = rb_str_new(0, ilen);
3085 else {
3086 StringValue(str);
3087 rb_str_modify(str);
3088 rb_str_resize(str, ilen);
3090 if (ilen == 0) return str;
3092 GetOpenFile(io, fptr);
3093 rb_io_check_readable(fptr);
3095 if (READ_DATA_BUFFERED(fptr)) {
3096 rb_raise(rb_eIOError, "sysread for buffered IO");
3099 n = fptr->fd;
3100 rb_thread_wait_fd(fptr->fd);
3101 rb_io_check_closed(fptr);
3102 if (RSTRING_LEN(str) != ilen) {
3103 rb_raise(rb_eRuntimeError, "buffer string modified");
3106 n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen);
3108 if (n == -1) {
3109 rb_sys_fail(fptr->path);
3111 rb_str_set_len(str, n);
3112 if (n == 0 && ilen > 0) {
3113 rb_eof_error();
3115 rb_str_resize(str, n);
3116 OBJ_TAINT(str);
3118 return str;
3121 VALUE
3122 rb_io_binmode(VALUE io)
3124 rb_io_t *fptr;
3126 GetOpenFile(io, fptr);
3127 #if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__)
3128 if (!(fptr->mode & FMODE_BINMODE) && READ_DATA_BUFFERED(fptr)) {
3129 rb_raise(rb_eIOError, "buffer already filled with text-mode content");
3131 if (0 <= fptr->fd && setmode(fptr->fd, O_BINARY) == -1)
3132 rb_sys_fail(fptr->path);
3133 #endif
3134 fptr->mode |= FMODE_BINMODE;
3135 return io;
3139 * call-seq:
3140 * ios.binmode => ios
3142 * Puts <em>ios</em> into binary mode. This is useful only in
3143 * MS-DOS/Windows environments. Once a stream is in binary mode, it
3144 * cannot be reset to nonbinary mode.
3147 static VALUE
3148 rb_io_binmode_m(VALUE io)
3150 #if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__)
3151 VALUE write_io;
3152 #endif
3154 rb_io_binmode(io);
3156 #if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__)
3157 write_io = GetWriteIO(io);
3158 if (write_io != io)
3159 rb_io_binmode(write_io);
3160 #endif
3161 return io;
3165 * call-seq:
3166 * ios.binmode? => true or false
3168 * Returns <code>true</code> if <em>ios</em> is binmode.
3170 static VALUE
3171 rb_io_binmode_p(VALUE io)
3173 rb_io_t *fptr;
3174 GetOpenFile(io, fptr);
3175 return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
3178 static const char*
3179 rb_io_flags_mode(int flags)
3181 #ifdef O_BINARY
3182 # define MODE_BINMODE(a,b) ((flags & FMODE_BINMODE) ? (b) : (a))
3183 #else
3184 # define MODE_BINMODE(a,b) (a)
3185 #endif
3186 if (flags & FMODE_APPEND) {
3187 if ((flags & FMODE_READWRITE) == FMODE_READWRITE) {
3188 return MODE_BINMODE("a+", "ab+");
3190 return MODE_BINMODE("a", "ab");
3192 switch (flags & FMODE_READWRITE) {
3193 case FMODE_READABLE:
3194 return MODE_BINMODE("r", "rb");
3195 case FMODE_WRITABLE:
3196 return MODE_BINMODE("w", "wb");
3197 case FMODE_READWRITE:
3198 if (flags & FMODE_CREATE) {
3199 return MODE_BINMODE("w+", "wb+");
3201 return MODE_BINMODE("r+", "rb+");
3203 rb_raise(rb_eArgError, "invalid access modenum %o", flags);
3204 return NULL; /* not reached */
3208 rb_io_mode_flags(const char *mode)
3210 int flags = 0;
3211 const char *m = mode;
3213 switch (*m++) {
3214 case 'r':
3215 flags |= FMODE_READABLE;
3216 break;
3217 case 'w':
3218 flags |= FMODE_WRITABLE | FMODE_CREATE;
3219 break;
3220 case 'a':
3221 flags |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
3222 break;
3223 default:
3224 error:
3225 rb_raise(rb_eArgError, "invalid access mode %s", mode);
3228 while (*m) {
3229 switch (*m++) {
3230 case 'b':
3231 flags |= FMODE_BINMODE;
3232 break;
3233 case '+':
3234 flags |= FMODE_READWRITE;
3235 break;
3236 default:
3237 goto error;
3238 case ':':
3239 return flags;
3243 return flags;
3247 rb_io_modenum_flags(int mode)
3249 int flags = 0;
3251 switch (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
3252 case O_RDONLY:
3253 flags = FMODE_READABLE;
3254 break;
3255 case O_WRONLY:
3256 flags = FMODE_WRITABLE;
3257 break;
3258 case O_RDWR:
3259 flags = FMODE_READWRITE;
3260 break;
3263 if (mode & O_APPEND) {
3264 flags |= FMODE_APPEND;
3266 if (mode & O_CREAT) {
3267 flags |= FMODE_CREATE;
3269 #ifdef O_BINARY
3270 if (mode & O_BINARY) {
3271 flags |= FMODE_BINMODE;
3273 #endif
3275 return flags;
3279 rb_io_mode_modenum(const char *mode)
3281 int flags = 0;
3282 const char *m = mode;
3284 switch (*m++) {
3285 case 'r':
3286 flags |= O_RDONLY;
3287 break;
3288 case 'w':
3289 flags |= O_WRONLY | O_CREAT | O_TRUNC;
3290 break;
3291 case 'a':
3292 flags |= O_WRONLY | O_CREAT | O_APPEND;
3293 break;
3294 default:
3295 error:
3296 rb_raise(rb_eArgError, "invalid access mode %s", mode);
3299 while (*m) {
3300 switch (*m++) {
3301 case 'b':
3302 #ifdef O_BINARY
3303 flags |= O_BINARY;
3304 #endif
3305 break;
3306 case '+':
3307 flags = (flags & ~O_ACCMODE) | O_RDWR;
3308 break;
3309 default:
3310 goto error;
3311 case ':':
3312 return flags;
3316 return flags;
3319 #define MODENUM_MAX 4
3321 static const char*
3322 rb_io_modenum_mode(int flags)
3324 #ifdef O_BINARY
3325 # define MODE_BINARY(a,b) ((flags & O_BINARY) ? (b) : (a))
3326 #else
3327 # define MODE_BINARY(a,b) (a)
3328 #endif
3329 if (flags & O_APPEND) {
3330 if ((flags & O_RDWR) == O_RDWR) {
3331 return MODE_BINARY("a+", "ab+");
3333 return MODE_BINARY("a", "ab");
3335 switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
3336 case O_RDONLY:
3337 return MODE_BINARY("r", "rb");
3338 case O_WRONLY:
3339 return MODE_BINARY("w", "wb");
3340 case O_RDWR:
3341 return MODE_BINARY("r+", "rb+");
3343 rb_raise(rb_eArgError, "invalid access modenum %o", flags);
3344 return NULL; /* not reached */
3347 static void
3348 mode_enc(rb_io_t *fptr, const char *estr)
3350 const char *p0, *p1;
3351 char *enc2name;
3352 int idx, idx2;
3354 p0 = strrchr(estr, ':');
3355 if (!p0) p1 = estr;
3356 else p1 = p0 + 1;
3357 idx = rb_enc_find_index(p1);
3358 if (idx >= 0) {
3359 fptr->enc = rb_enc_from_index(idx);
3361 else {
3362 rb_warn("Unsupported encoding %s ignored", p1);
3365 if (p0) {
3366 int n = p0 - estr;
3367 if (n > ENCODING_MAXNAMELEN) {
3368 idx2 = -1;
3370 else {
3371 enc2name = ALLOCA_N(char, n+1);
3372 memcpy(enc2name, estr, n);
3373 enc2name[n] = '\0';
3374 estr = enc2name;
3375 idx2 = rb_enc_find_index(enc2name);
3377 if (idx2 < 0) {
3378 rb_warn("Unsupported encoding %.*s ignored", n, estr);
3380 else if (idx2 == idx) {
3381 rb_warn("Ignoring internal encoding %.*s: it is identical to external encoding %s",
3382 n, estr, p1);
3384 else {
3385 fptr->enc2 = rb_enc_from_index(idx2);
3390 void
3391 rb_io_mode_enc(rb_io_t *fptr, const char *mode)
3393 const char *p = strchr(mode, ':');
3394 if (p) {
3395 mode_enc(fptr, p+1);
3399 struct sysopen_struct {
3400 char *fname;
3401 int flag;
3402 unsigned int mode;
3405 static VALUE
3406 sysopen_func(void *ptr)
3408 struct sysopen_struct *data = ptr;
3409 return (VALUE)open(data->fname, data->flag, data->mode);
3412 static int
3413 rb_sysopen_internal(char *fname, int flags, unsigned int mode)
3415 struct sysopen_struct data;
3416 data.fname = fname;
3417 data.flag = flags;
3418 data.mode = mode;
3419 return (int)rb_thread_blocking_region(sysopen_func, &data, RB_UBF_DFL, 0);
3422 static int
3423 rb_sysopen(char *fname, int flags, unsigned int mode)
3425 int fd;
3427 fd = rb_sysopen_internal(fname, flags, mode);
3428 if (fd < 0) {
3429 if (errno == EMFILE || errno == ENFILE) {
3430 rb_gc();
3431 fd = rb_sysopen_internal(fname, flags, mode);
3433 if (fd < 0) {
3434 rb_sys_fail(fname);
3437 UPDATE_MAXFD(fd);
3438 return fd;
3441 FILE *
3442 rb_fopen(const char *fname, const char *mode)
3444 FILE *file;
3446 file = fopen(fname, mode);
3447 if (!file) {
3448 if (errno == EMFILE || errno == ENFILE) {
3449 rb_gc();
3450 file = fopen(fname, mode);
3452 if (!file) {
3453 rb_sys_fail(fname);
3456 #ifdef USE_SETVBUF
3457 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
3458 rb_warn("setvbuf() can't be honoured for %s", fname);
3459 #endif
3460 #ifdef __human68k__
3461 setmode(fileno(file), O_TEXT);
3462 #endif
3463 return file;
3466 FILE *
3467 rb_fdopen(int fd, const char *mode)
3469 FILE *file;
3471 #if defined(sun)
3472 errno = 0;
3473 #endif
3474 file = fdopen(fd, mode);
3475 if (!file) {
3476 if (
3477 #if defined(sun)
3478 errno == 0 ||
3479 #endif
3480 errno == EMFILE || errno == ENFILE) {
3481 rb_gc();
3482 #if defined(sun)
3483 errno = 0;
3484 #endif
3485 file = fdopen(fd, mode);
3487 if (!file) {
3488 #ifdef _WIN32
3489 if (errno == 0) errno = EINVAL;
3490 #elif defined(sun)
3491 if (errno == 0) errno = EMFILE;
3492 #endif
3493 rb_sys_fail(0);
3497 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
3498 #ifdef USE_SETVBUF
3499 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
3500 rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
3501 #endif
3502 return file;
3505 static void
3506 io_check_tty(rb_io_t *fptr)
3508 if (isatty(fptr->fd))
3509 fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
3512 static VALUE
3513 rb_file_open_internal(VALUE io, const char *fname, const char *mode)
3515 rb_io_t *fptr;
3517 MakeOpenFile(io, fptr);
3518 fptr->mode = rb_io_mode_flags(mode);
3519 rb_io_mode_enc(fptr, mode);
3520 fptr->path = strdup(fname);
3521 fptr->fd = rb_sysopen(fptr->path, rb_io_mode_modenum(rb_io_flags_mode(fptr->mode)), 0666);
3522 io_check_tty(fptr);
3524 return io;
3527 VALUE
3528 rb_file_open(const char *fname, const char *mode)
3530 return rb_file_open_internal(io_alloc(rb_cFile), fname, mode);
3533 static VALUE
3534 rb_file_sysopen_internal(VALUE io, const char *fname, int flags, int mode)
3536 rb_io_t *fptr;
3538 MakeOpenFile(io, fptr);
3540 fptr->path = strdup(fname);
3541 fptr->mode = rb_io_modenum_flags(flags);
3542 fptr->fd = rb_sysopen(fptr->path, flags, mode);
3543 io_check_tty(fptr);
3545 return io;
3548 VALUE
3549 rb_file_sysopen(const char *fname, int flags, int mode)
3551 return rb_file_sysopen_internal(io_alloc(rb_cFile), fname, flags, mode);
3554 #if defined(__CYGWIN__) || !defined(HAVE_FORK)
3555 static struct pipe_list {
3556 rb_io_t *fptr;
3557 struct pipe_list *next;
3558 } *pipe_list;
3560 static void
3561 pipe_add_fptr(rb_io_t *fptr)
3563 struct pipe_list *list;
3565 list = ALLOC(struct pipe_list);
3566 list->fptr = fptr;
3567 list->next = pipe_list;
3568 pipe_list = list;
3571 static void
3572 pipe_del_fptr(rb_io_t *fptr)
3574 struct pipe_list *list = pipe_list;
3575 struct pipe_list *tmp;
3577 if (list->fptr == fptr) {
3578 pipe_list = list->next;
3579 free(list);
3580 return;
3583 while (list->next) {
3584 if (list->next->fptr == fptr) {
3585 tmp = list->next;
3586 list->next = list->next->next;
3587 free(tmp);
3588 return;
3590 list = list->next;
3594 static void
3595 pipe_atexit(void)
3597 struct pipe_list *list = pipe_list;
3598 struct pipe_list *tmp;
3600 while (list) {
3601 tmp = list->next;
3602 rb_io_fptr_finalize(list->fptr);
3603 list = tmp;
3607 static void
3608 pipe_finalize(rb_io_t *fptr, int noraise)
3610 #if !defined(HAVE_FORK) && !defined(_WIN32)
3611 int status;
3612 if (fptr->stdio_file) {
3613 status = pclose(fptr->stdio_file);
3615 fptr->fd = -1;
3616 fptr->stdio_file = 0;
3617 #if defined DJGPP
3618 status <<= 8;
3619 #endif
3620 rb_last_status_set(status, fptr->pid);
3621 #else
3622 fptr_finalize(fptr, noraise);
3623 #endif
3624 pipe_del_fptr(fptr);
3626 #endif
3628 void
3629 rb_io_synchronized(rb_io_t *fptr)
3631 rb_io_check_initialized(fptr);
3632 fptr->mode |= FMODE_SYNC;
3635 void
3636 rb_io_unbuffered(rb_io_t *fptr)
3638 rb_io_synchronized(fptr);
3642 rb_pipe(int *pipes)
3644 int ret;
3645 ret = pipe(pipes);
3646 if (ret == -1) {
3647 if (errno == EMFILE || errno == ENFILE) {
3648 rb_gc();
3649 ret = pipe(pipes);
3652 if (ret == 0) {
3653 UPDATE_MAXFD(pipes[0]);
3654 UPDATE_MAXFD(pipes[1]);
3656 return ret;
3659 #ifdef HAVE_FORK
3660 struct popen_arg {
3661 struct rb_exec_arg *execp;
3662 int modef;
3663 int pair[2];
3664 int write_pair[2];
3667 static void
3668 popen_redirect(struct popen_arg *p)
3670 if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
3671 close(p->write_pair[1]);
3672 if (p->write_pair[0] != 0) {
3673 dup2(p->write_pair[0], 0);
3674 close(p->write_pair[0]);
3676 close(p->pair[0]);
3677 if (p->pair[1] != 1) {
3678 dup2(p->pair[1], 1);
3679 close(p->pair[1]);
3682 else if (p->modef & FMODE_READABLE) {
3683 close(p->pair[0]);
3684 if (p->pair[1] != 1) {
3685 dup2(p->pair[1], 1);
3686 close(p->pair[1]);
3689 else {
3690 close(p->pair[1]);
3691 if (p->pair[0] != 0) {
3692 dup2(p->pair[0], 0);
3693 close(p->pair[0]);
3698 void
3699 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
3701 int fd, ret;
3702 int max = max_file_descriptor;
3703 if (max < maxhint)
3704 max = maxhint;
3705 for (fd = lowfd; fd <= max; fd++) {
3706 if (!NIL_P(noclose_fds) &&
3707 RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd))))
3708 continue;
3709 #ifdef FD_CLOEXEC
3710 ret = fcntl(fd, F_GETFD);
3711 if (ret != -1 && !(ret & FD_CLOEXEC)) {
3712 fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
3714 #else
3715 close(fd);
3716 #endif
3720 static int
3721 popen_exec(void *pp)
3723 struct popen_arg *p = (struct popen_arg*)pp;
3725 rb_thread_atfork_before_exec();
3726 return rb_exec(p->execp);
3728 #endif
3730 static VALUE
3731 pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *mode)
3733 int modef = rb_io_mode_flags(mode);
3734 int pid = 0;
3735 rb_io_t *fptr;
3736 VALUE port;
3737 rb_io_t *write_fptr;
3738 VALUE write_port;
3739 #if defined(HAVE_FORK)
3740 int status;
3741 struct popen_arg arg;
3742 #elif defined(_WIN32)
3743 int openmode = rb_io_mode_modenum(mode);
3744 const char *exename = NULL;
3745 volatile VALUE cmdbuf;
3746 struct rb_exec_arg sarg;
3747 #endif
3748 FILE *fp = 0;
3749 int fd = -1;
3750 int write_fd = -1;
3751 const char *cmd = 0;
3752 int argc;
3753 VALUE *argv;
3755 if (prog)
3756 cmd = StringValueCStr(prog);
3758 if (!eargp) {
3759 /* fork : IO.popen("-") */
3760 argc = 0;
3761 argv = 0;
3763 else if (eargp->argc) {
3764 /* no shell : IO.popen([prog, arg0], arg1, ...) */
3765 argc = eargp->argc;
3766 argv = eargp->argv;
3768 else {
3769 /* with shell : IO.popen(prog) */
3770 argc = 0;
3771 argv = 0;
3774 #if defined(HAVE_FORK)
3775 arg.execp = eargp;
3776 arg.modef = modef;
3777 arg.pair[0] = arg.pair[1] = -1;
3778 arg.write_pair[0] = arg.write_pair[1] = -1;
3779 switch (modef & (FMODE_READABLE|FMODE_WRITABLE)) {
3780 case FMODE_READABLE|FMODE_WRITABLE:
3781 if (rb_pipe(arg.write_pair) < 0)
3782 rb_sys_fail(cmd);
3783 if (rb_pipe(arg.pair) < 0) {
3784 int e = errno;
3785 close(arg.write_pair[0]);
3786 close(arg.write_pair[1]);
3787 errno = e;
3788 rb_sys_fail(cmd);
3790 if (eargp) {
3791 rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.write_pair[0]));
3792 rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1]));
3794 break;
3795 case FMODE_READABLE:
3796 if (rb_pipe(arg.pair) < 0)
3797 rb_sys_fail(cmd);
3798 if (eargp)
3799 rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1]));
3800 break;
3801 case FMODE_WRITABLE:
3802 if (rb_pipe(arg.pair) < 0)
3803 rb_sys_fail(cmd);
3804 if (eargp)
3805 rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.pair[0]));
3806 break;
3807 default:
3808 rb_sys_fail(cmd);
3810 if (eargp) {
3811 rb_exec_arg_fixup(arg.execp);
3812 pid = rb_fork(&status, popen_exec, &arg, arg.execp->redirect_fds);
3814 else {
3815 fflush(stdin); /* is it really needed? */
3816 rb_io_flush(rb_stdout);
3817 rb_io_flush(rb_stderr);
3818 pid = rb_fork(&status, 0, 0, Qnil);
3819 if (pid == 0) { /* child */
3820 popen_redirect(&arg);
3821 rb_io_synchronized(RFILE(orig_stdout)->fptr);
3822 rb_io_synchronized(RFILE(orig_stderr)->fptr);
3823 return Qnil;
3827 /* parent */
3828 if (pid == -1) {
3829 int e = errno;
3830 close(arg.pair[0]);
3831 close(arg.pair[1]);
3832 if ((modef & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
3833 close(arg.write_pair[0]);
3834 close(arg.write_pair[1]);
3836 errno = e;
3837 rb_sys_fail(cmd);
3839 if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) {
3840 close(arg.pair[1]);
3841 fd = arg.pair[0];
3842 close(arg.write_pair[0]);
3843 write_fd = arg.write_pair[1];
3845 else if (modef & FMODE_READABLE) {
3846 close(arg.pair[1]);
3847 fd = arg.pair[0];
3849 else {
3850 close(arg.pair[0]);
3851 fd = arg.pair[1];
3853 #elif defined(_WIN32)
3854 if (argc) {
3855 volatile VALUE argbuf;
3856 char **args;
3857 int i;
3859 if (argc >= FIXNUM_MAX / sizeof(char *)) {
3860 rb_raise(rb_eArgError, "too many arguments");
3862 argbuf = rb_str_tmp_new((argc+1) * sizeof(char *));
3863 args = (void *)RSTRING_PTR(argbuf);
3864 for (i = 0; i < argc; ++i) {
3865 args[i] = StringValueCStr(argv[i]);
3867 args[i] = NULL;
3868 exename = cmd;
3869 cmdbuf = rb_str_tmp_new(rb_w32_argv_size(args));
3870 cmd = rb_w32_join_argv(RSTRING_PTR(cmdbuf), args);
3871 rb_str_resize(argbuf, 0);
3873 if (eargp) {
3874 rb_exec_arg_fixup(eargp);
3875 rb_run_exec_options(eargp, &sarg);
3877 while ((pid = rb_w32_pipe_exec(cmd, exename, openmode, &fd, &write_fd)) == -1) {
3878 /* exec failed */
3879 switch (errno) {
3880 case EAGAIN:
3881 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
3882 case EWOULDBLOCK:
3883 #endif
3884 rb_thread_sleep(1);
3885 break;
3886 default:
3887 if (eargp)
3888 rb_run_exec_options(&sarg, NULL);
3889 rb_sys_fail(cmd);
3890 break;
3893 if (eargp)
3894 rb_run_exec_options(&sarg, NULL);
3895 #else
3896 if (argc) {
3897 prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
3898 cmd = StringValueCStr(prog);
3900 if (eargp) {
3901 rb_exec_arg_fixup(eargp);
3902 rb_run_exec_options(eargp, &sarg);
3904 fp = popen(cmd, mode);
3905 if (eargp)
3906 rb_run_exec_options(&sarg, NULL);
3907 if (!fp) rb_sys_fail(RSTRING_PTR(prog));
3908 fd = fileno(fp);
3909 #endif
3911 port = io_alloc(rb_cIO);
3912 MakeOpenFile(port, fptr);
3913 fptr->fd = fd;
3914 fptr->stdio_file = fp;
3915 fptr->mode = modef | FMODE_SYNC|FMODE_DUPLEX;
3916 rb_io_mode_enc(fptr, mode);
3917 fptr->pid = pid;
3919 if (0 <= write_fd) {
3920 write_port = io_alloc(rb_cIO);
3921 MakeOpenFile(write_port, write_fptr);
3922 write_fptr->fd = write_fd;
3923 write_fptr->mode = (modef & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
3924 fptr->mode &= ~FMODE_WRITABLE;
3925 fptr->tied_io_for_writing = write_port;
3926 rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
3929 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
3930 fptr->finalize = pipe_finalize;
3931 pipe_add_fptr(fptr);
3932 #endif
3933 return port;
3936 static VALUE
3937 pipe_open_v(int argc, VALUE *argv, const char *mode)
3939 VALUE prog;
3940 struct rb_exec_arg earg;
3941 prog = rb_exec_arg_init(argc, argv, Qfalse, &earg);
3942 return pipe_open(&earg, prog, mode);
3945 static VALUE
3946 pipe_open_s(VALUE prog, const char *mode)
3948 const char *cmd = RSTRING_PTR(prog);
3949 int argc = 1;
3950 VALUE *argv = &prog;
3951 struct rb_exec_arg earg;
3953 if (RSTRING_LEN(prog) == 1 && cmd[0] == '-') {
3954 #if !defined(HAVE_FORK)
3955 rb_raise(rb_eNotImpError,
3956 "fork() function is unimplemented on this machine");
3957 #endif
3958 return pipe_open(0, 0, mode);
3961 rb_exec_arg_init(argc, argv, Qtrue, &earg);
3962 return pipe_open(&earg, prog, mode);
3966 * call-seq:
3967 * IO.popen(cmd, mode="r") => io
3968 * IO.popen(cmd, mode="r") {|io| block } => obj
3970 * Runs the specified command as a subprocess; the subprocess's
3971 * standard input and output will be connected to the returned
3972 * <code>IO</code> object. If _cmd_ is a +String+
3973 * ``<code>-</code>'', then a new instance of Ruby is started as the
3974 * subprocess. If <i>cmd</i> is an +Array+ of +String+, then it will
3975 * be used as the subprocess's +argv+ bypassing a shell.
3976 * The array can contains a hash at first for environments and
3977 * a hash at last for options similar to <code>spawn</code>. The default
3978 * mode for the new file object is ``r'', but <i>mode</i> may be set
3979 * to any of the modes listed in the description for class IO.
3981 * Raises exceptions which <code>IO::pipe</code> and
3982 * <code>Kernel::system</code> raise.
3984 * If a block is given, Ruby will run the command as a child connected
3985 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
3986 * parameter to the block.
3987 * At the end of block, Ruby close the pipe and sets <code>$?</code>.
3988 * In this case <code>IO::popen</code> returns
3989 * the value of the block.
3991 * If a block is given with a _cmd_ of ``<code>-</code>'',
3992 * the block will be run in two separate processes: once in the parent,
3993 * and once in a child. The parent process will be passed the pipe
3994 * object as a parameter to the block, the child version of the block
3995 * will be passed <code>nil</code>, and the child's standard in and
3996 * standard out will be connected to the parent through the pipe. Not
3997 * available on all platforms.
3999 * f = IO.popen("uname")
4000 * p f.readlines
4001 * puts "Parent is #{Process.pid}"
4002 * IO.popen("date") { |f| puts f.gets }
4003 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f}"}
4004 * p $?
4005 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
4006 * f.puts "bar"; f.close_write; puts f.gets
4009 * <em>produces:</em>
4011 * ["Linux\n"]
4012 * Parent is 26166
4013 * Wed Apr 9 08:53:52 CDT 2003
4014 * 26169 is here, f is
4015 * 26166 is here, f is #<IO:0x401b3d44>
4016 * #<Process::Status: pid=26166,exited(0)>
4017 * <foo>bar;zot;
4020 static VALUE
4021 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
4023 const char *mode;
4024 VALUE pname, pmode, port, tmp;
4026 if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) {
4027 mode = "r";
4029 else if (FIXNUM_P(pmode)) {
4030 mode = rb_io_modenum_mode(FIX2INT(pmode));
4032 else {
4033 mode = StringValueCStr(pmode);
4035 tmp = rb_check_array_type(pname);
4036 if (!NIL_P(tmp)) {
4037 tmp = rb_ary_dup(tmp);
4038 RBASIC(tmp)->klass = 0;
4039 port = pipe_open_v(RARRAY_LEN(tmp), RARRAY_PTR(tmp), mode);
4040 rb_ary_clear(tmp);
4042 else {
4043 SafeStringValue(pname);
4044 port = pipe_open_s(pname, mode);
4046 if (NIL_P(port)) {
4047 /* child */
4048 if (rb_block_given_p()) {
4049 rb_yield(Qnil);
4050 rb_io_flush(rb_stdout);
4051 rb_io_flush(rb_stderr);
4052 _exit(0);
4054 return Qnil;
4056 RBASIC(port)->klass = klass;
4057 if (rb_block_given_p()) {
4058 return rb_ensure(rb_yield, port, io_close, port);
4060 return port;
4063 static void
4064 io_set_encoding(VALUE io, VALUE opt)
4066 rb_io_t *fptr;
4067 VALUE encoding=Qnil, extenc=Qnil, intenc=Qnil;
4068 if (!NIL_P(opt)) {
4069 VALUE v;
4070 v = rb_hash_aref(opt, sym_encoding);
4071 if (!NIL_P(v)) encoding = v;
4072 v = rb_hash_aref(opt, sym_extenc);
4073 if (!NIL_P(v)) extenc = v;
4074 v = rb_hash_aref(opt, sym_intenc);
4075 if (!NIL_P(v)) intenc = v;
4077 if (!NIL_P(extenc)) {
4078 rb_encoding *extencoding = rb_to_encoding(extenc);
4079 GetOpenFile(io, fptr);
4080 if (!NIL_P(encoding)) {
4081 rb_warn("Ignoring encoding parameter '%s': external_encoding is used",
4082 RSTRING_PTR(encoding));
4084 if (!NIL_P(intenc)) {
4085 rb_encoding *intencoding = rb_to_encoding(intenc);
4086 if (extencoding == intencoding) {
4087 rb_warn("Ignoring internal encoding '%s': it is identical to external encoding '%s'",
4088 RSTRING_PTR(rb_inspect(intenc)),
4089 RSTRING_PTR(rb_inspect(extenc)));
4091 else {
4092 fptr->enc2 = intencoding;
4095 fptr->enc = extencoding;
4097 else {
4098 if (!NIL_P(intenc)) {
4099 rb_raise(rb_eArgError, "External encoding must be specified when internal encoding is given");
4101 if (!NIL_P(encoding)) {
4102 GetOpenFile(io, fptr);
4103 mode_enc(fptr, StringValueCStr(encoding));
4108 static VALUE
4109 rb_open_file(int argc, VALUE *argv, VALUE io)
4111 VALUE opt, fname, vmode, perm;
4112 const char *mode;
4113 int flags;
4114 unsigned int fmode;
4116 opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
4117 if (!NIL_P(opt)) {
4118 VALUE v;
4119 v = rb_hash_aref(opt, sym_mode);
4120 if (!NIL_P(v)) vmode = v;
4121 v = rb_hash_aref(opt, sym_perm);
4122 if (!NIL_P(v)) perm = v;
4123 argc -= 1;
4126 rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
4127 #if defined _WIN32 || defined __APPLE__
4129 static rb_encoding *fs_encoding;
4130 rb_encoding *fname_encoding = rb_enc_get(fname);
4131 if (!fs_encoding)
4132 fs_encoding = rb_filesystem_encoding();
4133 if (rb_usascii_encoding() != fname_encoding
4134 && rb_ascii8bit_encoding() != fname_encoding
4135 #if defined __APPLE__
4136 && rb_utf8_encoding() != fname_encoding
4137 #endif
4138 && fs_encoding != fname_encoding) {
4139 static VALUE fs_enc;
4140 if (!fs_enc)
4141 fs_enc = rb_enc_from_encoding(fs_encoding);
4142 fname = rb_str_transcode(fname, fs_enc);
4145 #endif
4146 FilePathValue(fname);
4148 if (FIXNUM_P(vmode) || !NIL_P(perm)) {
4149 if (FIXNUM_P(vmode)) {
4150 flags = FIX2INT(vmode);
4152 else {
4153 SafeStringValue(vmode);
4154 flags = rb_io_mode_modenum(StringValueCStr(vmode));
4156 fmode = NIL_P(perm) ? 0666 : NUM2UINT(perm);
4158 rb_file_sysopen_internal(io, RSTRING_PTR(fname), flags, fmode);
4160 else {
4161 mode = NIL_P(vmode) ? "r" : StringValueCStr(vmode);
4162 rb_file_open_internal(io, RSTRING_PTR(fname), mode);
4165 io_set_encoding(io, opt);
4166 return io;
4170 * call-seq:
4171 * IO.open(fd, mode_string="r" ) => io
4172 * IO.open(fd, mode_string="r" ) {|io| block } => obj
4174 * With no associated block, <code>open</code> is a synonym for
4175 * <code>IO::new</code>. If the optional code block is given, it will
4176 * be passed <i>io</i> as an argument, and the IO object will
4177 * automatically be closed when the block terminates. In this instance,
4178 * <code>IO::open</code> returns the value of the block.
4182 static VALUE
4183 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
4185 VALUE io = rb_class_new_instance(argc, argv, klass);
4187 if (rb_block_given_p()) {
4188 return rb_ensure(rb_yield, io, io_close, io);
4191 return io;
4195 * call-seq:
4196 * IO.sysopen(path, [mode, [perm]]) => fixnum
4198 * Opens the given path, returning the underlying file descriptor as a
4199 * <code>Fixnum</code>.
4201 * IO.sysopen("testfile") #=> 3
4205 static VALUE
4206 rb_io_s_sysopen(int argc, VALUE *argv)
4208 VALUE fname, vmode, perm;
4209 int flags, fd;
4210 unsigned int fmode;
4211 char *path;
4213 rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
4214 FilePathValue(fname);
4216 if (NIL_P(vmode)) flags = O_RDONLY;
4217 else if (FIXNUM_P(vmode)) flags = FIX2INT(vmode);
4218 else {
4219 SafeStringValue(vmode);
4220 flags = rb_io_mode_modenum(StringValueCStr(vmode));
4222 if (NIL_P(perm)) fmode = 0666;
4223 else fmode = NUM2UINT(perm);
4225 RB_GC_GUARD(fname) = rb_str_new4(fname);
4226 path = RSTRING_PTR(fname);
4227 fd = rb_sysopen(path, flags, fmode);
4228 return INT2NUM(fd);
4232 * call-seq:
4233 * open(path [, mode_enc [, perm]] ) => io or nil
4234 * open(path [, mode_enc [, perm]] ) {|io| block } => obj
4236 * Creates an <code>IO</code> object connected to the given stream,
4237 * file, or subprocess.
4239 * If <i>path</i> does not start with a pipe character
4240 * (``<code>|</code>''), treat it as the name of a file to open using
4241 * the specified mode (defaulting to ``<code>r</code>'').
4243 * The mode_enc is
4244 * either a string or an integer. If it is an integer, it must be
4245 * bitwise-or of open(2) flags, such as File::RDWR or File::EXCL.
4246 * If it is a string, it is either "mode", "mode:ext_enc", or
4247 * "mode:ext_enc:int_enc".
4248 * The mode is one of the following:
4250 * r: read (default)
4251 * w: write
4252 * a: append
4254 * The mode can be followed by "b" (means binary-mode), or "+"
4255 * (means both reading and writing allowed) or both.
4256 * If ext_enc (external encoding) is specified,
4257 * read string will be tagged by the encoding in reading,
4258 * and output string will be converted
4259 * to the specified encoding in writing.
4260 * If two encoding names,
4261 * ext_enc and int_enc (external encoding and internal encoding),
4262 * are specified, the read string is converted from ext_enc
4263 * to int_enc then tagged with the int_enc in read mode,
4264 * and in write mode, the output string will be
4265 * converted from int_enc to ext_enc before writing.
4267 * If a file is being created, its initial permissions may be
4268 * set using the integer third parameter.
4270 * If a block is specified, it will be invoked with the
4271 * <code>File</code> object as a parameter, and the file will be
4272 * automatically closed when the block terminates. The call
4273 * returns the value of the block.
4275 * If <i>path</i> starts with a pipe character, a subprocess is
4276 * created, connected to the caller by a pair of pipes. The returned
4277 * <code>IO</code> object may be used to write to the standard input
4278 * and read from the standard output of this subprocess. If the command
4279 * following the ``<code>|</code>'' is a single minus sign, Ruby forks,
4280 * and this subprocess is connected to the parent. In the subprocess,
4281 * the <code>open</code> call returns <code>nil</code>. If the command
4282 * is not ``<code>-</code>'', the subprocess runs the command. If a
4283 * block is associated with an <code>open("|-")</code> call, that block
4284 * will be run twice---once in the parent and once in the child. The
4285 * block parameter will be an <code>IO</code> object in the parent and
4286 * <code>nil</code> in the child. The parent's <code>IO</code> object
4287 * will be connected to the child's <code>$stdin</code> and
4288 * <code>$stdout</code>. The subprocess will be terminated at the end
4289 * of the block.
4291 * open("testfile") do |f|
4292 * print f.gets
4293 * end
4295 * <em>produces:</em>
4297 * This is line one
4299 * Open a subprocess and read its output:
4301 * cmd = open("|date")
4302 * print cmd.gets
4303 * cmd.close
4305 * <em>produces:</em>
4307 * Wed Apr 9 08:56:31 CDT 2003
4309 * Open a subprocess running the same Ruby program:
4311 * f = open("|-", "w+")
4312 * if f == nil
4313 * puts "in Child"
4314 * exit
4315 * else
4316 * puts "Got: #{f.gets}"
4317 * end
4319 * <em>produces:</em>
4321 * Got: in Child
4323 * Open a subprocess using a block to receive the I/O object:
4325 * open("|-") do |f|
4326 * if f == nil
4327 * puts "in Child"
4328 * else
4329 * puts "Got: #{f.gets}"
4330 * end
4331 * end
4333 * <em>produces:</em>
4335 * Got: in Child
4338 static VALUE
4339 rb_f_open(int argc, VALUE *argv)
4341 ID to_open = 0;
4342 int redirect = Qfalse;
4344 if (argc >= 1) {
4345 CONST_ID(to_open, "to_open");
4346 if (rb_respond_to(argv[0], to_open)) {
4347 redirect = Qtrue;
4349 else {
4350 VALUE tmp = argv[0];
4351 FilePathValue(tmp);
4352 if (NIL_P(tmp)) {
4353 redirect = Qtrue;
4355 else {
4356 char *str = StringValuePtr(tmp);
4357 if (str && str[0] == '|') {
4358 argv[0] = rb_str_new(str+1, RSTRING_LEN(tmp)-1);
4359 OBJ_INFECT(argv[0], tmp);
4360 return rb_io_s_popen(argc, argv, rb_cIO);
4365 if (redirect) {
4366 VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
4368 if (rb_block_given_p()) {
4369 return rb_ensure(rb_yield, io, io_close, io);
4371 return io;
4373 return rb_io_s_open(argc, argv, rb_cFile);
4376 static VALUE
4377 rb_io_open(const char *fname, const char *mode)
4379 if (fname[0] == '|') {
4380 VALUE cmd = rb_str_new2(fname+1);
4381 return pipe_open_s(cmd, mode);
4383 else {
4384 return rb_file_open(fname, mode);
4388 static VALUE
4389 rb_io_open_with_args(int argc, VALUE *argv)
4391 const char *mode;
4392 VALUE pname, pmode;
4394 if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) {
4395 mode = "r";
4397 else if (FIXNUM_P(pmode)) {
4398 mode = rb_io_modenum_mode(FIX2INT(pmode));
4400 else {
4401 mode = StringValueCStr(pmode);
4403 return rb_io_open(StringValueCStr(pname), mode);
4406 static VALUE
4407 io_reopen(VALUE io, VALUE nfile)
4409 rb_io_t *fptr, *orig;
4410 int fd, fd2;
4411 off_t pos = 0;
4413 nfile = rb_io_get_io(nfile);
4414 if (rb_safe_level() >= 4 && (!OBJ_TAINTED(io) || !OBJ_TAINTED(nfile))) {
4415 rb_raise(rb_eSecurityError, "Insecure: can't reopen");
4417 GetOpenFile(io, fptr);
4418 GetOpenFile(nfile, orig);
4420 if (fptr == orig) return io;
4421 if (IS_PREP_STDIO(fptr)) {
4422 if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
4423 (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
4424 (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
4425 rb_raise(rb_eArgError,
4426 "%s can't change access mode from \"%s\" to \"%s\"",
4427 PREP_STDIO_NAME(fptr), rb_io_flags_mode(fptr->mode),
4428 rb_io_flags_mode(orig->mode));
4431 if (orig->mode & FMODE_READABLE) {
4432 pos = io_tell(orig);
4434 if (orig->mode & FMODE_WRITABLE) {
4435 io_fflush(orig);
4437 if (fptr->mode & FMODE_WRITABLE) {
4438 io_fflush(fptr);
4441 /* copy rb_io_t structure */
4442 fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
4443 fptr->pid = orig->pid;
4444 fptr->lineno = orig->lineno;
4445 if (fptr->path) free(fptr->path);
4446 if (orig->path) fptr->path = strdup(orig->path);
4447 else fptr->path = 0;
4448 fptr->finalize = orig->finalize;
4450 fd = fptr->fd;
4451 fd2 = orig->fd;
4452 if (fd != fd2) {
4453 if (IS_PREP_STDIO(fptr)) {
4454 /* need to keep stdio objects */
4455 if (dup2(fd2, fd) < 0)
4456 rb_sys_fail(orig->path);
4458 else {
4459 if (fptr->stdio_file)
4460 fclose(fptr->stdio_file);
4461 else
4462 close(fptr->fd);
4463 fptr->stdio_file = 0;
4464 fptr->fd = -1;
4465 if (dup2(fd2, fd) < 0)
4466 rb_sys_fail(orig->path);
4467 fptr->fd = fd;
4469 rb_thread_fd_close(fd);
4470 if ((orig->mode & FMODE_READABLE) && pos >= 0) {
4471 if (io_seek(fptr, pos, SEEK_SET) < 0) {
4472 rb_sys_fail(fptr->path);
4474 if (io_seek(orig, pos, SEEK_SET) < 0) {
4475 rb_sys_fail(orig->path);
4480 if (fptr->mode & FMODE_BINMODE) {
4481 rb_io_binmode(io);
4484 RBASIC(io)->klass = RBASIC(nfile)->klass;
4485 return io;
4489 * call-seq:
4490 * ios.reopen(other_IO) => ios
4491 * ios.reopen(path, mode_str) => ios
4493 * Reassociates <em>ios</em> with the I/O stream given in
4494 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
4495 * dynamically change the actual class of this stream.
4497 * f1 = File.new("testfile")
4498 * f2 = File.new("testfile")
4499 * f2.readlines[0] #=> "This is line one\n"
4500 * f2.reopen(f1) #=> #<File:testfile>
4501 * f2.readlines[0] #=> "This is line one\n"
4504 static VALUE
4505 rb_io_reopen(int argc, VALUE *argv, VALUE file)
4507 VALUE fname, nmode;
4508 const char *mode;
4509 rb_io_t *fptr;
4511 rb_secure(4);
4512 if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
4513 VALUE tmp = rb_io_check_io(fname);
4514 if (!NIL_P(tmp)) {
4515 return io_reopen(file, tmp);
4519 FilePathValue(fname);
4520 rb_io_taint_check(file);
4521 fptr = RFILE(file)->fptr;
4522 if (!fptr) {
4523 fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
4524 MEMZERO(fptr, rb_io_t, 1);
4527 if (!NIL_P(nmode)) {
4528 int flags = rb_io_mode_flags(StringValueCStr(nmode));
4529 if (IS_PREP_STDIO(fptr) &&
4530 ((fptr->mode & FMODE_READWRITE) & (flags & FMODE_READWRITE)) !=
4531 (fptr->mode & FMODE_READWRITE)) {
4532 rb_raise(rb_eArgError,
4533 "%s can't change access mode from \"%s\" to \"%s\"",
4534 PREP_STDIO_NAME(fptr), rb_io_flags_mode(fptr->mode),
4535 rb_io_flags_mode(flags));
4537 fptr->mode = flags;
4538 rb_io_mode_enc(fptr, StringValueCStr(nmode));
4541 if (fptr->path) {
4542 free(fptr->path);
4543 fptr->path = 0;
4546 fptr->path = strdup(StringValueCStr(fname));
4547 mode = rb_io_flags_mode(fptr->mode);
4548 if (fptr->fd < 0) {
4549 fptr->fd = rb_sysopen(fptr->path, rb_io_mode_modenum(mode), 0666);
4550 fptr->stdio_file = 0;
4551 return file;
4554 if (fptr->mode & FMODE_WRITABLE) {
4555 io_fflush(fptr);
4557 fptr->rbuf_off = fptr->rbuf_len = 0;
4559 if (fptr->stdio_file) {
4560 if (freopen(fptr->path, mode, fptr->stdio_file) == 0) {
4561 rb_sys_fail(fptr->path);
4563 fptr->fd = fileno(fptr->stdio_file);
4564 #ifdef USE_SETVBUF
4565 if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
4566 rb_warn("setvbuf() can't be honoured for %s", fptr->path);
4567 #endif
4569 else {
4570 if (close(fptr->fd) < 0)
4571 rb_sys_fail(fptr->path);
4572 fptr->fd = -1;
4573 fptr->fd = rb_sysopen(fptr->path, rb_io_mode_modenum(mode), 0666);
4576 return file;
4579 /* :nodoc: */
4580 static VALUE
4581 rb_io_init_copy(VALUE dest, VALUE io)
4583 rb_io_t *fptr, *orig;
4584 int fd;
4585 VALUE write_io;
4587 io = rb_io_get_io(io);
4588 if (dest == io) return dest;
4589 GetOpenFile(io, orig);
4590 MakeOpenFile(dest, fptr);
4592 rb_io_flush(io);
4594 /* copy rb_io_t structure */
4595 fptr->mode = orig->mode & ~FMODE_PREP;
4596 fptr->pid = orig->pid;
4597 fptr->lineno = orig->lineno;
4598 if (orig->path) fptr->path = strdup(orig->path);
4599 fptr->finalize = orig->finalize;
4601 fd = ruby_dup(orig->fd);
4602 fptr->fd = fd;
4603 io_seek(fptr, io_tell(orig), SEEK_SET);
4604 if (fptr->mode & FMODE_BINMODE) {
4605 rb_io_binmode(dest);
4608 write_io = GetWriteIO(io);
4609 if (io != write_io) {
4610 write_io = rb_obj_dup(write_io);
4611 fptr->tied_io_for_writing = write_io;
4612 rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
4615 return dest;
4619 * call-seq:
4620 * ios.printf(format_string [, obj, ...] ) => nil
4622 * Formats and writes to <em>ios</em>, converting parameters under
4623 * control of the format string. See <code>Kernel#sprintf</code>
4624 * for details.
4627 VALUE
4628 rb_io_printf(int argc, VALUE *argv, VALUE out)
4630 rb_io_write(out, rb_f_sprintf(argc, argv));
4631 return Qnil;
4635 * call-seq:
4636 * printf(io, string [, obj ... ] ) => nil
4637 * printf(string [, obj ... ] ) => nil
4639 * Equivalent to:
4640 * io.write(sprintf(string, obj, ...)
4641 * or
4642 * $stdout.write(sprintf(string, obj, ...)
4645 static VALUE
4646 rb_f_printf(int argc, VALUE *argv)
4648 VALUE out;
4650 if (argc == 0) return Qnil;
4651 if (TYPE(argv[0]) == T_STRING) {
4652 out = rb_stdout;
4654 else {
4655 out = argv[0];
4656 argv++;
4657 argc--;
4659 rb_io_write(out, rb_f_sprintf(argc, argv));
4661 return Qnil;
4665 * call-seq:
4666 * ios.print() => nil
4667 * ios.print(obj, ...) => nil
4669 * Writes the given object(s) to <em>ios</em>. The stream must be
4670 * opened for writing. If the output record separator (<code>$\\</code>)
4671 * is not <code>nil</code>, it will be appended to the output. If no
4672 * arguments are given, prints <code>$_</code>. Objects that aren't
4673 * strings will be converted by calling their <code>to_s</code> method.
4674 * With no argument, prints the contents of the variable <code>$_</code>.
4675 * Returns <code>nil</code>.
4677 * $stdout.print("This is ", 100, " percent.\n")
4679 * <em>produces:</em>
4681 * This is 100 percent.
4684 VALUE
4685 rb_io_print(int argc, VALUE *argv, VALUE out)
4687 int i;
4688 VALUE line;
4690 /* if no argument given, print `$_' */
4691 if (argc == 0) {
4692 argc = 1;
4693 line = rb_lastline_get();
4694 argv = &line;
4696 for (i=0; i<argc; i++) {
4697 rb_io_write(out, argv[i]);
4698 if (!NIL_P(rb_output_fs)) {
4699 rb_io_write(out, rb_output_fs);
4702 if (argc > 0 && !NIL_P(rb_output_rs)) {
4703 rb_io_write(out, rb_output_rs);
4706 return Qnil;
4710 * call-seq:
4711 * print(obj, ...) => nil
4713 * Prints each object in turn to <code>$stdout</code>. If the output
4714 * field separator (<code>$,</code>) is not +nil+, its
4715 * contents will appear between each field. If the output record
4716 * separator (<code>$\\</code>) is not +nil+, it will be
4717 * appended to the output. If no arguments are given, prints
4718 * <code>$_</code>. Objects that aren't strings will be converted by
4719 * calling their <code>to_s</code> method.
4721 * print "cat", [1,2,3], 99, "\n"
4722 * $, = ", "
4723 * $\ = "\n"
4724 * print "cat", [1,2,3], 99
4726 * <em>produces:</em>
4728 * cat12399
4729 * cat, 1, 2, 3, 99
4732 static VALUE
4733 rb_f_print(int argc, VALUE *argv)
4735 rb_io_print(argc, argv, rb_stdout);
4736 return Qnil;
4740 * call-seq:
4741 * ios.putc(obj) => obj
4743 * If <i>obj</i> is <code>Numeric</code>, write the character whose
4744 * code is <i>obj</i>, otherwise write the first character of the
4745 * string representation of <i>obj</i> to <em>ios</em>.
4747 * $stdout.putc "A"
4748 * $stdout.putc 65
4750 * <em>produces:</em>
4752 * AA
4755 static VALUE
4756 rb_io_putc(VALUE io, VALUE ch)
4758 char c = NUM2CHR(ch);
4760 rb_io_write(io, rb_str_new(&c, 1));
4761 return ch;
4765 * call-seq:
4766 * putc(int) => int
4768 * Equivalent to:
4770 * $stdout.putc(int)
4773 static VALUE
4774 rb_f_putc(VALUE recv, VALUE ch)
4776 if (recv == rb_stdout) {
4777 return rb_io_putc(recv, ch);
4779 return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
4782 static VALUE
4783 io_puts_ary(VALUE ary, VALUE out, int recur)
4785 VALUE tmp;
4786 long i;
4788 if (recur) {
4789 tmp = rb_str_new2("[...]");
4790 rb_io_puts(1, &tmp, out);
4791 return Qnil;
4793 for (i=0; i<RARRAY_LEN(ary); i++) {
4794 tmp = RARRAY_PTR(ary)[i];
4795 rb_io_puts(1, &tmp, out);
4797 return Qnil;
4801 * call-seq:
4802 * ios.puts(obj, ...) => nil
4804 * Writes the given objects to <em>ios</em> as with
4805 * <code>IO#print</code>. Writes a record separator (typically a
4806 * newline) after any that do not already end with a newline sequence.
4807 * If called with an array argument, writes each element on a new line.
4808 * If called without arguments, outputs a single record separator.
4810 * $stdout.puts("this", "is", "a", "test")
4812 * <em>produces:</em>
4814 * this
4815 * is
4817 * test
4820 VALUE
4821 rb_io_puts(int argc, VALUE *argv, VALUE out)
4823 int i;
4824 VALUE line;
4826 /* if no argument given, print newline. */
4827 if (argc == 0) {
4828 rb_io_write(out, rb_default_rs);
4829 return Qnil;
4831 for (i=0; i<argc; i++) {
4832 line = rb_check_array_type(argv[i]);
4833 if (!NIL_P(line)) {
4834 rb_exec_recursive(io_puts_ary, line, out);
4835 continue;
4837 line = rb_obj_as_string(argv[i]);
4838 rb_io_write(out, line);
4839 if (RSTRING_LEN(line) == 0 ||
4840 RSTRING_PTR(line)[RSTRING_LEN(line)-1] != '\n') {
4841 rb_io_write(out, rb_default_rs);
4845 return Qnil;
4849 * call-seq:
4850 * puts(obj, ...) => nil
4852 * Equivalent to
4854 * $stdout.puts(obj, ...)
4857 static VALUE
4858 rb_f_puts(int argc, VALUE *argv, VALUE recv)
4860 if (recv == rb_stdout) {
4861 return rb_io_puts(argc, argv, recv);
4863 return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
4866 void
4867 rb_p(VALUE obj) /* for debug print within C code */
4869 VALUE str = rb_obj_as_string(rb_inspect(obj));
4870 rb_str_buf_append(str, rb_default_rs);
4871 rb_io_write(rb_stdout, str);
4875 * call-seq:
4876 * p(obj) => obj
4877 * p(obj1, obj2, ...) => [obj, ...]
4878 * p() => nil
4880 * For each object, directly writes
4881 * _obj_.+inspect+ followed by the current output
4882 * record separator to the program's standard output.
4884 * S = Struct.new(:name, :state)
4885 * s = S['dave', 'TX']
4886 * p s
4888 * <em>produces:</em>
4890 * #<S name="dave", state="TX">
4893 static VALUE
4894 rb_f_p(int argc, VALUE *argv, VALUE self)
4896 int i;
4897 VALUE ret = Qnil;
4899 for (i=0; i<argc; i++) {
4900 rb_p(argv[i]);
4902 if (argc == 1) {
4903 ret = argv[0];
4905 else if (argc > 1) {
4906 ret = rb_ary_new4(argc, argv);
4908 if (TYPE(rb_stdout) == T_FILE) {
4909 rb_io_flush(rb_stdout);
4911 return ret;
4915 * call-seq:
4916 * obj.display(port=$>) => nil
4918 * Prints <i>obj</i> on the given port (default <code>$></code>).
4919 * Equivalent to:
4921 * def display(port=$>)
4922 * port.write self
4923 * end
4925 * For example:
4927 * 1.display
4928 * "cat".display
4929 * [ 4, 5, 6 ].display
4930 * puts
4932 * <em>produces:</em>
4934 * 1cat456
4937 static VALUE
4938 rb_obj_display(int argc, VALUE *argv, VALUE self)
4940 VALUE out;
4942 if (argc == 0) {
4943 out = rb_stdout;
4945 else {
4946 rb_scan_args(argc, argv, "01", &out);
4948 rb_io_write(out, self);
4950 return Qnil;
4953 void
4954 rb_write_error2(const char *mesg, long len)
4956 if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
4957 fwrite(mesg, sizeof(char), len, stderr);
4959 else {
4960 rb_io_write(rb_stderr, rb_str_new(mesg, len));
4964 void
4965 rb_write_error(const char *mesg)
4967 rb_write_error2(mesg, strlen(mesg));
4970 static void
4971 must_respond_to(ID mid, VALUE val, ID id)
4973 if (!rb_respond_to(val, mid)) {
4974 rb_raise(rb_eTypeError, "%s must have %s method, %s given",
4975 rb_id2name(id), rb_id2name(mid),
4976 rb_obj_classname(val));
4980 static void
4981 stdout_setter(VALUE val, ID id, VALUE *variable)
4983 must_respond_to(id_write, val, id);
4984 *variable = val;
4987 static VALUE
4988 prep_io(int fd, int mode, VALUE klass, const char *path)
4990 rb_io_t *fp;
4991 VALUE io = io_alloc(klass);
4993 MakeOpenFile(io, fp);
4994 fp->fd = fd;
4995 #ifdef __CYGWIN__
4996 if (!isatty(fd)) {
4997 mode |= O_BINARY;
4998 setmode(fd, O_BINARY);
5000 #endif
5001 fp->mode = mode;
5002 io_check_tty(fp);
5003 if (path) fp->path = strdup(path);
5005 return io;
5008 VALUE
5009 rb_io_fdopen(int fd, int mode, const char *path)
5011 VALUE klass = rb_cIO;
5013 if (path && strcmp(path, "-")) klass = rb_cFile;
5014 return prep_io(fd, rb_io_modenum_flags(mode), klass, path);
5017 static VALUE
5018 prep_stdio(FILE *f, int mode, VALUE klass, const char *path)
5020 rb_io_t *fptr;
5021 VALUE io = prep_io(fileno(f), mode|FMODE_PREP, klass, path);
5023 GetOpenFile(io, fptr);
5024 fptr->stdio_file = f;
5026 return io;
5029 FILE *
5030 rb_io_stdio_file(rb_io_t *fptr)
5032 if (!fptr->stdio_file) {
5033 fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_flags_mode(fptr->mode));
5035 return fptr->stdio_file;
5039 * call-seq:
5040 * IO.new(fd, mode) => io
5042 * Returns a new <code>IO</code> object (a stream) for the given
5043 * <code>IO</code> object or integer file descriptor and mode
5044 * string. See also <code>IO#fileno</code> and
5045 * <code>IO::for_fd</code>.
5047 * puts IO.new($stdout).fileno # => 1
5049 * a = IO.new(2,"w") # '2' is standard error
5050 * $stderr.puts "Hello"
5051 * a.puts "World"
5053 * <em>produces:</em>
5055 * Hello
5056 * World
5059 static VALUE
5060 rb_io_initialize(int argc, VALUE *argv, VALUE io)
5062 VALUE fnum, mode, orig;
5063 rb_io_t *fp, *ofp = NULL;
5064 int fd, fmode, flags = O_RDONLY;
5066 rb_secure(4);
5067 rb_scan_args(argc, argv, "11", &fnum, &mode);
5068 if (argc == 2) {
5069 if (FIXNUM_P(mode)) {
5070 flags = FIX2LONG(mode);
5072 else {
5073 SafeStringValue(mode);
5074 flags = rb_io_mode_modenum(StringValueCStr(mode));
5077 orig = rb_io_check_io(fnum);
5078 if (NIL_P(orig)) {
5079 fd = NUM2INT(fnum);
5080 UPDATE_MAXFD(fd);
5081 if (argc != 2) {
5082 #if defined(HAVE_FCNTL) && defined(F_GETFL)
5083 flags = fcntl(fd, F_GETFL);
5084 if (flags == -1) rb_sys_fail(0);
5085 #endif
5087 MakeOpenFile(io, fp);
5088 fp->fd = fd;
5089 fp->mode = rb_io_modenum_flags(flags);
5090 io_check_tty(fp);
5092 else if (RFILE(io)->fptr) {
5093 rb_raise(rb_eRuntimeError, "reinitializing IO");
5095 else {
5096 GetOpenFile(orig, ofp);
5097 if (ofp->refcnt == LONG_MAX) {
5098 VALUE s = rb_inspect(orig);
5099 rb_raise(rb_eIOError, "too many shared IO for %s", StringValueCStr(s));
5101 if (argc == 2) {
5102 fmode = rb_io_modenum_flags(flags);
5103 if ((ofp->mode ^ fmode) & (FMODE_READWRITE|FMODE_BINMODE)) {
5104 if (FIXNUM_P(mode)) {
5105 rb_raise(rb_eArgError, "incompatible mode 0%o", flags);
5107 else {
5108 rb_raise(rb_eArgError, "incompatible mode \"%s\"", RSTRING_PTR(mode));
5112 ofp->refcnt++;
5113 RFILE(io)->fptr = ofp;
5116 return io;
5121 * call-seq:
5122 * File.new(filename, mode="r") => file
5123 * File.new(filename [, mode [, perm]]) => file
5126 * Opens the file named by _filename_ according to
5127 * _mode_ (default is ``r'') and returns a new
5128 * <code>File</code> object. See the description of class +IO+ for
5129 * a description of _mode_. The file mode may optionally be
5130 * specified as a +Fixnum+ by _or_-ing together the
5131 * flags (O_RDONLY etc, again described under +IO+). Optional
5132 * permission bits may be given in _perm_. These mode and permission
5133 * bits are platform dependent; on Unix systems, see
5134 * <code>open(2)</code> for details.
5136 * f = File.new("testfile", "r")
5137 * f = File.new("newfile", "w+")
5138 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
5141 static VALUE
5142 rb_file_initialize(int argc, VALUE *argv, VALUE io)
5144 if (RFILE(io)->fptr) {
5145 rb_raise(rb_eRuntimeError, "reinitializing File");
5147 if (0 < argc && argc < 3) {
5148 VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
5150 if (!NIL_P(fd)) {
5151 argv[0] = fd;
5152 return rb_io_initialize(argc, argv, io);
5155 rb_open_file(argc, argv, io);
5157 return io;
5161 * call-seq:
5162 * IO.new(fd, mode_string) => io
5164 * Returns a new <code>IO</code> object (a stream) for the given
5165 * integer file descriptor and mode string. See also
5166 * <code>IO#fileno</code> and <code>IO::for_fd</code>.
5168 * a = IO.new(2,"w") # '2' is standard error
5169 * $stderr.puts "Hello"
5170 * a.puts "World"
5172 * <em>produces:</em>
5174 * Hello
5175 * World
5178 static VALUE
5179 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
5181 if (rb_block_given_p()) {
5182 const char *cname = rb_class2name(klass);
5184 rb_warn("%s::new() does not take block; use %s::open() instead",
5185 cname, cname);
5187 return rb_class_new_instance(argc, argv, klass);
5192 * call-seq:
5193 * IO.for_fd(fd, mode) => io
5195 * Synonym for <code>IO::new</code>.
5199 static VALUE
5200 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
5202 VALUE io = rb_obj_alloc(klass);
5203 rb_io_initialize(argc, argv, io);
5204 return io;
5207 static void
5208 argf_mark(void *ptr)
5210 struct argf *p = ptr;
5211 rb_gc_mark(p->filename);
5212 rb_gc_mark(p->current_file);
5213 rb_gc_mark(p->lineno);
5214 rb_gc_mark(p->argv);
5217 static void
5218 argf_free(void *ptr)
5220 struct argf *p = ptr;
5221 free(p->inplace);
5224 static inline void
5225 argf_init(struct argf *p, VALUE v)
5227 p->filename = Qnil;
5228 p->current_file = Qnil;
5229 p->lineno = Qnil;
5230 p->argv = v;
5233 static VALUE
5234 argf_alloc(VALUE klass)
5236 struct argf *p;
5237 VALUE argf = Data_Make_Struct(klass, struct argf, argf_mark, argf_free, p);
5239 argf_init(p, Qnil);
5240 return argf;
5243 #undef rb_argv
5244 #define filename ARGF.filename
5245 #define current_file ARGF.current_file
5246 #define gets_lineno ARGF.gets_lineno
5247 #define init_p ARGF.init_p
5248 #define next_p ARGF.next_p
5249 #define lineno ARGF.lineno
5250 #define ruby_inplace_mode ARGF.inplace
5251 #define argf_binmode ARGF.binmode
5252 #define argf_enc ARGF.enc
5253 #define argf_enc2 ARGF.enc2
5254 #define rb_argv ARGF.argv
5256 static VALUE
5257 argf_initialize(VALUE argf, VALUE argv)
5259 memset(&ARGF, 0, sizeof(ARGF));
5260 argf_init(&ARGF, argv);
5262 return argf;
5265 static VALUE
5266 argf_initialize_copy(VALUE argf, VALUE orig)
5268 ARGF = argf_of(orig);
5269 rb_argv = rb_obj_dup(rb_argv);
5270 if (ARGF.inplace) {
5271 const char *inplace = ARGF.inplace;
5272 ARGF.inplace = 0;
5273 ARGF.inplace = ruby_strdup(inplace);
5275 return argf;
5278 static VALUE
5279 argf_set_lineno(VALUE argf, VALUE val)
5281 gets_lineno = NUM2INT(val);
5282 lineno = INT2FIX(gets_lineno);
5283 return Qnil;
5286 static VALUE
5287 argf_lineno(VALUE argf)
5289 return lineno;
5292 static VALUE
5293 argf_forward(int argc, VALUE *argv, VALUE argf)
5295 return rb_funcall3(current_file, rb_frame_this_func(), argc, argv);
5298 #define next_argv() argf_next_argv(argf)
5299 #define ARGF_GENERIC_INPUT_P() \
5300 (current_file == rb_stdin && TYPE(current_file) != T_FILE)
5301 #define ARGF_FORWARD(argc, argv) do {\
5302 if (ARGF_GENERIC_INPUT_P())\
5303 return argf_forward(argc, argv, argf);\
5304 } while (0)
5305 #define NEXT_ARGF_FORWARD(argc, argv) do {\
5306 if (!next_argv()) return Qnil;\
5307 ARGF_FORWARD(argc, argv);\
5308 } while (0)
5310 static void
5311 argf_close(VALUE file)
5313 rb_funcall3(file, rb_intern("close"), 0, 0);
5316 static int
5317 argf_next_argv(VALUE argf)
5319 char *fn;
5320 rb_io_t *fptr;
5321 int stdout_binmode = 0;
5323 if (TYPE(rb_stdout) == T_FILE) {
5324 GetOpenFile(rb_stdout, fptr);
5325 if (fptr->mode & FMODE_BINMODE)
5326 stdout_binmode = 1;
5329 if (init_p == 0) {
5330 if (!NIL_P(rb_argv) && RARRAY_LEN(rb_argv) > 0) {
5331 next_p = 1;
5333 else {
5334 next_p = -1;
5336 init_p = 1;
5337 gets_lineno = 0;
5340 if (next_p == 1) {
5341 next_p = 0;
5342 retry:
5343 if (RARRAY_LEN(rb_argv) > 0) {
5344 filename = rb_ary_shift(rb_argv);
5345 fn = StringValueCStr(filename);
5346 if (strlen(fn) == 1 && fn[0] == '-') {
5347 current_file = rb_stdin;
5348 if (ruby_inplace_mode) {
5349 rb_warn("Can't do inplace edit for stdio; skipping");
5350 goto retry;
5353 else {
5354 int fr = rb_sysopen(fn, O_RDONLY, 0);
5356 if (ruby_inplace_mode) {
5357 struct stat st;
5358 #ifndef NO_SAFE_RENAME
5359 struct stat st2;
5360 #endif
5361 VALUE str;
5362 int fw;
5364 if (TYPE(rb_stdout) == T_FILE && rb_stdout != orig_stdout) {
5365 rb_io_close(rb_stdout);
5367 fstat(fr, &st);
5368 if (*ruby_inplace_mode) {
5369 str = rb_str_new2(fn);
5370 #ifdef NO_LONG_FNAME
5371 ruby_add_suffix(str, ruby_inplace_mode);
5372 #else
5373 rb_str_cat2(str, ruby_inplace_mode);
5374 #endif
5375 #ifdef NO_SAFE_RENAME
5376 (void)close(fr);
5377 (void)unlink(RSTRING_PTR(str));
5378 (void)rename(fn, RSTRING_PTR(str));
5379 fr = rb_sysopen(RSTRING_PTR(str), O_RDONLY, 0);
5380 #else
5381 if (rename(fn, RSTRING_PTR(str)) < 0) {
5382 rb_warn("Can't rename %s to %s: %s, skipping file",
5383 fn, RSTRING_PTR(str), strerror(errno));
5384 close(fr);
5385 goto retry;
5387 #endif
5389 else {
5390 #ifdef NO_SAFE_RENAME
5391 rb_fatal("Can't do inplace edit without backup");
5392 #else
5393 if (unlink(fn) < 0) {
5394 rb_warn("Can't remove %s: %s, skipping file",
5395 fn, strerror(errno));
5396 close(fr);
5397 goto retry;
5399 #endif
5401 fw = rb_sysopen(fn, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5402 #ifndef NO_SAFE_RENAME
5403 fstat(fw, &st2);
5404 #ifdef HAVE_FCHMOD
5405 fchmod(fw, st.st_mode);
5406 #else
5407 chmod(fn, st.st_mode);
5408 #endif
5409 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
5410 fchown(fw, st.st_uid, st.st_gid);
5412 #endif
5413 rb_stdout = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
5414 if (stdout_binmode) rb_io_binmode(rb_stdout);
5416 current_file = prep_io(fr, FMODE_READABLE, rb_cFile, fn);
5418 if (argf_binmode) rb_io_binmode(current_file);
5419 if (argf_enc) {
5420 rb_io_t *fptr;
5422 GetOpenFile(current_file, fptr);
5423 fptr->enc = argf_enc;
5424 fptr->enc2 = argf_enc2;
5427 else {
5428 next_p = 1;
5429 return Qfalse;
5432 else if (next_p == -1) {
5433 current_file = rb_stdin;
5434 filename = rb_str_new2("-");
5435 if (ruby_inplace_mode) {
5436 rb_warn("Can't do inplace edit for stdio");
5437 rb_stdout = orig_stdout;
5440 return Qtrue;
5443 static VALUE
5444 argf_getline(int argc, VALUE *argv, VALUE argf)
5446 VALUE line;
5448 retry:
5449 if (!next_argv()) return Qnil;
5450 if (ARGF_GENERIC_INPUT_P()) {
5451 line = rb_funcall3(current_file, rb_intern("gets"), argc, argv);
5453 else {
5454 if (argc == 0 && rb_rs == rb_default_rs) {
5455 line = rb_io_gets(current_file);
5457 else {
5458 line = rb_io_getline(argc, argv, current_file);
5460 if (NIL_P(line) && next_p != -1) {
5461 argf_close(current_file);
5462 next_p = 1;
5463 goto retry;
5466 if (!NIL_P(line)) {
5467 gets_lineno++;
5468 lineno = INT2FIX(gets_lineno);
5470 return line;
5473 static VALUE
5474 argf_lineno_getter(ID id, VALUE *var)
5476 VALUE argf = *var;
5477 return lineno;
5480 static void
5481 argf_lineno_setter(VALUE val, ID id, VALUE *var)
5483 VALUE argf = *var;
5484 int n = NUM2INT(val);
5485 gets_lineno = n;
5486 lineno = INT2FIX(n);
5489 static VALUE argf_gets(int, VALUE *, VALUE);
5492 * call-seq:
5493 * gets(sep=$/) => string or nil
5494 * gets(limit) => string or nil
5495 * gets(sep,limit) => string or nil
5497 * Returns (and assigns to <code>$_</code>) the next line from the list
5498 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
5499 * no files are present on the command line. Returns +nil+ at end of
5500 * file. The optional argument specifies the record separator. The
5501 * separator is included with the contents of each record. A separator
5502 * of +nil+ reads the entire contents, and a zero-length separator
5503 * reads the input one paragraph at a time, where paragraphs are
5504 * divided by two consecutive newlines. If the first argument is an
5505 * integer, or optional second argument is given, the returning string
5506 * would not be longer than the given value. If multiple filenames are
5507 * present in +ARGV+, +gets(nil)+ will read the contents one file at a
5508 * time.
5510 * ARGV << "testfile"
5511 * print while gets
5513 * <em>produces:</em>
5515 * This is line one
5516 * This is line two
5517 * This is line three
5518 * And so on...
5520 * The style of programming using <code>$_</code> as an implicit
5521 * parameter is gradually losing favor in the Ruby community.
5524 static VALUE
5525 rb_f_gets(int argc, VALUE *argv, VALUE recv)
5527 if (recv == argf) {
5528 return argf_gets(argc, argv, argf);
5530 return rb_funcall2(argf, rb_intern("gets"), argc, argv);
5533 static VALUE
5534 argf_gets(int argc, VALUE *argv, VALUE argf)
5536 VALUE line;
5538 line = argf_getline(argc, argv, argf);
5539 rb_lastline_set(line);
5540 return line;
5543 VALUE
5544 rb_gets(void)
5546 VALUE line;
5548 if (rb_rs != rb_default_rs) {
5549 return rb_f_gets(0, 0, argf);
5552 retry:
5553 if (!next_argv()) return Qnil;
5554 line = rb_io_gets(current_file);
5555 if (NIL_P(line) && next_p != -1) {
5556 rb_io_close(current_file);
5557 next_p = 1;
5558 goto retry;
5560 rb_lastline_set(line);
5561 if (!NIL_P(line)) {
5562 gets_lineno++;
5563 lineno = INT2FIX(gets_lineno);
5566 return line;
5569 static VALUE argf_readline(int, VALUE *, VALUE);
5572 * call-seq:
5573 * readline(sep=$/) => string
5574 * readline(limit) => string
5575 * readline(sep, limit) => string
5577 * Equivalent to <code>Kernel::gets</code>, except
5578 * +readline+ raises +EOFError+ at end of file.
5581 static VALUE
5582 rb_f_readline(int argc, VALUE *argv, VALUE recv)
5584 if (recv == argf) {
5585 return argf_readline(argc, argv, argf);
5587 return rb_funcall2(argf, rb_intern("readline"), argc, argv);
5590 static VALUE
5591 argf_readline(int argc, VALUE *argv, VALUE argf)
5593 VALUE line;
5595 if (!next_argv()) rb_eof_error();
5596 ARGF_FORWARD(argc, argv);
5597 line = argf_gets(argc, argv, argf);
5598 if (NIL_P(line)) {
5599 rb_eof_error();
5602 return line;
5605 static VALUE argf_readlines(int, VALUE *, VALUE);
5608 * call-seq:
5609 * readlines(sep=$/) => array
5610 * readlines(limit) => array
5611 * readlines(sep,limit) => array
5613 * Returns an array containing the lines returned by calling
5614 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
5617 static VALUE
5618 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
5620 if (recv == argf) {
5621 return argf_readlines(argc, argv, argf);
5623 return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
5626 static VALUE
5627 argf_readlines(int argc, VALUE *argv, VALUE argf)
5629 VALUE line, ary;
5631 ary = rb_ary_new();
5632 while (!NIL_P(line = argf_getline(argc, argv, argf))) {
5633 rb_ary_push(ary, line);
5636 return ary;
5640 * call-seq:
5641 * `cmd` => string
5643 * Returns the standard output of running _cmd_ in a subshell.
5644 * The built-in syntax <code>%x{...}</code> uses
5645 * this method. Sets <code>$?</code> to the process status.
5647 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
5648 * `ls testdir`.split[1] #=> "main.rb"
5649 * `echo oops && exit 99` #=> "oops\n"
5650 * $?.exitstatus #=> 99
5653 static VALUE
5654 rb_f_backquote(VALUE obj, VALUE str)
5656 volatile VALUE port;
5657 VALUE result;
5658 rb_io_t *fptr;
5660 SafeStringValue(str);
5661 port = pipe_open_s(str, "r");
5662 if (NIL_P(port)) return rb_str_new(0,0);
5664 GetOpenFile(port, fptr);
5665 result = read_all(fptr, remain_size(fptr), Qnil);
5666 rb_io_close(port);
5668 return result;
5671 #ifdef HAVE_SYS_SELECT_H
5672 #include <sys/select.h>
5673 #endif
5675 static VALUE
5676 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
5678 VALUE res, list;
5679 fd_set *rp, *wp, *ep;
5680 rb_io_t *fptr;
5681 long i;
5682 int max = 0, n;
5683 int interrupt_flag = 0;
5684 int pending = 0;
5685 struct timeval timerec;
5687 if (!NIL_P(read)) {
5688 Check_Type(read, T_ARRAY);
5689 for (i=0; i<RARRAY_LEN(read); i++) {
5690 GetOpenFile(rb_io_get_io(RARRAY_PTR(read)[i]), fptr);
5691 rb_fd_set(fptr->fd, &fds[0]);
5692 if (READ_DATA_PENDING(fptr)) { /* check for buffered data */
5693 pending++;
5694 rb_fd_set(fptr->fd, &fds[3]);
5696 if (max < fptr->fd) max = fptr->fd;
5698 if (pending) { /* no blocking if there's buffered data */
5699 timerec.tv_sec = timerec.tv_usec = 0;
5700 tp = &timerec;
5702 rp = rb_fd_ptr(&fds[0]);
5704 else
5705 rp = 0;
5707 if (!NIL_P(write)) {
5708 Check_Type(write, T_ARRAY);
5709 for (i=0; i<RARRAY_LEN(write); i++) {
5710 VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_PTR(write)[i]));
5711 GetOpenFile(write_io, fptr);
5712 rb_fd_set(fptr->fd, &fds[1]);
5713 if (max < fptr->fd) max = fptr->fd;
5715 wp = rb_fd_ptr(&fds[1]);
5717 else
5718 wp = 0;
5720 if (!NIL_P(except)) {
5721 Check_Type(except, T_ARRAY);
5722 for (i=0; i<RARRAY_LEN(except); i++) {
5723 VALUE io = rb_io_get_io(RARRAY_PTR(except)[i]);
5724 VALUE write_io = GetWriteIO(io);
5725 GetOpenFile(io, fptr);
5726 rb_fd_set(fptr->fd, &fds[2]);
5727 if (max < fptr->fd) max = fptr->fd;
5728 if (io != write_io) {
5729 GetOpenFile(write_io, fptr);
5730 rb_fd_set(fptr->fd, &fds[2]);
5731 if (max < fptr->fd) max = fptr->fd;
5734 ep = rb_fd_ptr(&fds[2]);
5736 else {
5737 ep = 0;
5740 max++;
5742 n = rb_thread_select(max, rp, wp, ep, tp);
5743 if (n < 0) {
5744 rb_sys_fail(0);
5746 if (!pending && n == 0) return Qnil; /* returns nil on timeout */
5748 res = rb_ary_new2(3);
5749 rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
5750 rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
5751 rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
5753 if (interrupt_flag == 0) {
5754 if (rp) {
5755 list = RARRAY_PTR(res)[0];
5756 for (i=0; i< RARRAY_LEN(read); i++) {
5757 VALUE obj = rb_ary_entry(read, i);
5758 VALUE io = rb_io_get_io(obj);
5759 GetOpenFile(io, fptr);
5760 if (rb_fd_isset(fptr->fd, &fds[0]) ||
5761 rb_fd_isset(fptr->fd, &fds[3])) {
5762 rb_ary_push(list, obj);
5767 if (wp) {
5768 list = RARRAY_PTR(res)[1];
5769 for (i=0; i< RARRAY_LEN(write); i++) {
5770 VALUE obj = rb_ary_entry(write, i);
5771 VALUE io = rb_io_get_io(obj);
5772 VALUE write_io = GetWriteIO(io);
5773 GetOpenFile(write_io, fptr);
5774 if (rb_fd_isset(fptr->fd, &fds[1])) {
5775 rb_ary_push(list, obj);
5780 if (ep) {
5781 list = RARRAY_PTR(res)[2];
5782 for (i=0; i< RARRAY_LEN(except); i++) {
5783 VALUE obj = rb_ary_entry(except, i);
5784 VALUE io = rb_io_get_io(obj);
5785 VALUE write_io = GetWriteIO(io);
5786 GetOpenFile(io, fptr);
5787 if (rb_fd_isset(fptr->fd, &fds[2])) {
5788 rb_ary_push(list, obj);
5790 else if (io != write_io) {
5791 GetOpenFile(write_io, fptr);
5792 if (rb_fd_isset(fptr->fd, &fds[2])) {
5793 rb_ary_push(list, obj);
5800 return res; /* returns an empty array on interrupt */
5803 struct select_args {
5804 VALUE read, write, except;
5805 struct timeval *timeout;
5806 rb_fdset_t fdsets[4];
5809 #ifdef HAVE_RB_FD_INIT
5810 static VALUE
5811 select_call(VALUE arg)
5813 struct select_args *p = (struct select_args *)arg;
5815 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
5818 static VALUE
5819 select_end(VALUE arg)
5821 struct select_args *p = (struct select_args *)arg;
5822 int i;
5824 for (i = 0; i < sizeof(p->fdsets) / sizeof(p->fdsets[0]); ++i)
5825 rb_fd_term(&p->fdsets[i]);
5826 return Qnil;
5828 #endif
5831 * call-seq:
5832 * IO.select(read_array
5833 * [, write_array
5834 * [, error_array
5835 * [, timeout]]] ) => array or nil
5837 * See <code>Kernel#select</code>.
5840 static VALUE
5841 rb_f_select(int argc, VALUE *argv, VALUE obj)
5843 VALUE timeout;
5844 struct select_args args;
5845 struct timeval timerec;
5846 int i;
5848 rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
5849 if (NIL_P(timeout)) {
5850 args.timeout = 0;
5852 else {
5853 timerec = rb_time_interval(timeout);
5854 args.timeout = &timerec;
5857 for (i = 0; i < sizeof(args.fdsets) / sizeof(args.fdsets[0]); ++i)
5858 rb_fd_init(&args.fdsets[i]);
5860 #ifdef HAVE_RB_FD_INIT
5861 return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
5862 #else
5863 return select_internal(args.read, args.write, args.except,
5864 args.timeout, args.fdsets);
5865 #endif
5869 #if !defined(MSDOS) && !defined(__human68k__)
5870 static int
5871 io_cntl(int fd, int cmd, long narg, int io_p)
5873 int retval;
5875 #ifdef HAVE_FCNTL
5876 TRAP_BEG;
5877 # if defined(__CYGWIN__)
5878 retval = io_p?ioctl(fd, cmd, (void*)narg):fcntl(fd, cmd, narg);
5879 # else
5880 retval = io_p?ioctl(fd, cmd, narg):fcntl(fd, cmd, narg);
5881 # endif
5882 TRAP_END;
5883 #else
5884 if (!io_p) {
5885 rb_notimplement();
5887 TRAP_BEG;
5888 retval = ioctl(fd, cmd, narg);
5889 TRAP_END;
5890 #endif
5891 return retval;
5893 #endif
5895 static VALUE
5896 rb_io_ctl(VALUE io, VALUE req, VALUE arg, int io_p)
5898 #if !defined(MSDOS) && !defined(__human68k__)
5899 int cmd = NUM2ULONG(req);
5900 rb_io_t *fptr;
5901 long len = 0;
5902 long narg = 0;
5903 int retval;
5905 rb_secure(2);
5907 if (NIL_P(arg) || arg == Qfalse) {
5908 narg = 0;
5910 else if (FIXNUM_P(arg)) {
5911 narg = FIX2LONG(arg);
5913 else if (arg == Qtrue) {
5914 narg = 1;
5916 else {
5917 VALUE tmp = rb_check_string_type(arg);
5919 if (NIL_P(tmp)) {
5920 narg = NUM2LONG(arg);
5922 else {
5923 arg = tmp;
5924 #ifdef IOCPARM_MASK
5925 #ifndef IOCPARM_LEN
5926 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
5927 #endif
5928 #endif
5929 #ifdef IOCPARM_LEN
5930 len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
5931 #else
5932 len = 256; /* otherwise guess at what's safe */
5933 #endif
5934 rb_str_modify(arg);
5936 if (len <= RSTRING_LEN(arg)) {
5937 len = RSTRING_LEN(arg);
5939 if (RSTRING_LEN(arg) < len) {
5940 rb_str_resize(arg, len+1);
5942 RSTRING_PTR(arg)[len] = 17; /* a little sanity check here */
5943 narg = (long)RSTRING_PTR(arg);
5946 GetOpenFile(io, fptr);
5947 retval = io_cntl(fptr->fd, cmd, narg, io_p);
5948 if (retval < 0) rb_sys_fail(fptr->path);
5949 if (TYPE(arg) == T_STRING && RSTRING_PTR(arg)[len] != 17) {
5950 rb_raise(rb_eArgError, "return value overflowed string");
5953 if (!io_p && cmd == F_SETFL) {
5954 if (narg & O_NONBLOCK) {
5955 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
5956 fptr->mode &= ~FMODE_WSPLIT;
5958 else {
5959 fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
5963 return INT2NUM(retval);
5964 #else
5965 rb_notimplement();
5966 return Qnil; /* not reached */
5967 #endif
5972 * call-seq:
5973 * ios.ioctl(integer_cmd, arg) => integer
5975 * Provides a mechanism for issuing low-level commands to control or
5976 * query I/O devices. Arguments and results are platform dependent. If
5977 * <i>arg</i> is a number, its value is passed directly. If it is a
5978 * string, it is interpreted as a binary sequence of bytes. On Unix
5979 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
5980 * all platforms.
5983 static VALUE
5984 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
5986 VALUE req, arg;
5988 rb_scan_args(argc, argv, "11", &req, &arg);
5989 return rb_io_ctl(io, req, arg, 1);
5993 * call-seq:
5994 * ios.fcntl(integer_cmd, arg) => integer
5996 * Provides a mechanism for issuing low-level commands to control or
5997 * query file-oriented I/O streams. Arguments and results are platform
5998 * dependent. If <i>arg</i> is a number, its value is passed
5999 * directly. If it is a string, it is interpreted as a binary sequence
6000 * of bytes (<code>Array#pack</code> might be a useful way to build this
6001 * string). On Unix platforms, see <code>fcntl(2)</code> for details.
6002 * Not implemented on all platforms.
6005 static VALUE
6006 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
6008 #ifdef HAVE_FCNTL
6009 VALUE req, arg;
6011 rb_scan_args(argc, argv, "11", &req, &arg);
6012 return rb_io_ctl(io, req, arg, 0);
6013 #else
6014 rb_notimplement();
6015 return Qnil; /* not reached */
6016 #endif
6020 * call-seq:
6021 * syscall(fixnum [, args...]) => integer
6023 * Calls the operating system function identified by _fixnum_,
6024 * passing in the arguments, which must be either +String+
6025 * objects, or +Integer+ objects that ultimately fit within
6026 * a native +long+. Up to nine parameters may be passed (14
6027 * on the Atari-ST). The function identified by _fixnum_ is system
6028 * dependent. On some Unix systems, the numbers may be obtained from a
6029 * header file called <code>syscall.h</code>.
6031 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
6033 * <em>produces:</em>
6035 * hello
6038 static VALUE
6039 rb_f_syscall(int argc, VALUE *argv)
6041 #if defined(HAVE_SYSCALL) && !defined(__CHECKER__)
6042 #ifdef atarist
6043 unsigned long arg[14]; /* yes, we really need that many ! */
6044 #else
6045 unsigned long arg[8];
6046 #endif
6047 int retval = -1;
6048 int i = 1;
6049 int items = argc - 1;
6051 /* This probably won't work on machines where sizeof(long) != sizeof(int)
6052 * or where sizeof(long) != sizeof(char*). But such machines will
6053 * not likely have syscall implemented either, so who cares?
6056 rb_secure(2);
6057 if (argc == 0)
6058 rb_raise(rb_eArgError, "too few arguments for syscall");
6059 if (argc > sizeof(arg) / sizeof(arg[0]))
6060 rb_raise(rb_eArgError, "too many arguments for syscall");
6061 arg[0] = NUM2LONG(argv[0]); argv++;
6062 while (items--) {
6063 VALUE v = rb_check_string_type(*argv);
6065 if (!NIL_P(v)) {
6066 StringValue(v);
6067 rb_str_modify(v);
6068 arg[i] = (unsigned long)StringValueCStr(v);
6070 else {
6071 arg[i] = (unsigned long)NUM2LONG(*argv);
6073 argv++;
6074 i++;
6076 TRAP_BEG;
6077 switch (argc) {
6078 case 1:
6079 retval = syscall(arg[0]);
6080 break;
6081 case 2:
6082 retval = syscall(arg[0],arg[1]);
6083 break;
6084 case 3:
6085 retval = syscall(arg[0],arg[1],arg[2]);
6086 break;
6087 case 4:
6088 retval = syscall(arg[0],arg[1],arg[2],arg[3]);
6089 break;
6090 case 5:
6091 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
6092 break;
6093 case 6:
6094 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
6095 break;
6096 case 7:
6097 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
6098 break;
6099 case 8:
6100 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
6101 arg[7]);
6102 break;
6103 #ifdef atarist
6104 case 9:
6105 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
6106 arg[7], arg[8]);
6107 break;
6108 case 10:
6109 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
6110 arg[7], arg[8], arg[9]);
6111 break;
6112 case 11:
6113 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
6114 arg[7], arg[8], arg[9], arg[10]);
6115 break;
6116 case 12:
6117 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
6118 arg[7], arg[8], arg[9], arg[10], arg[11]);
6119 break;
6120 case 13:
6121 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
6122 arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
6123 break;
6124 case 14:
6125 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
6126 arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13]);
6127 break;
6128 #endif /* atarist */
6130 TRAP_END;
6131 if (retval < 0) rb_sys_fail(0);
6132 return INT2NUM(retval);
6133 #else
6134 rb_notimplement();
6135 return Qnil; /* not reached */
6136 #endif
6139 static VALUE
6140 io_new_instance(VALUE args)
6142 return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
6145 static void
6146 io_encoding_set(rb_io_t *fptr, int argc, VALUE v1, VALUE v2)
6148 if (NIL_P(v2)) argc = 1;
6149 if (argc == 2) {
6150 fptr->enc2 = rb_to_encoding(v1);
6151 fptr->enc = rb_to_encoding(v2);
6153 else if (argc == 1) {
6154 if (NIL_P(v1)) {
6155 fptr->enc = 0;
6157 else {
6158 VALUE tmp = rb_check_string_type(v1);
6159 if (!NIL_P(tmp)) {
6160 mode_enc(fptr, StringValueCStr(tmp));
6162 else {
6163 fptr->enc = rb_to_encoding(v1);
6170 * call-seq:
6171 * IO.pipe -> [read_io, write_io]
6172 * IO.pipe(ext_enc) -> [read_io, write_io]
6173 * IO.pipe("ext_enc:int_enc") -> [read_io, write_io]
6174 * IO.pipe(ext_enc, int_enc) -> [read_io, write_io]
6176 * Creates a pair of pipe endpoints (connected to each other) and
6177 * returns them as a two-element array of <code>IO</code> objects:
6178 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>. Not
6179 * available on all platforms.
6181 * If an encoding (encoding name or encoding object) is specified as an optional argument,
6182 * read string from pipe is tagged with the encoding specified.
6183 * If the argument is a colon separated two encoding names "A:B",
6184 * the read string is converted from encoding A (external encoding)
6185 * to encoding B (internal encoding), then tagged with B.
6186 * If two optional arguments are specified, those must be
6187 * encoding objects or encoding names,
6188 * and the first one is the external encoding,
6189 * and the second one is the internal encoding.
6191 * In the example below, the two processes close the ends of the pipe
6192 * that they are not using. This is not just a cosmetic nicety. The
6193 * read end of a pipe will not generate an end of file condition if
6194 * there are any writers with the pipe still open. In the case of the
6195 * parent process, the <code>rd.read</code> will never return if it
6196 * does not first issue a <code>wr.close</code>.
6198 * rd, wr = IO.pipe
6200 * if fork
6201 * wr.close
6202 * puts "Parent got: <#{rd.read}>"
6203 * rd.close
6204 * Process.wait
6205 * else
6206 * rd.close
6207 * puts "Sending message to parent"
6208 * wr.write "Hi Dad"
6209 * wr.close
6210 * end
6212 * <em>produces:</em>
6214 * Sending message to parent
6215 * Parent got: <Hi Dad>
6218 static VALUE
6219 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
6221 #ifdef __human68k__
6222 rb_notimplement();
6223 return Qnil; /* not reached */
6224 #else
6225 int pipes[2], state;
6226 VALUE r, w, args[3], v1, v2;
6227 rb_io_t *fptr;
6229 rb_scan_args(argc, argv, "02", &v1, &v2);
6230 if (rb_pipe(pipes) == -1)
6231 rb_sys_fail(0);
6233 args[0] = klass;
6234 args[1] = INT2NUM(pipes[0]);
6235 args[2] = INT2FIX(O_RDONLY);
6236 r = rb_protect(io_new_instance, (VALUE)args, &state);
6237 if (state) {
6238 close(pipes[0]);
6239 close(pipes[1]);
6240 rb_jump_tag(state);
6242 GetOpenFile(r, fptr);
6243 io_encoding_set(fptr, argc, v1, v2);
6244 args[1] = INT2NUM(pipes[1]);
6245 args[2] = INT2FIX(O_WRONLY);
6246 w = rb_protect(io_new_instance, (VALUE)args, &state);
6247 if (state) {
6248 close(pipes[1]);
6249 if (!NIL_P(r)) rb_io_close(r);
6250 rb_jump_tag(state);
6252 rb_io_synchronized(RFILE(w)->fptr);
6254 return rb_assoc_new(r, w);
6255 #endif
6258 struct foreach_arg {
6259 int argc;
6260 VALUE *argv;
6261 VALUE io;
6264 static void
6265 open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
6267 VALUE opt, v;
6269 FilePathValue(argv[0]);
6270 arg->io = 0;
6271 arg->argc = argc > 1 ? 1 : 0;
6272 arg->argv = argv + 1;
6273 if (argc == 1) {
6274 no_key:
6275 arg->io = rb_io_open(RSTRING_PTR(argv[0]), "r");
6276 return;
6278 opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
6279 if (NIL_P(opt)) goto no_key;
6280 if (argc > 2) arg->argc = 1;
6281 else arg->argc = 0;
6283 v = rb_hash_aref(opt, sym_open_args);
6284 if (!NIL_P(v)) {
6285 VALUE args;
6287 v = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
6288 args = rb_ary_new2(RARRAY_LEN(v)+1);
6289 rb_ary_push(args, argv[0]);
6290 rb_ary_concat(args, v);
6291 MEMCPY(RARRAY_PTR(args)+1, RARRAY_PTR(v), VALUE, RARRAY_LEN(v));
6293 arg->io = rb_io_open_with_args(RARRAY_LEN(args), RARRAY_PTR(args));
6294 return;
6296 v = rb_hash_aref(opt, sym_mode);
6297 if (!NIL_P(v)) {
6298 arg->io = rb_io_open(RSTRING_PTR(argv[0]), StringValueCStr(v));
6300 else {
6301 arg->io = rb_io_open(RSTRING_PTR(argv[0]), "r");
6304 io_set_encoding(arg->io, opt);
6307 static VALUE
6308 io_s_foreach(struct foreach_arg *arg)
6310 VALUE str;
6312 while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
6313 rb_yield(str);
6315 return Qnil;
6319 * call-seq:
6320 * IO.foreach(name, sep=$/) {|line| block } => nil
6321 * IO.foreach(name, limit) {|line| block } => nil
6322 * IO.foreach(name, sep, limit) {|line| block } => nil
6324 * Executes the block for every line in the named I/O port, where lines
6325 * are separated by <em>sep</em>.
6327 * IO.foreach("testfile") {|x| print "GOT ", x }
6329 * <em>produces:</em>
6331 * GOT This is line one
6332 * GOT This is line two
6333 * GOT This is line three
6334 * GOT And so on...
6336 * If the last argument is a hash, it's the keyword argument to open.
6337 * See <code>IO.read</code> for detail.
6341 static VALUE
6342 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
6344 struct foreach_arg arg;
6346 rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
6347 RETURN_ENUMERATOR(self, argc, argv);
6348 open_key_args(argc, argv, &arg);
6349 if (NIL_P(arg.io)) return Qnil;
6350 return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
6353 static VALUE
6354 io_s_readlines(struct foreach_arg *arg)
6356 return rb_io_readlines(arg->argc, arg->argv, arg->io);
6360 * call-seq:
6361 * IO.readlines(name, sep=$/) => array
6362 * IO.readlines(name, limit) => array
6363 * IO.readlines(name, sep, limit) => array
6365 * Reads the entire file specified by <i>name</i> as individual
6366 * lines, and returns those lines in an array. Lines are separated by
6367 * <i>sep</i>.
6369 * a = IO.readlines("testfile")
6370 * a[0] #=> "This is line one\n"
6372 * If the last argument is a hash, it's the keyword argument to open.
6373 * See <code>IO.read</code> for detail.
6377 static VALUE
6378 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
6380 struct foreach_arg arg;
6382 rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
6383 open_key_args(argc, argv, &arg);
6384 if (NIL_P(arg.io)) return Qnil;
6385 return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
6388 static VALUE
6389 io_s_read(struct foreach_arg *arg)
6391 return io_read(arg->argc, arg->argv, arg->io);
6395 * call-seq:
6396 * IO.read(name, [length [, offset]] ) => string
6397 * IO.read(name, [length [, offset]], opt) => string
6399 * Opens the file, optionally seeks to the given offset, then returns
6400 * <i>length</i> bytes (defaulting to the rest of the file).
6401 * <code>read</code> ensures the file is closed before returning.
6403 * If the last argument is a hash, it specifies option for internal
6404 * open(). The key would be the following. open_args: is exclusive
6405 * to others.
6407 * encoding: string or encoding
6409 * specifies encoding of the read string. encoding will be ignored
6410 * if length is specified.
6412 * mode: string
6414 * specifies mode argument for open(). it should start with "r"
6415 * otherwise it would cause error.
6417 * open_args: array of strings
6419 * specifies arguments for open() as an array.
6421 * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
6422 * IO.read("testfile", 20) #=> "This is line one\nThi"
6423 * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
6426 static VALUE
6427 rb_io_s_read(int argc, VALUE *argv, VALUE io)
6429 VALUE offset;
6430 struct foreach_arg arg;
6432 rb_scan_args(argc, argv, "13", NULL, NULL, &offset, NULL);
6433 open_key_args(argc, argv, &arg);
6434 if (NIL_P(arg.io)) return Qnil;
6435 if (!NIL_P(offset)) {
6436 rb_io_binmode(arg.io);
6437 rb_io_seek(arg.io, offset, SEEK_SET);
6438 if (arg.argc == 2) arg.argc = 1;
6440 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
6443 struct copy_stream_struct {
6444 VALUE src;
6445 VALUE dst;
6446 off_t copy_length; /* (off_t)-1 if not specified */
6447 off_t src_offset; /* (off_t)-1 if not specified */
6449 int src_fd;
6450 int dst_fd;
6451 int close_src;
6452 int close_dst;
6453 off_t total;
6454 const char *syserr;
6455 int error_no;
6456 const char *notimp;
6457 rb_fdset_t fds;
6458 rb_thread_t *th;
6461 static int
6462 copy_stream_wait_read(struct copy_stream_struct *stp)
6464 int ret;
6465 rb_fd_zero(&stp->fds);
6466 rb_fd_set(stp->src_fd, &stp->fds);
6467 ret = rb_fd_select(rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
6468 if (ret == -1) {
6469 stp->syserr = "select";
6470 stp->error_no = errno;
6471 return -1;
6473 return 0;
6476 static int
6477 copy_stream_wait_write(struct copy_stream_struct *stp)
6479 int ret;
6480 rb_fd_zero(&stp->fds);
6481 rb_fd_set(stp->dst_fd, &stp->fds);
6482 ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
6483 if (ret == -1) {
6484 stp->syserr = "select";
6485 stp->error_no = errno;
6486 return -1;
6488 return 0;
6491 #ifdef HAVE_SENDFILE
6493 #ifdef __linux__
6494 #define USE_SENDFILE
6496 #ifdef HAVE_SYS_SENDFILE_H
6497 #include <sys/sendfile.h>
6498 #endif
6500 static ssize_t
6501 simple_sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
6503 return sendfile(out_fd, in_fd, offset, count);
6506 #endif
6508 #endif
6510 #ifdef USE_SENDFILE
6511 static int
6512 copy_stream_sendfile(struct copy_stream_struct *stp)
6514 struct stat src_stat, dst_stat;
6515 ssize_t ss;
6516 int ret;
6518 off_t copy_length;
6519 off_t src_offset;
6520 int use_pread;
6522 ret = fstat(stp->src_fd, &src_stat);
6523 if (ret == -1) {
6524 stp->syserr = "fstat";
6525 stp->error_no = errno;
6526 return -1;
6528 if (!S_ISREG(src_stat.st_mode))
6529 return 0;
6531 ret = fstat(stp->dst_fd, &dst_stat);
6532 if (ret == -1) {
6533 stp->syserr = "fstat";
6534 stp->error_no = errno;
6535 return -1;
6537 if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
6538 return 0;
6540 src_offset = stp->src_offset;
6541 use_pread = src_offset != (off_t)-1;
6543 copy_length = stp->copy_length;
6544 if (copy_length == (off_t)-1) {
6545 if (use_pread)
6546 copy_length = src_stat.st_size - src_offset;
6547 else {
6548 off_t cur = lseek(stp->src_fd, 0, SEEK_CUR);
6549 if (cur == (off_t)-1) {
6550 stp->syserr = "lseek";
6551 stp->error_no = errno;
6552 return -1;
6554 copy_length = src_stat.st_size - cur;
6558 retry_sendfile:
6559 if (use_pread) {
6560 ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, copy_length);
6562 else {
6563 ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, copy_length);
6565 if (0 < ss) {
6566 stp->total += ss;
6567 copy_length -= ss;
6568 if (0 < copy_length) {
6569 ss = -1;
6570 errno = EAGAIN;
6573 if (ss == -1) {
6574 if (errno == EINVAL || errno == ENOSYS)
6575 return 0;
6576 if (errno == EAGAIN || errno == EWOULDBLOCK) {
6577 if (copy_stream_wait_write(stp) == -1)
6578 return -1;
6579 if (RUBY_VM_INTERRUPTED(stp->th))
6580 return -1;
6581 goto retry_sendfile;
6583 stp->syserr = "sendfile";
6584 stp->error_no = errno;
6585 return -1;
6587 return 1;
6589 #endif
6591 static ssize_t
6592 copy_stream_read(struct copy_stream_struct *stp, char *buf, int len, off_t offset)
6594 ssize_t ss;
6595 retry_read:
6596 if (offset == (off_t)-1)
6597 ss = read(stp->src_fd, buf, len);
6598 else {
6599 #ifdef HAVE_PREAD
6600 ss = pread(stp->src_fd, buf, len, offset);
6601 #else
6602 stp->notimp = "pread";
6603 return -1;
6604 #endif
6606 if (ss == 0) {
6607 return 0;
6609 if (ss == -1) {
6610 if (errno == EAGAIN || errno == EWOULDBLOCK) {
6611 if (copy_stream_wait_read(stp) == -1)
6612 return -1;
6613 goto retry_read;
6615 if (errno == ENOSYS) {
6616 stp->notimp = "pread";
6617 return -1;
6619 stp->syserr = offset == (off_t)-1 ? "read" : "pread";
6620 stp->error_no = errno;
6621 return -1;
6623 return ss;
6626 static int
6627 copy_stream_write(struct copy_stream_struct *stp, char *buf, int len)
6629 ssize_t ss;
6630 int off = 0;
6631 while (len) {
6632 ss = write(stp->dst_fd, buf+off, len);
6633 if (ss == -1) {
6634 if (errno == EAGAIN || errno == EWOULDBLOCK) {
6635 if (copy_stream_wait_write(stp) == -1)
6636 return -1;
6637 continue;
6639 stp->syserr = "write";
6640 stp->error_no = errno;
6641 return -1;
6643 off += ss;
6644 len -= ss;
6645 stp->total += ss;
6647 return 0;
6650 static void
6651 copy_stream_read_write(struct copy_stream_struct *stp)
6653 char buf[1024*16];
6654 int len;
6655 ssize_t ss;
6656 int ret;
6657 off_t copy_length;
6658 int use_eof;
6659 off_t src_offset;
6660 int use_pread;
6662 copy_length = stp->copy_length;
6663 use_eof = copy_length == (off_t)-1;
6664 src_offset = stp->src_offset;
6665 use_pread = src_offset != (off_t)-1;
6667 if (use_pread && stp->close_src) {
6668 off_t r;
6669 r = lseek(stp->src_fd, src_offset, SEEK_SET);
6670 if (r == (off_t)-1) {
6671 stp->syserr = "lseek";
6672 stp->error_no = errno;
6673 return;
6675 src_offset = (off_t)-1;
6676 use_pread = 0;
6679 while (use_eof || 0 < copy_length) {
6680 if (!use_eof && copy_length < sizeof(buf)) {
6681 len = copy_length;
6683 else {
6684 len = sizeof(buf);
6686 if (use_pread) {
6687 ss = copy_stream_read(stp, buf, len, src_offset);
6688 if (0 < ss)
6689 src_offset += ss;
6691 else {
6692 ss = copy_stream_read(stp, buf, len, (off_t)-1);
6694 if (ss <= 0) /* EOF or error */
6695 return;
6697 ret = copy_stream_write(stp, buf, ss);
6698 if (ret < 0)
6699 return;
6701 if (!use_eof)
6702 copy_length -= ss;
6704 if (RUBY_VM_INTERRUPTED(stp->th))
6705 return;
6709 static VALUE
6710 copy_stream_func(void *arg)
6712 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
6713 #ifdef USE_SENDFILE
6714 int ret;
6715 #endif
6717 #ifdef USE_SENDFILE
6718 ret = copy_stream_sendfile(stp);
6719 if (ret != 0)
6720 goto finish; /* error or success */
6721 #endif
6723 copy_stream_read_write(stp);
6725 #ifdef USE_SENDFILE
6726 finish:
6727 #endif
6728 return Qnil;
6731 static VALUE
6732 copy_stream_fallback_body(VALUE arg)
6734 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
6735 const int buflen = 16*1024;
6736 VALUE n;
6737 VALUE buf = rb_str_buf_new(buflen);
6738 long rest = stp->copy_length;
6739 off_t off = stp->src_offset;
6741 while (1) {
6742 long numwrote;
6743 long l;
6744 if (stp->copy_length == (off_t)-1) {
6745 l = buflen;
6747 else {
6748 if (rest == 0)
6749 break;
6750 l = buflen < rest ? buflen : rest;
6752 if (stp->src_fd == -1) {
6753 rb_funcall(stp->src, id_readpartial, 2, INT2FIX(l), buf);
6755 else {
6756 ssize_t ss;
6757 rb_thread_wait_fd(stp->src_fd);
6758 rb_str_resize(buf, buflen);
6759 ss = copy_stream_read(stp, RSTRING_PTR(buf), l, off);
6760 if (ss == -1)
6761 return Qnil;
6762 if (ss == 0)
6763 rb_eof_error();
6764 rb_str_resize(buf, ss);
6765 if (off != (off_t)-1)
6766 off += ss;
6768 n = rb_io_write(stp->dst, buf);
6769 numwrote = NUM2LONG(n);
6770 stp->total += numwrote;
6771 rest -= numwrote;
6774 return Qnil;
6777 static VALUE
6778 copy_stream_fallback(struct copy_stream_struct *stp)
6780 if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
6781 rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
6783 rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
6784 (VALUE (*) (ANYARGS))0, (VALUE)0,
6785 rb_eEOFError, (VALUE)0);
6786 return Qnil;
6789 static VALUE
6790 copy_stream_body(VALUE arg)
6792 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
6793 VALUE src_io, dst_io;
6794 rb_io_t *src_fptr = 0, *dst_fptr = 0;
6795 int src_fd, dst_fd;
6797 stp->th = GET_THREAD();
6799 stp->total = 0;
6801 if (stp->src == argf ||
6802 !(TYPE(stp->src) == T_FILE ||
6803 rb_respond_to(stp->src, rb_intern("to_io")) ||
6804 TYPE(stp->src) == T_STRING ||
6805 rb_respond_to(stp->src, rb_intern("to_path")))) {
6806 src_fd = -1;
6808 else {
6809 src_io = rb_check_convert_type(stp->src, T_FILE, "IO", "to_io");
6810 if (NIL_P(src_io)) {
6811 VALUE args[2];
6812 int flags = O_RDONLY;
6813 #ifdef O_NOCTTY
6814 flags |= O_NOCTTY;
6815 #endif
6816 FilePathValue(stp->src);
6817 args[0] = stp->src;
6818 args[1] = INT2NUM(flags);
6819 src_io = rb_class_new_instance(2, args, rb_cFile);
6820 stp->src = src_io;
6821 stp->close_src = 1;
6823 GetOpenFile(src_io, src_fptr);
6824 rb_io_check_readable(src_fptr);
6825 src_fd = src_fptr->fd;
6827 stp->src_fd = src_fd;
6829 if (stp->dst == argf ||
6830 !(TYPE(stp->dst) == T_FILE ||
6831 rb_respond_to(stp->dst, rb_intern("to_io")) ||
6832 TYPE(stp->dst) == T_STRING ||
6833 rb_respond_to(stp->dst, rb_intern("to_path")))) {
6834 dst_fd = -1;
6836 else {
6837 dst_io = rb_check_convert_type(stp->dst, T_FILE, "IO", "to_io");
6838 if (NIL_P(dst_io)) {
6839 VALUE args[3];
6840 int flags = O_WRONLY|O_CREAT|O_TRUNC;
6841 #ifdef O_NOCTTY
6842 flags |= O_NOCTTY;
6843 #endif
6844 FilePathValue(stp->dst);
6845 args[0] = stp->dst;
6846 args[1] = INT2NUM(flags);
6847 args[2] = INT2FIX(0600);
6848 dst_io = rb_class_new_instance(3, args, rb_cFile);
6849 stp->dst = dst_io;
6850 stp->close_dst = 1;
6852 else {
6853 dst_io = GetWriteIO(dst_io);
6854 stp->dst = dst_io;
6856 GetOpenFile(dst_io, dst_fptr);
6857 rb_io_check_writable(dst_fptr);
6858 dst_fd = dst_fptr->fd;
6860 stp->dst_fd = dst_fd;
6862 if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf_len) {
6863 long len = src_fptr->rbuf_len;
6864 VALUE str;
6865 if (stp->copy_length != (off_t)-1 && stp->copy_length < len) {
6866 len = stp->copy_length;
6868 str = rb_str_buf_new(len);
6869 rb_str_resize(str,len);
6870 read_buffered_data(RSTRING_PTR(str), len, src_fptr);
6871 if (dst_fptr) /* IO or filename */
6872 io_fwrite(str, dst_fptr);
6873 else /* others such as StringIO */
6874 rb_io_write(stp->dst, str);
6875 stp->total += len;
6876 if (stp->copy_length != (off_t)-1)
6877 stp->copy_length -= len;
6880 if (dst_fptr && io_fflush(dst_fptr) < 0) {
6881 rb_raise(rb_eIOError, "flush failed");
6884 if (stp->copy_length == 0)
6885 return Qnil;
6887 if (src_fd == -1 || dst_fd == -1) {
6888 return copy_stream_fallback(stp);
6891 rb_fd_init(&stp->fds);
6892 rb_fd_set(src_fd, &stp->fds);
6893 rb_fd_set(dst_fd, &stp->fds);
6895 return rb_thread_blocking_region(copy_stream_func, (void*)stp, RB_UBF_DFL, 0);
6898 static VALUE
6899 copy_stream_finalize(VALUE arg)
6901 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
6902 if (stp->close_src) {
6903 rb_io_close_m(stp->src);
6905 if (stp->close_dst) {
6906 rb_io_close_m(stp->dst);
6908 rb_fd_term(&stp->fds);
6909 if (stp->syserr) {
6910 errno = stp->error_no;
6911 rb_sys_fail(stp->syserr);
6913 if (stp->notimp) {
6914 rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
6916 return Qnil;
6920 * call-seq:
6921 * IO.copy_stream(src, dst)
6922 * IO.copy_stream(src, dst, copy_length)
6923 * IO.copy_stream(src, dst, copy_length, src_offset)
6925 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
6926 * <i>src</i> and <i>dst</i> is either a filename or an IO.
6928 * This method returns the number of bytes copied.
6930 * If optional arguments are not given,
6931 * the start position of the copy is
6932 * the beginning of the filename or
6933 * the current file offset of the IO.
6934 * The end position of the copy is the end of file.
6936 * If <i>copy_length</i> is given,
6937 * No more than <i>copy_length</i> bytes are copied.
6939 * If <i>src_offset</i> is given,
6940 * it specifies the start position of the copy.
6942 * When <i>src_offset</i> is specified and
6943 * <i>src</i> is an IO,
6944 * IO.copy_stream doesn't move the current file offset.
6947 static VALUE
6948 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
6950 VALUE src, dst, length, src_offset;
6951 struct copy_stream_struct st;
6953 MEMZERO(&st, struct copy_stream_struct, 1);
6955 rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
6957 st.src = src;
6958 st.dst = dst;
6960 if (NIL_P(length))
6961 st.copy_length = (off_t)-1;
6962 else
6963 st.copy_length = NUM2OFFT(length);
6965 if (NIL_P(src_offset))
6966 st.src_offset = (off_t)-1;
6967 else
6968 st.src_offset = NUM2OFFT(src_offset);
6970 rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
6972 return OFFT2NUM(st.total);
6976 * call-seq:
6977 * io.external_encoding => encoding
6979 * Returns the Encoding object that represents the encoding of the file.
6980 * If io is write mode and no encoding is specified, returns <code>nil</code>.
6983 static VALUE
6984 rb_io_external_encoding(VALUE io)
6986 rb_io_t *fptr;
6988 GetOpenFile(io, fptr);
6989 if (fptr->enc2) {
6990 return rb_enc_from_encoding(fptr->enc2);
6992 if (!fptr->enc && fptr->fd == 0) {
6993 fptr->enc = rb_default_external_encoding();
6995 if (fptr->mode & FMODE_WRITABLE) {
6996 if (fptr->enc)
6997 return rb_enc_from_encoding(fptr->enc);
6998 return Qnil;
7000 return rb_enc_from_encoding(io_read_encoding(fptr));
7004 * call-seq:
7005 * io.internal_encoding => encoding
7007 * Returns the Encoding of the internal string if conversion is
7008 * specified. Otherwise returns nil.
7011 static VALUE
7012 rb_io_internal_encoding(VALUE io)
7014 rb_io_t *fptr;
7016 GetOpenFile(io, fptr);
7017 if (!fptr->enc2) return Qnil;
7018 return rb_enc_from_encoding(io_read_encoding(fptr));
7022 * call-seq:
7023 * io.set_encoding(ext_enc) => io
7024 * io.set_encoding("ext_enc:int_enc") => io
7025 * io.set_encoding(ext_enc, int_enc) => io
7027 * If single argument is specified, read string from io is tagged
7028 * with the encoding specified. If encoding is a colon separated two
7029 * encoding names "A:B", the read string is converted from encoding A
7030 * (external encoding) to encoding B (internal encoding), then tagged
7031 * with B. If two arguments are specified, those must be encoding
7032 * objects or encoding names, and the first one is the external encoding, and the
7033 * second one is the internal encoding.
7036 static VALUE
7037 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
7039 rb_io_t *fptr;
7040 VALUE v1, v2;
7042 rb_scan_args(argc, argv, "11", &v1, &v2);
7043 GetOpenFile(io, fptr);
7044 io_encoding_set(fptr, argc, v1, v2);
7045 return io;
7048 static VALUE
7049 argf_external_encoding(VALUE argf)
7051 if (!RTEST(current_file)) {
7052 return rb_enc_from_encoding(rb_default_external_encoding());
7054 return rb_io_external_encoding(rb_io_check_io(current_file));
7057 static VALUE
7058 argf_internal_encoding(VALUE argf)
7060 if (!RTEST(current_file)) {
7061 return rb_enc_from_encoding(rb_default_external_encoding());
7063 return rb_io_internal_encoding(rb_io_check_io(current_file));
7066 static VALUE
7067 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
7069 rb_io_t *fptr;
7071 if (!next_argv()) {
7072 rb_raise(rb_eArgError, "no stream to set encoding");
7074 rb_io_set_encoding(argc, argv, current_file);
7075 GetOpenFile(current_file, fptr);
7076 argf_enc = fptr->enc;
7077 argf_enc2 = fptr->enc2;
7078 return argf;
7081 static VALUE
7082 argf_tell(VALUE argf)
7084 if (!next_argv()) {
7085 rb_raise(rb_eArgError, "no stream to tell");
7087 ARGF_FORWARD(0, 0);
7088 return rb_io_tell(current_file);
7091 static VALUE
7092 argf_seek_m(int argc, VALUE *argv, VALUE argf)
7094 if (!next_argv()) {
7095 rb_raise(rb_eArgError, "no stream to seek");
7097 ARGF_FORWARD(argc, argv);
7098 return rb_io_seek_m(argc, argv, current_file);
7101 static VALUE
7102 argf_set_pos(VALUE argf, VALUE offset)
7104 if (!next_argv()) {
7105 rb_raise(rb_eArgError, "no stream to set position");
7107 ARGF_FORWARD(1, &offset);
7108 return rb_io_set_pos(current_file, offset);
7111 static VALUE
7112 argf_rewind(VALUE argf)
7114 if (!next_argv()) {
7115 rb_raise(rb_eArgError, "no stream to rewind");
7117 ARGF_FORWARD(0, 0);
7118 return rb_io_rewind(current_file);
7121 static VALUE
7122 argf_fileno(VALUE argf)
7124 if (!next_argv()) {
7125 rb_raise(rb_eArgError, "no stream");
7127 ARGF_FORWARD(0, 0);
7128 return rb_io_fileno(current_file);
7131 static VALUE
7132 argf_to_io(VALUE argf)
7134 next_argv();
7135 ARGF_FORWARD(0, 0);
7136 return current_file;
7139 static VALUE
7140 argf_eof(VALUE argf)
7142 if (current_file) {
7143 if (init_p == 0) return Qtrue;
7144 ARGF_FORWARD(0, 0);
7145 if (rb_io_eof(current_file)) {
7146 return Qtrue;
7149 return Qfalse;
7152 static VALUE
7153 argf_read(int argc, VALUE *argv, VALUE argf)
7155 VALUE tmp, str, length;
7156 long len = 0;
7158 rb_scan_args(argc, argv, "02", &length, &str);
7159 if (!NIL_P(length)) {
7160 len = NUM2LONG(argv[0]);
7162 if (!NIL_P(str)) {
7163 StringValue(str);
7164 rb_str_resize(str,0);
7165 argv[1] = Qnil;
7168 retry:
7169 if (!next_argv()) {
7170 return str;
7172 if (ARGF_GENERIC_INPUT_P()) {
7173 tmp = argf_forward(argc, argv, argf);
7175 else {
7176 tmp = io_read(argc, argv, current_file);
7178 if (NIL_P(str)) str = tmp;
7179 else if (!NIL_P(tmp)) rb_str_append(str, tmp);
7180 if (NIL_P(tmp) || NIL_P(length)) {
7181 if (next_p != -1) {
7182 argf_close(current_file);
7183 next_p = 1;
7184 goto retry;
7187 else if (argc >= 1) {
7188 if (RSTRING_LEN(str) < len) {
7189 len -= RSTRING_LEN(str);
7190 argv[0] = INT2NUM(len);
7191 goto retry;
7194 return str;
7197 struct argf_call_arg {
7198 int argc;
7199 VALUE *argv;
7200 VALUE argf;
7203 static VALUE
7204 argf_forward_call(VALUE arg)
7206 struct argf_call_arg *p = (struct argf_call_arg *)arg;
7207 argf_forward(p->argc, p->argv, p->argf);
7208 return Qnil;
7211 static VALUE
7212 argf_readpartial(int argc, VALUE *argv, VALUE argf)
7214 VALUE tmp, str, length;
7216 rb_scan_args(argc, argv, "11", &length, &str);
7217 if (!NIL_P(str)) {
7218 StringValue(str);
7219 argv[1] = str;
7222 if (!next_argv()) {
7223 rb_str_resize(str, 0);
7224 rb_eof_error();
7226 if (ARGF_GENERIC_INPUT_P()) {
7227 struct argf_call_arg arg;
7228 arg.argc = argc;
7229 arg.argv = argv;
7230 arg.argf = argf;
7231 tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
7232 RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
7234 else {
7235 tmp = io_getpartial(argc, argv, current_file, 0);
7237 if (NIL_P(tmp)) {
7238 if (next_p == -1) {
7239 rb_eof_error();
7241 argf_close(current_file);
7242 next_p = 1;
7243 if (RARRAY_LEN(rb_argv) == 0)
7244 rb_eof_error();
7245 if (NIL_P(str))
7246 str = rb_str_new(NULL, 0);
7247 return str;
7249 return tmp;
7252 static VALUE
7253 argf_getc(VALUE argf)
7255 VALUE ch;
7257 retry:
7258 if (!next_argv()) return Qnil;
7259 if (ARGF_GENERIC_INPUT_P()) {
7260 ch = rb_funcall3(current_file, rb_intern("getc"), 0, 0);
7262 else {
7263 ch = rb_io_getc(current_file);
7265 if (NIL_P(ch) && next_p != -1) {
7266 argf_close(current_file);
7267 next_p = 1;
7268 goto retry;
7271 return ch;
7274 static VALUE
7275 argf_getbyte(VALUE argf)
7277 VALUE ch;
7279 retry:
7280 if (!next_argv()) return Qnil;
7281 if (TYPE(current_file) != T_FILE) {
7282 ch = rb_funcall3(current_file, rb_intern("getbyte"), 0, 0);
7284 else {
7285 ch = rb_io_getbyte(current_file);
7287 if (NIL_P(ch) && next_p != -1) {
7288 argf_close(current_file);
7289 next_p = 1;
7290 goto retry;
7293 return ch;
7296 static VALUE
7297 argf_readchar(VALUE argf)
7299 VALUE ch;
7301 retry:
7302 if (!next_argv()) rb_eof_error();
7303 if (TYPE(current_file) != T_FILE) {
7304 ch = rb_funcall3(current_file, rb_intern("getc"), 0, 0);
7306 else {
7307 ch = rb_io_getc(current_file);
7309 if (NIL_P(ch) && next_p != -1) {
7310 argf_close(current_file);
7311 next_p = 1;
7312 goto retry;
7315 return ch;
7318 static VALUE
7319 argf_readbyte(VALUE argf)
7321 VALUE c;
7323 NEXT_ARGF_FORWARD(0, 0);
7324 c = argf_getbyte(argf);
7325 if (NIL_P(c)) {
7326 rb_eof_error();
7328 return c;
7331 static VALUE
7332 argf_each_line(int argc, VALUE *argv, VALUE argf)
7334 RETURN_ENUMERATOR(argf, argc, argv);
7335 for (;;) {
7336 if (!next_argv()) return Qnil;
7337 rb_block_call(current_file, rb_intern("each_line"), argc, argv, rb_yield, 0);
7338 next_p = 1;
7340 return argf;
7343 static VALUE
7344 argf_each_byte(VALUE argf)
7346 RETURN_ENUMERATOR(argf, 0, 0);
7347 for (;;) {
7348 if (!next_argv()) return Qnil;
7349 rb_block_call(current_file, rb_intern("each_byte"), 0, 0, rb_yield, 0);
7350 next_p = 1;
7354 static VALUE
7355 argf_each_char(VALUE argf)
7357 RETURN_ENUMERATOR(argf, 0, 0);
7358 for (;;) {
7359 if (!next_argv()) return Qnil;
7360 rb_block_call(current_file, rb_intern("each_char"), 0, 0, rb_yield, 0);
7361 next_p = 1;
7365 static VALUE
7366 argf_filename(VALUE argf)
7368 next_argv();
7369 return filename;
7372 static VALUE
7373 argf_filename_getter(ID id, VALUE *var)
7375 return argf_filename(*var);
7378 static VALUE
7379 argf_file(VALUE argf)
7381 next_argv();
7382 return current_file;
7385 static VALUE
7386 argf_binmode_m(VALUE argf)
7388 argf_binmode = 1;
7389 next_argv();
7390 ARGF_FORWARD(0, 0);
7391 rb_io_binmode(current_file);
7392 return argf;
7395 static VALUE
7396 argf_binmode_p(VALUE argf)
7398 return argf_binmode ? Qtrue : Qfalse;
7401 static VALUE
7402 argf_skip(VALUE argf)
7404 if (next_p != -1) {
7405 argf_close(current_file);
7406 next_p = 1;
7408 return argf;
7411 static VALUE
7412 argf_close_m(VALUE argf)
7414 next_argv();
7415 argf_close(current_file);
7416 if (next_p != -1) {
7417 next_p = 1;
7419 gets_lineno = 0;
7420 return argf;
7423 static VALUE
7424 argf_closed(VALUE argf)
7426 next_argv();
7427 ARGF_FORWARD(0, 0);
7428 return rb_io_closed(current_file);
7431 static VALUE
7432 argf_to_s(VALUE argf)
7434 return rb_str_new2("ARGF");
7437 static VALUE
7438 argf_inplace_mode_get(VALUE argf)
7440 if (!ruby_inplace_mode) return Qnil;
7441 return rb_str_new2(ruby_inplace_mode);
7444 static VALUE
7445 opt_i_get(ID id, VALUE *var)
7447 return argf_inplace_mode_get(*var);
7450 static VALUE
7451 argf_inplace_mode_set(VALUE argf, VALUE val)
7453 if (!RTEST(val)) {
7454 if (ruby_inplace_mode) free(ruby_inplace_mode);
7455 ruby_inplace_mode = 0;
7457 else {
7458 StringValue(val);
7459 if (ruby_inplace_mode) free(ruby_inplace_mode);
7460 ruby_inplace_mode = 0;
7461 ruby_inplace_mode = strdup(RSTRING_PTR(val));
7463 return argf;
7466 static void
7467 opt_i_set(VALUE val, ID id, VALUE *var)
7469 argf_inplace_mode_set(*var, val);
7472 const char *
7473 ruby_get_inplace_mode(void)
7475 return ruby_inplace_mode;
7478 void
7479 ruby_set_inplace_mode(const char *suffix)
7481 if (ruby_inplace_mode) free(ruby_inplace_mode);
7482 ruby_inplace_mode = 0;
7483 if (suffix) ruby_inplace_mode = strdup(suffix);
7486 static VALUE
7487 argf_argv(VALUE argf)
7489 return rb_argv;
7492 static VALUE
7493 argf_argv_getter(ID id, VALUE *var)
7495 return argf_argv(*var);
7498 VALUE
7499 rb_get_argv(void)
7501 return rb_argv;
7505 * Class <code>IO</code> is the basis for all input and output in Ruby.
7506 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
7507 * so may use more than one native operating system stream.
7509 * Many of the examples in this section use class <code>File</code>,
7510 * the only standard subclass of <code>IO</code>. The two classes are
7511 * closely associated.
7513 * As used in this section, <em>portname</em> may take any of the
7514 * following forms.
7516 * * A plain string represents a filename suitable for the underlying
7517 * operating system.
7519 * * A string starting with ``<code>|</code>'' indicates a subprocess.
7520 * The remainder of the string following the ``<code>|</code>'' is
7521 * invoked as a process with appropriate input/output channels
7522 * connected to it.
7524 * * A string equal to ``<code>|-</code>'' will create another Ruby
7525 * instance as a subprocess.
7527 * Ruby will convert pathnames between different operating system
7528 * conventions if possible. For instance, on a Windows system the
7529 * filename ``<code>/gumby/ruby/test.rb</code>'' will be opened as
7530 * ``<code>\gumby\ruby\test.rb</code>''. When specifying a
7531 * Windows-style filename in a Ruby string, remember to escape the
7532 * backslashes:
7534 * "c:\\gumby\\ruby\\test.rb"
7536 * Our examples here will use the Unix-style forward slashes;
7537 * <code>File::SEPARATOR</code> can be used to get the
7538 * platform-specific separator character.
7540 * I/O ports may be opened in any one of several different modes, which
7541 * are shown in this section as <em>mode</em>. The mode may
7542 * either be a Fixnum or a String. If numeric, it should be
7543 * one of the operating system specific constants (O_RDONLY,
7544 * O_WRONLY, O_RDWR, O_APPEND and so on). See man open(2) for
7545 * more information.
7547 * If the mode is given as a String, it must be one of the
7548 * values listed in the following table.
7550 * Mode | Meaning
7551 * -----+--------------------------------------------------------
7552 * "r" | Read-only, starts at beginning of file (default mode).
7553 * -----+--------------------------------------------------------
7554 * "r+" | Read-write, starts at beginning of file.
7555 * -----+--------------------------------------------------------
7556 * "w" | Write-only, truncates existing file
7557 * | to zero length or creates a new file for writing.
7558 * -----+--------------------------------------------------------
7559 * "w+" | Read-write, truncates existing file to zero length
7560 * | or creates a new file for reading and writing.
7561 * -----+--------------------------------------------------------
7562 * "a" | Write-only, starts at end of file if file exists,
7563 * | otherwise creates a new file for writing.
7564 * -----+--------------------------------------------------------
7565 * "a+" | Read-write, starts at end of file if file exists,
7566 * | otherwise creates a new file for reading and
7567 * | writing.
7568 * -----+--------------------------------------------------------
7569 * "b" | (DOS/Windows only) Binary file mode (may appear with
7570 * | any of the key letters listed above).
7573 * The global constant ARGF (also accessible as $<) provides an
7574 * IO-like stream which allows access to all files mentioned on the
7575 * command line (or STDIN if no files are mentioned). ARGF provides
7576 * the methods <code>#path</code> and <code>#filename</code> to access
7577 * the name of the file currently being read.
7580 void
7581 Init_IO(void)
7583 #undef rb_intern
7585 VALUE rb_cARGF;
7586 #ifdef __CYGWIN__
7587 #include <sys/cygwin.h>
7588 static struct __cygwin_perfile pf[] =
7590 {"", O_RDONLY | O_BINARY},
7591 {"", O_WRONLY | O_BINARY},
7592 {"", O_RDWR | O_BINARY},
7593 {"", O_APPEND | O_BINARY},
7594 {NULL, 0}
7596 cygwin_internal(CW_PERFILE, pf);
7597 #endif
7599 rb_eIOError = rb_define_class("IOError", rb_eStandardError);
7600 rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
7602 id_write = rb_intern("write");
7603 id_read = rb_intern("read");
7604 id_getc = rb_intern("getc");
7605 id_flush = rb_intern("flush");
7606 id_encode = rb_intern("encode");
7607 id_readpartial = rb_intern("readpartial");
7609 rb_define_global_function("syscall", rb_f_syscall, -1);
7611 rb_define_global_function("open", rb_f_open, -1);
7612 rb_define_global_function("printf", rb_f_printf, -1);
7613 rb_define_global_function("print", rb_f_print, -1);
7614 rb_define_global_function("putc", rb_f_putc, 1);
7615 rb_define_global_function("puts", rb_f_puts, -1);
7616 rb_define_global_function("gets", rb_f_gets, -1);
7617 rb_define_global_function("readline", rb_f_readline, -1);
7618 rb_define_global_function("select", rb_f_select, -1);
7620 rb_define_global_function("readlines", rb_f_readlines, -1);
7622 rb_define_global_function("`", rb_f_backquote, 1);
7624 rb_define_global_function("p", rb_f_p, -1);
7625 rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
7627 rb_cIO = rb_define_class("IO", rb_cObject);
7628 rb_include_module(rb_cIO, rb_mEnumerable);
7630 rb_define_alloc_func(rb_cIO, io_alloc);
7631 rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
7632 rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
7633 rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
7634 rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
7635 rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
7636 rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
7637 rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
7638 rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
7639 rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
7640 rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
7641 rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
7642 rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
7644 rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
7646 rb_output_fs = Qnil;
7647 rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
7649 rb_global_variable(&rb_default_rs);
7650 rb_rs = rb_default_rs = rb_str_new2("\n");
7651 rb_output_rs = Qnil;
7652 OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
7653 rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
7654 rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
7655 rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
7657 rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
7659 rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
7660 rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
7662 rb_define_method(rb_cIO, "print", rb_io_print, -1);
7663 rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
7664 rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
7665 rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
7667 rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
7668 rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
7669 rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
7670 rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
7671 rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
7672 rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
7673 rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
7675 rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
7676 rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
7678 rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
7679 rb_define_alias(rb_cIO, "to_i", "fileno");
7680 rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
7682 rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
7683 rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
7684 rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
7686 rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
7687 rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
7689 rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
7691 rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1);
7692 rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
7693 rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
7694 rb_define_method(rb_cIO, "read", io_read, -1);
7695 rb_define_method(rb_cIO, "write", io_write, 1);
7696 rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
7697 rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
7698 rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
7699 rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
7700 rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
7701 rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
7702 rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
7703 rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
7704 rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
7705 rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
7706 rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
7707 rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
7708 rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
7709 rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
7710 rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
7711 rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
7712 rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
7713 rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
7714 rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
7716 rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
7717 rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
7719 rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
7720 rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
7721 rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
7722 rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
7724 rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
7725 rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
7726 rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
7727 rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
7728 rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
7730 rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
7731 rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
7732 rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
7733 rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
7735 rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
7736 rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
7737 rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
7739 rb_define_variable("$stdin", &rb_stdin);
7740 rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
7741 rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
7742 rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
7743 rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
7744 rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
7745 rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
7746 orig_stdout = rb_stdout;
7747 rb_deferr = orig_stderr = rb_stderr;
7749 /* constants to hold original stdin/stdout/stderr */
7750 rb_define_global_const("STDIN", rb_stdin);
7751 rb_define_global_const("STDOUT", rb_stdout);
7752 rb_define_global_const("STDERR", rb_stderr);
7754 rb_cARGF = rb_class_new(rb_cObject);
7755 rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
7756 rb_define_alloc_func(rb_cARGF, argf_alloc);
7758 rb_include_module(rb_cARGF, rb_mEnumerable);
7760 rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
7761 rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
7762 rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
7763 rb_define_method(rb_cARGF, "argv", argf_argv, 0);
7765 rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
7766 rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
7767 rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
7768 rb_define_method(rb_cARGF, "each", argf_each_line, -1);
7769 rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
7770 rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
7771 rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
7772 rb_define_method(rb_cARGF, "lines", argf_each_line, -1);
7773 rb_define_method(rb_cARGF, "bytes", argf_each_byte, 0);
7774 rb_define_method(rb_cARGF, "chars", argf_each_char, 0);
7776 rb_define_method(rb_cARGF, "read", argf_read, -1);
7777 rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
7778 rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
7779 rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
7780 rb_define_method(rb_cARGF, "gets", argf_gets, -1);
7781 rb_define_method(rb_cARGF, "readline", argf_readline, -1);
7782 rb_define_method(rb_cARGF, "getc", argf_getc, 0);
7783 rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
7784 rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
7785 rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
7786 rb_define_method(rb_cARGF, "tell", argf_tell, 0);
7787 rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
7788 rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
7789 rb_define_method(rb_cARGF, "pos", argf_tell, 0);
7790 rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
7791 rb_define_method(rb_cARGF, "eof", argf_eof, 0);
7792 rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
7793 rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
7794 rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
7796 rb_define_method(rb_cARGF, "filename", argf_filename, 0);
7797 rb_define_method(rb_cARGF, "path", argf_filename, 0);
7798 rb_define_method(rb_cARGF, "file", argf_file, 0);
7799 rb_define_method(rb_cARGF, "skip", argf_skip, 0);
7800 rb_define_method(rb_cARGF, "close", argf_close_m, 0);
7801 rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
7803 rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
7804 rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
7806 rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
7807 rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
7809 rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
7810 rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
7811 rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
7813 argf = rb_class_new_instance(0, 0, rb_cARGF);
7815 rb_define_readonly_variable("$<", &argf);
7816 rb_define_global_const("ARGF", argf);
7818 rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
7819 rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, 0);
7820 filename = rb_str_new2("-");
7822 rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
7823 rb_define_hooked_variable("$*", &argf, argf_argv_getter, 0);
7825 #if defined (_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__)
7826 atexit(pipe_atexit);
7827 #endif
7829 Init_File();
7831 rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
7833 rb_file_const("RDONLY", INT2FIX(O_RDONLY));
7834 rb_file_const("WRONLY", INT2FIX(O_WRONLY));
7835 rb_file_const("RDWR", INT2FIX(O_RDWR));
7836 rb_file_const("APPEND", INT2FIX(O_APPEND));
7837 rb_file_const("CREAT", INT2FIX(O_CREAT));
7838 rb_file_const("EXCL", INT2FIX(O_EXCL));
7839 #if defined(O_NDELAY) || defined(O_NONBLOCK)
7840 # ifdef O_NONBLOCK
7841 rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
7842 # else
7843 rb_file_const("NONBLOCK", INT2FIX(O_NDELAY));
7844 # endif
7845 #endif
7846 rb_file_const("TRUNC", INT2FIX(O_TRUNC));
7847 #ifdef O_NOCTTY
7848 rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
7849 #endif
7850 #ifdef O_BINARY
7851 rb_file_const("BINARY", INT2FIX(O_BINARY));
7852 #else
7853 rb_file_const("BINARY", INT2FIX(0));
7854 #endif
7855 #ifdef O_SYNC
7856 rb_file_const("SYNC", INT2FIX(O_SYNC));
7857 #endif
7859 sym_mode = ID2SYM(rb_intern("mode"));
7860 sym_perm = ID2SYM(rb_intern("perm"));
7861 sym_extenc = ID2SYM(rb_intern("external_encoding"));
7862 sym_intenc = ID2SYM(rb_intern("internal_encoding"));
7863 sym_encoding = ID2SYM(rb_intern("encoding"));
7864 sym_open_args = ID2SYM(rb_intern("open_args"));