diff options
author | Gary Houston <ghouston@arglist.com> | 2000-03-12 19:58:56 +0000 |
---|---|---|
committer | Gary Houston <ghouston@arglist.com> | 2000-03-12 19:58:56 +0000 |
commit | 19b27fa236d0a5e20a01443070a4bcffe025af05 (patch) | |
tree | 47acaaa74c16538afcd08006a57901c56e205559 /libguile/init.c | |
parent | f8a72ca4c983b3e4c19bffb9ec1e9b433331df8b (diff) | |
download | guile-19b27fa236d0a5e20a01443070a4bcffe025af05.tar.gz |
* fports.c (scm_fdes_to_port): call fcntl F_GETFL to test that
the fdes is valid before doing anything else. check that
the file descriptor supports the modes required.
(scm_fport_buffer_add): don't throw an error if fstat doesn't
work: just use the default buffer size.
* throw.c: change an outdated comment about scm_internal_catch
BODY: it doesn't take a jumpbuf arg.
* init.c (scm_standard_stream_to_port): install a handler in case
scm_fdes_to_port throws an error. don't check here whether the
file descriptor is valid, since scm_fdes_to_port will do that.
set the revealed count depending on whether the port got the
standard file descriptor.
(stream_body_data): new type.
(stream_body, stream_handler): new procs.
Diffstat (limited to 'libguile/init.c')
-rw-r--r-- | libguile/init.c | 81 |
1 files changed, 59 insertions, 22 deletions
diff --git a/libguile/init.c b/libguile/init.c index f170bd1f0..2cda6eb64 100644 --- a/libguile/init.c +++ b/libguile/init.c @@ -248,32 +248,69 @@ check_config (void) /* initializing standard and current I/O ports */ -/* Like scm_fdes_to_port, except that: - - NAME is a standard C string, not a Guile string - - we set the revealed count for FILE's file descriptor to 1, so - that FDES won't be closed when the port object is GC'd. - - when FDES is not a valid file descripter (as determined by - fstat), we open "/dev/null" and use that instead. In that case, - the revealed count is left at zero. -*/ +typedef struct +{ + int fdes; + char *mode; + char *name; +} stream_body_data; + +/* proc to be called in scope of exception handler stream_handler. */ static SCM -scm_standard_stream_to_port (int fdes, char *mode, char *name) +stream_body (void *data) { - struct stat st; - if (fstat (fdes, &st) == -1) - { - /* We do not bother to check errno. When fstat fails, there is - generally no point in trying to use FDES, I think. */ + stream_body_data *body_data = (stream_body_data *) data; + SCM port = scm_fdes_to_port (body_data->fdes, body_data->mode, + scm_makfrom0str (body_data->name)); - fdes = open ("/dev/null", (mode[0] == 'r')? O_RDONLY : O_WRONLY); - return scm_fdes_to_port (fdes, mode, scm_makfrom0str (name)); - } - else + SCM_REVEALED (port) = 1; + return port; +} + +/* exception handler for stream_body. */ +static SCM +stream_handler (void *data, SCM tag, SCM throw_args) +{ + return SCM_BOOL_F; +} + +/* Convert a file descriptor to a port, using scm_fdes_to_port. + - NAME is a C string, not a Guile string + - set the revealed count for FILE's file descriptor to 1, so + that fdes won't be closed when the port object is GC'd. + - catch exceptions: allow Guile to be able to start up even + if it has been handed bogus stdin/stdout/stderr. In this case + try to open a new stream on /dev/null. */ +static SCM +scm_standard_stream_to_port (int fdes, char *mode, char *name) +{ + SCM port; + stream_body_data body_data; + + body_data.fdes = fdes; + body_data.mode = mode; + body_data.name = name; + port = scm_internal_catch (SCM_BOOL_T, stream_body, &body_data, + stream_handler, NULL); + if (SCM_FALSEP (port)) { - SCM port = scm_fdes_to_port (fdes, mode, scm_makfrom0str (name)); - scm_set_port_revealed_x (port, SCM_MAKINUM (1)); - return port; - } + /* FIXME: /dev/null portability. there's also *null-device* in + r4rs.scm. */ + int null_fdes = open ("/dev/null", + (mode[0] == 'r') ? O_RDONLY : O_WRONLY); + + body_data.fdes = null_fdes; + port = (null_fdes == -1) ? SCM_BOOL_F + : scm_internal_catch (SCM_BOOL_T, stream_body, &body_data, + stream_handler, NULL); + /* if the standard fdes was not allocated, reset the revealed count + on the grounds that the user doesn't know what it is. */ + if (SCM_NFALSEP (port) && null_fdes != fdes) + SCM_REVEALED (port) = 0; + /* if port is still #f, we'll just leave it like that and + an error will be raised on the first attempt to use it. */ + } + return port; } /* Create standard ports from stdin, stdout, and stderr. */ |