mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-30 08:50:23 +02:00
* 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.
This commit is contained in:
parent
f8a72ca4c9
commit
19b27fa236
4 changed files with 85 additions and 37 deletions
|
@ -67,6 +67,9 @@ scm_sizet fwrite ();
|
||||||
|
|
||||||
#include "iselect.h"
|
#include "iselect.h"
|
||||||
|
|
||||||
|
/* default buffer size, used if the O/S won't supply a value. */
|
||||||
|
static const int default_buffer_size = 1024;
|
||||||
|
|
||||||
/* create FPORT buffer with specified sizes (or -1 to use default size or
|
/* create FPORT buffer with specified sizes (or -1 to use default size or
|
||||||
0 for no buffer. */
|
0 for no buffer. */
|
||||||
static void
|
static void
|
||||||
|
@ -82,11 +85,10 @@ scm_fport_buffer_add (SCM port, int read_size, int write_size)
|
||||||
#ifdef HAVE_ST_BLKSIZE
|
#ifdef HAVE_ST_BLKSIZE
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (fstat (fp->fdes, &st) == -1)
|
default_size = (fstat (fp->fdes, &st) == -1) ? default_buffer_size
|
||||||
scm_syserror (s_scm_fport_buffer_add);
|
: st.st_blksize;
|
||||||
default_size = st.st_blksize;
|
|
||||||
#else
|
#else
|
||||||
default_size = 1024;
|
default_size = default_buffer_size;
|
||||||
#endif
|
#endif
|
||||||
if (read_size == -1)
|
if (read_size == -1)
|
||||||
read_size = default_size;
|
read_size = default_size;
|
||||||
|
@ -359,14 +361,28 @@ SCM_DEFINE (scm_open_file, "open-file", 2, 0, 0,
|
||||||
/* Build a Scheme port from an open file descriptor `fdes'.
|
/* Build a Scheme port from an open file descriptor `fdes'.
|
||||||
MODE indicates whether FILE is open for reading or writing; it uses
|
MODE indicates whether FILE is open for reading or writing; it uses
|
||||||
the same notation as open-file's second argument.
|
the same notation as open-file's second argument.
|
||||||
Use NAME as the port's filename. */
|
NAME is a string to be used as the port's filename.
|
||||||
|
*/
|
||||||
SCM
|
SCM
|
||||||
scm_fdes_to_port (int fdes, char *mode, SCM name)
|
scm_fdes_to_port (int fdes, char *mode, SCM name)
|
||||||
|
#define FUNC_NAME "scm_fdes_to_port"
|
||||||
{
|
{
|
||||||
long mode_bits = scm_mode_bits (mode);
|
long mode_bits = scm_mode_bits (mode);
|
||||||
SCM port;
|
SCM port;
|
||||||
scm_port *pt;
|
scm_port *pt;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
/* test that fdes is valid. */
|
||||||
|
flags = fcntl (fdes, F_GETFL, 0);
|
||||||
|
if (flags == -1)
|
||||||
|
SCM_SYSERROR;
|
||||||
|
flags &= O_ACCMODE;
|
||||||
|
if (flags != O_RDWR
|
||||||
|
&& ((flags != O_WRONLY && (mode_bits & SCM_WRTNG))
|
||||||
|
|| (flags != O_RDONLY && (mode_bits & SCM_RDNG))))
|
||||||
|
{
|
||||||
|
SCM_MISC_ERROR ("requested file mode not available on fdes", SCM_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
SCM_NEWCELL (port);
|
SCM_NEWCELL (port);
|
||||||
SCM_DEFER_INTS;
|
SCM_DEFER_INTS;
|
||||||
|
@ -378,7 +394,7 @@ scm_fdes_to_port (int fdes, char *mode, SCM name)
|
||||||
struct scm_fport *fp
|
struct scm_fport *fp
|
||||||
= (struct scm_fport *) malloc (sizeof (struct scm_fport));
|
= (struct scm_fport *) malloc (sizeof (struct scm_fport));
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
scm_memory_error ("scm_fdes_to_port");
|
SCM_MEMORY_ERROR;
|
||||||
fp->fdes = fdes;
|
fp->fdes = fdes;
|
||||||
pt->rw_random = SCM_FDES_RANDOM_P (fdes);
|
pt->rw_random = SCM_FDES_RANDOM_P (fdes);
|
||||||
SCM_SETSTREAM (port, fp);
|
SCM_SETSTREAM (port, fp);
|
||||||
|
@ -391,7 +407,7 @@ scm_fdes_to_port (int fdes, char *mode, SCM name)
|
||||||
SCM_ALLOW_INTS;
|
SCM_ALLOW_INTS;
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
/* Return a lower bound on the number of bytes available for input. */
|
/* Return a lower bound on the number of bytes available for input. */
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -248,32 +248,69 @@ check_config (void)
|
||||||
|
|
||||||
/* initializing standard and current I/O ports */
|
/* initializing standard and current I/O ports */
|
||||||
|
|
||||||
/* Like scm_fdes_to_port, except that:
|
typedef struct
|
||||||
- NAME is a standard C string, not a Guile string
|
{
|
||||||
- we set the revealed count for FILE's file descriptor to 1, so
|
int fdes;
|
||||||
that FDES won't be closed when the port object is GC'd.
|
char *mode;
|
||||||
- when FDES is not a valid file descripter (as determined by
|
char *name;
|
||||||
fstat), we open "/dev/null" and use that instead. In that case,
|
} stream_body_data;
|
||||||
the revealed count is left at zero.
|
|
||||||
*/
|
/* proc to be called in scope of exception handler stream_handler. */
|
||||||
|
static SCM
|
||||||
|
stream_body (void *data)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
|
||||||
|
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
|
static SCM
|
||||||
scm_standard_stream_to_port (int fdes, char *mode, char *name)
|
scm_standard_stream_to_port (int fdes, char *mode, char *name)
|
||||||
{
|
{
|
||||||
struct stat st;
|
SCM port;
|
||||||
if (fstat (fdes, &st) == -1)
|
stream_body_data body_data;
|
||||||
{
|
|
||||||
/* We do not bother to check errno. When fstat fails, there is
|
|
||||||
generally no point in trying to use FDES, I think. */
|
|
||||||
|
|
||||||
fdes = open ("/dev/null", (mode[0] == 'r')? O_RDONLY : O_WRONLY);
|
body_data.fdes = fdes;
|
||||||
return scm_fdes_to_port (fdes, mode, scm_makfrom0str (name));
|
body_data.mode = mode;
|
||||||
}
|
body_data.name = name;
|
||||||
else
|
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));
|
/* FIXME: /dev/null portability. there's also *null-device* in
|
||||||
scm_set_port_revealed_x (port, SCM_MAKINUM (1));
|
r4rs.scm. */
|
||||||
return port;
|
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. */
|
/* Create standard ports from stdin, stdout, and stderr. */
|
||||||
|
|
|
@ -448,13 +448,11 @@ SCM_DEFINE (scm_fdopen, "fdopen", 2, 0, 0,
|
||||||
"by @ref{File Ports, open-file}.")
|
"by @ref{File Ports, open-file}.")
|
||||||
#define FUNC_NAME s_scm_fdopen
|
#define FUNC_NAME s_scm_fdopen
|
||||||
{
|
{
|
||||||
SCM port;
|
|
||||||
|
|
||||||
SCM_VALIDATE_INUM (1,fdes);
|
SCM_VALIDATE_INUM (1,fdes);
|
||||||
SCM_VALIDATE_ROSTRING (2,modes);
|
SCM_VALIDATE_ROSTRING (2,modes);
|
||||||
SCM_COERCE_SUBSTR (modes);
|
SCM_COERCE_SUBSTR (modes);
|
||||||
port = scm_fdes_to_port (SCM_INUM (fdes), SCM_ROCHARS (modes), SCM_BOOL_F);
|
|
||||||
return port;
|
return scm_fdes_to_port (SCM_INUM (fdes), SCM_ROCHARS (modes), SCM_BOOL_F);
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
|
@ -148,13 +148,11 @@ struct jmp_buf_and_retval /* use only on the stack, in scm_catch */
|
||||||
|
|
||||||
BODY is a pointer to a C function which runs the body of the catch;
|
BODY is a pointer to a C function which runs the body of the catch;
|
||||||
this is the code you can throw from. We call it like this:
|
this is the code you can throw from. We call it like this:
|
||||||
BODY (BODY_DATA, JMPBUF)
|
BODY (BODY_DATA)
|
||||||
where:
|
where:
|
||||||
BODY_DATA is just the BODY_DATA argument we received; we pass it
|
BODY_DATA is just the BODY_DATA argument we received; we pass it
|
||||||
through to BODY as its first argument. The caller can make
|
through to BODY as its first argument. The caller can make
|
||||||
BODY_DATA point to anything useful that BODY might need.
|
BODY_DATA point to anything useful that BODY might need.
|
||||||
JMPBUF is the Scheme jmpbuf object corresponding to this catch,
|
|
||||||
which we have just created and initialized.
|
|
||||||
|
|
||||||
HANDLER is a pointer to a C function to deal with a throw to TAG,
|
HANDLER is a pointer to a C function to deal with a throw to TAG,
|
||||||
should one occur. We call it like this:
|
should one occur. We call it like this:
|
||||||
|
@ -610,7 +608,6 @@ SCM_DEFINE (scm_throw, "throw", 1, 0, 1,
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
||||||
SCM
|
SCM
|
||||||
scm_ithrow (SCM key, SCM args, int noreturn)
|
scm_ithrow (SCM key, SCM args, int noreturn)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue