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