-/* Copyright (C) 1995 Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * As a special exception, the Free Software Foundation gives permission
- * for additional uses of the text contained in its release of GUILE.
- *
- * The exception is that, if you link the GUILE library with other files
- * to produce an executable, this does not by itself cause the
- * resulting executable to be covered by the GNU General Public License.
- * Your use of that executable is in no way restricted on account of
- * linking the GUILE library code into it.
- *
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
- *
- * This exception applies only to the code released by the
- * Free Software Foundation under the name GUILE. If you copy
- * code from other Free Software Foundation releases into a copy of
- * GUILE, as the General Public License permits, the exception does
- * not apply to the code that you add in this way. To avoid misleading
- * anyone as to the status of such modified files, you must delete
- * this exception notice from them.
- *
- * If you write modifications of your own for GUILE, it is your choice
- * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.
- */
-\f
-
-
-#include <stdio.h>
-#include "fd.h"
-#include "_scm.h"
-#include "fports.h"
-
-#include "ioext.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-\f
-
-SCM_PROC (s_sys_ftell, "ftell", 1, 0, 0, scm_sys_ftell);
-
-SCM
-scm_sys_ftell (port)
- SCM port;
-{
- long pos;
- SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_ftell);
- SCM_SYSCALL (pos = ftell ((FILE *)SCM_STREAM (port)));
- if (pos < 0)
- scm_syserror (s_sys_ftell);
- if (pos > 0 && SCM_CRDYP (port))
- pos--;
- return SCM_MAKINUM (pos);
-}
-
-
-
-SCM_PROC (s_sys_fseek, "fseek", 3, 0, 0, scm_sys_fseek);
-
-SCM
-scm_sys_fseek (port, offset, whence)
- SCM port;
- SCM offset;
- SCM whence;
-{
- int rv;
- SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_fseek);
- SCM_ASSERT (SCM_INUMP (offset), offset, SCM_ARG2, s_sys_fseek);
- SCM_ASSERT (SCM_INUMP (whence) && (SCM_INUM (whence) < 3) && (SCM_INUM (whence) >= 0),
- whence, SCM_ARG3, s_sys_fseek);
- SCM_CLRDY (port); /* Clear ungetted char */
- /* Values of whence are interned in scm_init_ioext. */
- rv = fseek ((FILE *)SCM_STREAM (port), SCM_INUM (offset), SCM_INUM (whence));
- if (rv != 0)
- scm_syserror (s_sys_fseek);
- return SCM_UNSPECIFIED;
-}
-
-
-
-SCM_PROC (s_sys_freopen, "freopen", 3, 0, 0, scm_sys_freopen);
-
-SCM
-scm_sys_freopen (filename, modes, port)
- SCM filename;
- SCM modes;
- SCM port;
-{
- FILE *f;
- SCM_ASSERT (SCM_NIMP (filename) && SCM_STRINGP (filename), filename, SCM_ARG1, s_sys_freopen);
- SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_freopen);
- SCM_DEFER_INTS;
- SCM_ASSERT (SCM_NIMP (port) && SCM_FPORTP (port), port, SCM_ARG3, s_sys_freopen);
- SCM_SYSCALL (f = freopen (SCM_CHARS (filename), SCM_CHARS (modes), (FILE *)SCM_STREAM (port)));
- if (!f)
- {
- SCM p;
- p = port;
- port = SCM_MAKINUM (errno);
- SCM_SETAND_CAR (p, ~SCM_OPN);
- scm_remove_from_port_table (p);
- }
- else
- {
- SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes)));
- SCM_SETSTREAM (port, (SCM)f);
- SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes)));
- if (SCM_BUF0 & SCM_CAR (port))
- scm_setbuf0 (port);
- }
- SCM_ALLOW_INTS;
- return port;
-}
-
-
-
-SCM_PROC (s_sys_duplicate_port, "duplicate-port", 2, 0, 0, scm_sys_duplicate_port);
-
-SCM
-scm_sys_duplicate_port (oldpt, modes)
- SCM oldpt;
- SCM modes;
-{
- int oldfd;
- int newfd;
- FILE *f;
- SCM newpt;
- SCM_ASSERT (SCM_NIMP (oldpt) && SCM_OPPORTP (oldpt), oldpt, SCM_ARG1, s_sys_duplicate_port);
- SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_duplicate_port);
- SCM_NEWCELL (newpt);
- SCM_DEFER_INTS;
- oldfd = fileno ((FILE *)SCM_STREAM (oldpt));
- if (oldfd == -1)
- scm_syserror (s_sys_duplicate_port);
- SCM_SYSCALL (newfd = dup (oldfd));
- if (newfd == -1)
- scm_syserror (s_sys_duplicate_port);
- f = fdopen (newfd, SCM_CHARS (modes));
- if (!f)
- {
- SCM_SYSCALL (close (newfd));
- scm_syserror (s_sys_duplicate_port);
- }
- {
- struct scm_port_table * pt;
- pt = scm_add_to_port_table (newpt);
- SCM_SETPTAB_ENTRY (newpt, pt);
- SCM_SETCAR (newpt, scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes)));
- if (SCM_BUF0 & SCM_CAR (newpt))
- scm_setbuf0 (newpt);
- SCM_SETSTREAM (newpt, (SCM)f);
- SCM_PTAB_ENTRY (newpt)->file_name = SCM_PTAB_ENTRY (oldpt)->file_name;
- }
- SCM_ALLOW_INTS;
- return newpt;
-}
-
-
-
-SCM_PROC (s_sys_redirect_port, "redirect-port", 2, 0, 0, scm_sys_redirect_port);
-
-SCM
-scm_sys_redirect_port (into_pt, from_pt)
- SCM into_pt;
- SCM from_pt;
-{
- int ans, oldfd, newfd;
- SCM_DEFER_INTS;
- SCM_ASSERT (SCM_NIMP (into_pt) && SCM_OPPORTP (into_pt), into_pt, SCM_ARG1, s_sys_redirect_port);
- SCM_ASSERT (SCM_NIMP (from_pt) && SCM_OPPORTP (from_pt), from_pt, SCM_ARG2, s_sys_redirect_port);
- oldfd = fileno ((FILE *)SCM_STREAM (into_pt));
- if (oldfd == -1)
- scm_syserror (s_sys_redirect_port);
- newfd = fileno ((FILE *)SCM_STREAM (from_pt));
- if (newfd == -1)
- scm_syserror (s_sys_redirect_port);
- SCM_SYSCALL (ans = dup2 (oldfd, newfd));
- if (ans == -1)
- scm_syserror (s_sys_redirect_port);
- SCM_ALLOW_INTS;
- return SCM_UNSPECIFIED;
-}
-
-SCM_PROC (s_sys_fileno, "fileno", 1, 0, 0, scm_sys_fileno);
-
-SCM
-scm_sys_fileno (port)
- SCM port;
-{
- int fd;
- SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_fileno);
- fd = fileno ((FILE *)SCM_STREAM (port));
- if (fd == -1)
- scm_syserror (s_sys_fileno);
- return SCM_MAKINUM (fd);
-}
-
-SCM_PROC (s_sys_isatty, "isatty?", 1, 0, 0, scm_sys_isatty_p);
-
-SCM
-scm_sys_isatty_p (port)
- SCM port;
-{
- int rv;
- SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_isatty);
- rv = fileno ((FILE *)SCM_STREAM (port));
- if (rv == -1)
- scm_syserror (s_sys_isatty);
- rv = isatty (rv);
- return rv ? SCM_BOOL_T : SCM_BOOL_F;
-}
-
-
-
-SCM_PROC (s_sys_fdopen, "fdopen", 2, 0, 0, scm_sys_fdopen);
-
-SCM
-scm_sys_fdopen (fdes, modes)
- SCM fdes;
- SCM modes;
-{
- FILE *f;
- SCM port;
- struct scm_port_table * pt;
-
- SCM_ASSERT (SCM_INUMP (fdes), fdes, SCM_ARG1, s_sys_fdopen);
- SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_fdopen);
- SCM_NEWCELL (port);
- SCM_DEFER_INTS;
- f = fdopen (SCM_INUM (fdes), SCM_CHARS (modes));
- if (f == NULL)
- scm_syserror (s_sys_fdopen);
- pt = scm_add_to_port_table (port);
- SCM_SETPTAB_ENTRY (port, pt);
- SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes)));
- if (SCM_BUF0 & SCM_CAR (port))
- scm_setbuf0 (port);
- SCM_SETSTREAM (port, (SCM)f);
- SCM_ALLOW_INTS;
- return port;
-}
-
-
-
-/* Move a port's underlying file descriptor to a given value.
- * Returns #f if fdes is already the given value.
- * #t if fdes moved.
- * MOVE->FDES is implemented in Scheme and calls this primitive.
- */
-SCM_PROC (s_sys_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0, scm_sys_primitive_move_to_fdes);
-
-SCM
-scm_sys_primitive_move_to_fdes (port, fd)
- SCM port;
- SCM fd;
-{
- FILE *stream;
- int old_fd;
- int new_fd;
- int rv;
-
- SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_primitive_move_to_fdes);
- SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG2, s_sys_primitive_move_to_fdes);
- SCM_DEFER_INTS;
- stream = (FILE *)SCM_STREAM (port);
- old_fd = fileno (stream);
- new_fd = SCM_INUM (fd);
- if (old_fd == new_fd)
- {
- SCM_ALLOW_INTS;
- return SCM_BOOL_F;
- }
- scm_evict_ports (new_fd);
- rv = dup2 (old_fd, new_fd);
- if (rv == -1)
- scm_syserror (s_sys_primitive_move_to_fdes);
- scm_setfileno (stream, new_fd);
- SCM_SYSCALL (close (old_fd));
- SCM_ALLOW_INTS;
- return SCM_BOOL_T;
-}
-
-
-void
-scm_setfileno (fs, fd)
- FILE *fs;
- int fd;
-{
-#ifdef SET_FILE_FD_FIELD
- SET_FILE_FD_FIELD(fs, fd);
-#else
- Configure could not guess the name of the correct field in a FILE *.
-
- This function needs to be ported to your system.
-
- SET_FILE_FD_FIELD should change the descriptor refered to by a stdio
- stream, and nothing else.
-
- The way to port this file is to add cases to configure.in. Search
- that file for "SET_FILE_FD_FIELD" and follow the examples there.
-#endif
-}
-
-/* Move ports with the specified file descriptor to new descriptors,
- * reseting the revealed count to 0.
- * Should be called with SCM_DEFER_INTS active.
- */
-
-void
-scm_evict_ports (fd)
- int fd;
-{
- int i;
-
- for (i = 0; i < scm_port_table_size; i++)
- {
- if (SCM_FPORTP (scm_port_table[i]->port)
- && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == fd)
- {
- scm_setfileno ((FILE *)SCM_STREAM (scm_port_table[i]->port), dup (fd));
- scm_set_port_revealed_x (scm_port_table[i]->port, SCM_MAKINUM (0));
- }
- }
-}
-
-/* Return a list of ports using a given file descriptor. */
-SCM_PROC(s_fdes_to_ports, "fdes->ports", 1, 0, 0, scm_fdes_to_ports);
-
-SCM
-scm_fdes_to_ports (fd)
- SCM fd;
-{
- SCM result = SCM_EOL;
- int int_fd;
- int i;
-
- SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG1, s_fdes_to_ports);
- int_fd = SCM_INUM (fd);
-
- SCM_DEFER_INTS;
- for (i = 0; i < scm_port_table_size; i++)
- {
- if (SCM_FPORTP (scm_port_table[i]->port)
- && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == int_fd)
- result = scm_cons (scm_port_table[i]->port, result);
- }
- SCM_ALLOW_INTS;
- return result;
-}
-
-
-void
-scm_init_ioext ()
-{
- /* fseek() symbols. */
- scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
- scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
- scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
-
- /* File type/permission bits. */
-#ifdef S_IRUSR
- scm_sysintern ("S_IRUSR", SCM_MAKINUM (S_IRUSR));
-#endif
-#ifdef S_IWUSR
- scm_sysintern ("S_IWUSR", SCM_MAKINUM (S_IWUSR));
-#endif
-#ifdef S_IXUSR
- scm_sysintern ("S_IXUSR", SCM_MAKINUM (S_IXUSR));
-#endif
-#ifdef S_IRWXU
- scm_sysintern ("S_IRWXU", SCM_MAKINUM (S_IRWXU));
-#endif
-
-#ifdef S_IRGRP
- scm_sysintern ("S_IRGRP", SCM_MAKINUM (S_IRGRP));
-#endif
-#ifdef S_IWGRP
- scm_sysintern ("S_IWGRP", SCM_MAKINUM (S_IWGRP));
-#endif
-#ifdef S_IXGRP
- scm_sysintern ("S_IXGRP", SCM_MAKINUM (S_IXGRP));
-#endif
-#ifdef S_IRWXG
- scm_sysintern ("S_IRWXG", SCM_MAKINUM (S_IRWXG));
-#endif
-
-#ifdef S_IROTH
- scm_sysintern ("S_IROTH", SCM_MAKINUM (S_IROTH));
-#endif
-#ifdef S_IWOTH
- scm_sysintern ("S_IWOTH", SCM_MAKINUM (S_IWOTH));
-#endif
-#ifdef S_IXOTH
- scm_sysintern ("S_IXOTH", SCM_MAKINUM (S_IXOTH));
-#endif
-#ifdef S_IRWXO
- scm_sysintern ("S_IRWXO", SCM_MAKINUM (S_IRWXO));
-#endif
-
-#ifdef S_ISUID
- scm_sysintern ("S_ISUID", SCM_MAKINUM (S_ISUID));
-#endif
-#ifdef S_ISGID
- scm_sysintern ("S_ISGID", SCM_MAKINUM (S_ISGID));
-#endif
-#ifdef S_ISVTX
- scm_sysintern ("S_ISVTX", SCM_MAKINUM (S_ISVTX));
-#endif
-
-#ifdef S_IFMT
- scm_sysintern ("S_IFMT", SCM_MAKINUM (S_IFMT));
-#endif
-#ifdef S_IFDIR
- scm_sysintern ("S_IFDIR", SCM_MAKINUM (S_IFDIR));
-#endif
-#ifdef S_IFCHR
- scm_sysintern ("S_IFCHR", SCM_MAKINUM (S_IFCHR));
-#endif
-#ifdef S_IFBLK
- scm_sysintern ("S_IFBLK", SCM_MAKINUM (S_IFBLK));
-#endif
-#ifdef S_IFREG
- scm_sysintern ("S_IFREG", SCM_MAKINUM (S_IFREG));
-#endif
-#ifdef S_IFLNK
- scm_sysintern ("S_IFLNK", SCM_MAKINUM (S_IFLNK));
-#endif
-#ifdef S_IFSOCK
- scm_sysintern ("S_IFSOCK", SCM_MAKINUM (S_IFSOCK));
-#endif
-#ifdef S_IFIFO
- scm_sysintern ("S_IFIFO", SCM_MAKINUM (S_IFIFO));
-#endif
-#include "ioext.x"
-}
-
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+\f
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "libguile/_scm.h"
+#include "libguile/ioext.h"
+#include "libguile/fports.h"
+#include "libguile/feature.h"
+#include "libguile/ports.h"
+#include "libguile/strings.h"
+#include "libguile/validate.h"
+
+#include <fcntl.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+\f
+
+SCM_DEFINE (scm_ftell, "ftell", 1, 0, 0,
+ (SCM fd_port),
+ "Return an integer representing the current position of\n"
+ "@var{fd/port}, measured from the beginning. Equivalent to:\n"
+ "\n"
+ "@lisp\n"
+ "(seek port 0 SEEK_CUR)\n"
+ "@end lisp")
+#define FUNC_NAME s_scm_ftell
+{
+ return scm_seek (fd_port, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_redirect_port, "redirect-port", 2, 0, 0,
+ (SCM old, SCM new),
+ "This procedure takes two ports and duplicates the underlying file\n"
+ "descriptor from @var{old-port} into @var{new-port}. The\n"
+ "current file descriptor in @var{new-port} will be closed.\n"
+ "After the redirection the two ports will share a file position\n"
+ "and file status flags.\n\n"
+ "The return value is unspecified.\n\n"
+ "Unexpected behaviour can result if both ports are subsequently used\n"
+ "and the original and/or duplicate ports are buffered.\n\n"
+ "This procedure does not have any side effects on other ports or\n"
+ "revealed counts.")
+#define FUNC_NAME s_scm_redirect_port
+{
+ int ans, oldfd, newfd;
+ scm_t_fport *fp;
+
+ old = SCM_COERCE_OUTPORT (old);
+ new = SCM_COERCE_OUTPORT (new);
+
+ SCM_VALIDATE_OPFPORT (1, old);
+ SCM_VALIDATE_OPFPORT (2, new);
+ oldfd = SCM_FPORT_FDES (old);
+ fp = SCM_FSTREAM (new);
+ newfd = fp->fdes;
+ if (oldfd != newfd)
+ {
+ scm_t_port *pt = SCM_PTAB_ENTRY (new);
+ scm_t_port *old_pt = SCM_PTAB_ENTRY (old);
+ scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (new)];
+
+ /* must flush to old fdes. */
+ if (pt->rw_active == SCM_PORT_WRITE)
+ ptob->flush (new);
+ else if (pt->rw_active == SCM_PORT_READ)
+ scm_end_input (new);
+ ans = dup2 (oldfd, newfd);
+ if (ans == -1)
+ SCM_SYSERROR;
+ pt->rw_random = old_pt->rw_random;
+ /* continue using existing buffers, even if inappropriate. */
+ }
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_dup_to_fdes, "dup->fdes", 1, 1, 0,
+ (SCM fd_or_port, SCM fd),
+ "Return a new integer file descriptor referring to the open file\n"
+ "designated by @var{fd_or_port}, which must be either an open\n"
+ "file port or a file descriptor.")
+#define FUNC_NAME s_scm_dup_to_fdes
+{
+ int oldfd, newfd, rv;
+
+ fd_or_port = SCM_COERCE_OUTPORT (fd_or_port);
+
+ if (SCM_INUMP (fd_or_port))
+ oldfd = SCM_INUM (fd_or_port);
+ else
+ {
+ SCM_VALIDATE_OPFPORT (1, fd_or_port);
+ oldfd = SCM_FPORT_FDES (fd_or_port);
+ }
+
+ if (SCM_UNBNDP (fd))
+ {
+ newfd = dup (oldfd);
+ if (newfd == -1)
+ SCM_SYSERROR;
+ fd = SCM_MAKINUM (newfd);
+ }
+ else
+ {
+ SCM_VALIDATE_INUM_COPY (2, fd, newfd);
+ if (oldfd != newfd)
+ {
+ scm_evict_ports (newfd); /* see scsh manual. */
+ rv = dup2 (oldfd, newfd);
+ if (rv == -1)
+ SCM_SYSERROR;
+ }
+ }
+ return fd;
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_dup2, "dup2", 2, 0, 0,
+ (SCM oldfd, SCM newfd),
+ "A simple wrapper for the @code{dup2} system call.\n"
+ "Copies the file descriptor @var{oldfd} to descriptor\n"
+ "number @var{newfd}, replacing the previous meaning\n"
+ "of @var{newfd}. Both @var{oldfd} and @var{newfd} must\n"
+ "be integers.\n"
+ "Unlike for dup->fdes or primitive-move->fdes, no attempt\n"
+ "is made to move away ports which are using @var{newfd}.\n"
+ "The return value is unspecified.")
+#define FUNC_NAME s_scm_dup2
+{
+ int c_oldfd;
+ int c_newfd;
+ int rv;
+
+ SCM_VALIDATE_INUM_COPY (1, oldfd, c_oldfd);
+ SCM_VALIDATE_INUM_COPY (2, newfd, c_newfd);
+ rv = dup2 (c_oldfd, c_newfd);
+ if (rv == -1)
+ SCM_SYSERROR;
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_fileno, "fileno", 1, 0, 0,
+ (SCM port),
+ "Return the integer file descriptor underlying @var{port}. Does\n"
+ "not change its revealed count.")
+#define FUNC_NAME s_scm_fileno
+{
+ port = SCM_COERCE_OUTPORT (port);
+ SCM_VALIDATE_OPFPORT (1, port);
+ return SCM_MAKINUM (SCM_FPORT_FDES (port));
+}
+#undef FUNC_NAME
+
+/* GJB:FIXME:: why does this not throw
+ an error if the arg is not a port?
+ This proc as is would be better names isattyport?
+ if it is not going to assume that the arg is a port
+
+ [cmm] I don't see any problem with the above. why should a type
+ predicate assume _anything_ about its argument?
+*/
+SCM_DEFINE (scm_isatty_p, "isatty?", 1, 0, 0,
+ (SCM port),
+ "Return @code{#t} if @var{port} is using a serial non--file\n"
+ "device, otherwise @code{#f}.")
+#define FUNC_NAME s_scm_isatty_p
+{
+ int rv;
+
+ port = SCM_COERCE_OUTPORT (port);
+
+ if (!SCM_OPFPORTP (port))
+ return SCM_BOOL_F;
+
+ rv = isatty (SCM_FPORT_FDES (port));
+ return SCM_BOOL(rv);
+}
+#undef FUNC_NAME
+
+
+
+SCM_DEFINE (scm_fdopen, "fdopen", 2, 0, 0,
+ (SCM fdes, SCM modes),
+ "Return a new port based on the file descriptor @var{fdes}.\n"
+ "Modes are given by the string @var{modes}. The revealed count\n"
+ "of the port is initialized to zero. The modes string is the\n"
+ "same as that accepted by @ref{File Ports, open-file}.")
+#define FUNC_NAME s_scm_fdopen
+{
+ SCM_VALIDATE_INUM (1, fdes);
+ SCM_VALIDATE_STRING (2, modes);
+
+ return scm_fdes_to_port (SCM_INUM (fdes), SCM_STRING_CHARS (modes), SCM_BOOL_F);
+}
+#undef FUNC_NAME
+
+
+
+/* Move a port's underlying file descriptor to a given value.
+ * Returns #f if fdes is already the given value.
+ * #t if fdes moved.
+ * MOVE->FDES is implemented in Scheme and calls this primitive.
+ */
+SCM_DEFINE (scm_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0,
+ (SCM port, SCM fd),
+ "Moves the underlying file descriptor for @var{port} to the integer\n"
+ "value @var{fdes} without changing the revealed count of @var{port}.\n"
+ "Any other ports already using this descriptor will be automatically\n"
+ "shifted to new descriptors and their revealed counts reset to zero.\n"
+ "The return value is @code{#f} if the file descriptor already had the\n"
+ "required value or @code{#t} if it was moved.")
+#define FUNC_NAME s_scm_primitive_move_to_fdes
+{
+ scm_t_fport *stream;
+ int old_fd;
+ int new_fd;
+ int rv;
+
+ port = SCM_COERCE_OUTPORT (port);
+
+ SCM_VALIDATE_OPFPORT (1, port);
+ SCM_VALIDATE_INUM (2, fd);
+ stream = SCM_FSTREAM (port);
+ old_fd = stream->fdes;
+ new_fd = SCM_INUM (fd);
+ if (old_fd == new_fd)
+ {
+ return SCM_BOOL_F;
+ }
+ scm_evict_ports (new_fd);
+ rv = dup2 (old_fd, new_fd);
+ if (rv == -1)
+ SCM_SYSERROR;
+ stream->fdes = new_fd;
+ SCM_SYSCALL (close (old_fd));
+ return SCM_BOOL_T;
+}
+#undef FUNC_NAME
+
+/* Return a list of ports using a given file descriptor. */
+SCM_DEFINE (scm_fdes_to_ports, "fdes->ports", 1, 0, 0,
+ (SCM fd),
+ "Return a list of existing ports which have @var{fdes} as an\n"
+ "underlying file descriptor, without changing their revealed\n"
+ "counts.")
+#define FUNC_NAME s_scm_fdes_to_ports
+{
+ SCM result = SCM_EOL;
+ int int_fd;
+ long i;
+
+ SCM_VALIDATE_INUM_COPY (1, fd, int_fd);
+
+ scm_mutex_lock (&scm_i_port_table_mutex);
+ for (i = 0; i < scm_i_port_table_size; i++)
+ {
+ if (SCM_OPFPORTP (scm_i_port_table[i]->port)
+ && ((scm_t_fport *) scm_i_port_table[i]->stream)->fdes == int_fd)
+ result = scm_cons (scm_i_port_table[i]->port, result);
+ }
+ scm_mutex_unlock (&scm_i_port_table_mutex);
+ return result;
+}
+#undef FUNC_NAME
+
+
+void
+scm_init_ioext ()
+{
+ scm_add_feature ("i/o-extensions");
+
+#include "libguile/ioext.x"
+}
+
+
+/*
+ Local Variables:
+ c-file-style: "gnu"
+ End:
+*/