/*
* call-seq:
* IO.new(fd, mode) => io
*
* Returns a new <code>IO</code> object (a stream) for the given
* <code>IO</code> object or integer file descriptor and mode
* string. See also <code>IO#fileno</code> and
* <code>IO::for_fd</code>.
*
* puts IO.new($stdout).fileno # => 1
*
* a = IO.new(2,"w") # '2' is standard error
* $stderr.puts "Hello"
* a.puts "World"
*
* <em>produces:</em>
*
* Hello
* World
*/
static VALUE
rb_io_initialize(int argc, VALUE *argv, VALUE io)
{
VALUE fnum, mode, orig;
rb_io_t *fp, *ofp = NULL;
int fd, fmode, flags = O_RDONLY;
rb_secure(4);
rb_scan_args(argc, argv, "11", &fnum, &mode);
if (argc == 2) {
if (FIXNUM_P(mode)) {
flags = FIX2LONG(mode);
}
else {
SafeStringValue(mode);
flags = rb_io_mode_modenum(StringValueCStr(mode));
}
}
orig = rb_io_check_io(fnum);
if (NIL_P(orig)) {
fd = NUM2INT(fnum);
UPDATE_MAXFD(fd);
if (argc != 2) {
#if defined(HAVE_FCNTL) && defined(F_GETFL)
flags = fcntl(fd, F_GETFL);
if (flags == -1) rb_sys_fail(0);
#endif
}
MakeOpenFile(io, fp);
fp->fd = fd;
fp->mode = rb_io_modenum_flags(flags);
io_check_tty(fp);
}
else if (RFILE(io)->fptr) {
rb_raise(rb_eRuntimeError, "reinitializing IO");
}
else {
GetOpenFile(orig, ofp);
if (ofp->refcnt == LONG_MAX) {
VALUE s = rb_inspect(orig);
rb_raise(rb_eIOError, "too many shared IO for %s", StringValueCStr(s));
}
if (argc == 2) {
fmode = rb_io_modenum_flags(flags);
if ((ofp->mode ^ fmode) & (FMODE_READWRITE|FMODE_BINMODE)) {
if (FIXNUM_P(mode)) {
rb_raise(rb_eArgError, "incompatible mode 0%o", flags);
}
else {
rb_raise(rb_eArgError, "incompatible mode \"%s\"", RSTRING_PTR(mode));
}
}
}
ofp->refcnt++;
RFILE(io)->fptr = ofp;
}
return io;
}