* libguile/fports.c (scm_i_fdes_is_valid): New internal helper.
(scm_i_fdes_to_port): Use new helper.
* libguile/fports.h: Declare new helper.
* libguile/init.c (scm_standard_stream_to_port): Refactor to use
scm_i_fdes_is_valid.
\f
/* Building Guile ports from a file descriptor. */
+int
+scm_i_fdes_is_valid (int fdes, long mode_bits)
+{
+#ifdef F_GETFL
+ int flags = fcntl (fdes, F_GETFL, 0);
+ if (flags == -1)
+ return 0;
+ flags &= O_ACCMODE;
+ if (flags == O_RDWR)
+ return 1;
+ if (flags != O_WRONLY && (mode_bits & SCM_WRTNG))
+ return 0;
+ if (flags != O_RDONLY && (mode_bits & SCM_RDNG))
+ return 0;
+ return 1;
+#else
+ /* If we don't have F_GETFL, as on mingw, at least we can test that
+ it is a valid file descriptor. */
+ struct stat st;
+ return fstat (fdes, &st) == 0;
+#endif
+}
+
/* Build a Scheme port from an open file descriptor `fdes'.
MODE indicates whether FILE is open for reading or writing; it uses
the same notation as open-file's second argument.
if (options & SCM_FPORT_OPTION_VERIFY)
{
- /* Check that the foreign FD is valid and matches the mode
- bits. */
-#ifdef F_GETFL
- int 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))))
+ errno = 0;
+ if (!scm_i_fdes_is_valid (fdes, mode_bits))
{
+ if (errno)
+ SCM_SYSERROR;
SCM_MISC_ERROR ("requested file mode not available on fdes",
SCM_EOL);
}
-#else
- /* If we don't have F_GETFL, as on mingw, at least we can test that
- it is a valid file descriptor. */
- struct stat st;
- if (fstat (fdes, &st) != 0)
- SCM_SYSERROR;
-#endif
}
fp = (scm_t_fport *) scm_gc_malloc_pointerless (sizeof (scm_t_fport),
#ifndef SCM_FPORTS_H
#define SCM_FPORTS_H
-/* Copyright 1995-2001,2006,2008-2009,2011-2012,2017-2018
+/* Copyright 1995-2001,2006,2008-2009,2011-2012,2017-2019
Free Software Foundation, Inc.
This file is part of Guile.
that case. */
SCM_FPORT_OPTION_NOT_SEEKABLE = 1U<<1
};
+SCM_INTERNAL int scm_i_fdes_is_valid (int fdes, long mode_bits);
SCM_INTERNAL SCM scm_i_fdes_to_port (int fdes, long mode_bits, SCM name,
unsigned options);
+
#endif /* BUILDING_LIBGUILE */
#endif /* SCM_FPORTS_H */
\f
/* initializing standard and current I/O ports */
-typedef struct
-{
- int fdes;
- char *mode;
-} stream_body_data;
-
-/* 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_BOOL_F);
- scm_set_port_revealed_x (port, SCM_INUM1);
- return port;
-}
-
-/* exception handler for stream_body. */
-static SCM
-stream_handler (void *data SCM_UNUSED,
- SCM tag SCM_UNUSED,
- SCM throw_args SCM_UNUSED)
-{
- return SCM_BOOL_F;
-}
-
/* Convert a file descriptor to a port, using scm_fdes_to_port.
- 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. replace the
- bad ports with void ports. */
+ that fdes won't be closed when the port object is GC'd. */
static SCM
scm_standard_stream_to_port (int fdes, char *mode)
{
- SCM port;
- stream_body_data body_data;
-
- body_data.fdes = fdes;
- body_data.mode = mode;
- port = scm_internal_catch (SCM_BOOL_T, stream_body, &body_data,
- stream_handler, NULL);
- if (scm_is_false (port))
- port = scm_void_port (mode);
+ long mode_bits = scm_mode_bits (mode);
+
+ if (!scm_i_fdes_is_valid (fdes, mode_bits))
+ return scm_void_port (mode);
+
+ SCM port = scm_i_fdes_to_port (fdes, mode_bits, SCM_BOOL_F, 0);
+ scm_set_port_revealed_x (port, SCM_INUM1);
return port;
}