ioext.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2006 Free Software Foundation, Inc.
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public
  5. * License as published by the Free Software Foundation; either
  6. * version 2.1 of the License, or (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. # include <config.h>
  19. #endif
  20. #include <stdio.h>
  21. #include <errno.h>
  22. #include "libguile/_scm.h"
  23. #include "libguile/ioext.h"
  24. #include "libguile/fports.h"
  25. #include "libguile/feature.h"
  26. #include "libguile/ports.h"
  27. #include "libguile/strings.h"
  28. #include "libguile/validate.h"
  29. #include "libguile/dynwind.h"
  30. #include <fcntl.h>
  31. #ifdef HAVE_IO_H
  32. #include <io.h>
  33. #endif
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. SCM_DEFINE (scm_ftell, "ftell", 1, 0, 0,
  38. (SCM fd_port),
  39. "Return an integer representing the current position of\n"
  40. "@var{fd/port}, measured from the beginning. Equivalent to:\n"
  41. "\n"
  42. "@lisp\n"
  43. "(seek port 0 SEEK_CUR)\n"
  44. "@end lisp")
  45. #define FUNC_NAME s_scm_ftell
  46. {
  47. return scm_seek (fd_port, SCM_INUM0, scm_from_int (SEEK_CUR));
  48. }
  49. #undef FUNC_NAME
  50. SCM_DEFINE (scm_redirect_port, "redirect-port", 2, 0, 0,
  51. (SCM old, SCM new),
  52. "This procedure takes two ports and duplicates the underlying file\n"
  53. "descriptor from @var{old-port} into @var{new-port}. The\n"
  54. "current file descriptor in @var{new-port} will be closed.\n"
  55. "After the redirection the two ports will share a file position\n"
  56. "and file status flags.\n\n"
  57. "The return value is unspecified.\n\n"
  58. "Unexpected behaviour can result if both ports are subsequently used\n"
  59. "and the original and/or duplicate ports are buffered.\n\n"
  60. "This procedure does not have any side effects on other ports or\n"
  61. "revealed counts.")
  62. #define FUNC_NAME s_scm_redirect_port
  63. {
  64. int ans, oldfd, newfd;
  65. scm_t_fport *fp;
  66. old = SCM_COERCE_OUTPORT (old);
  67. new = SCM_COERCE_OUTPORT (new);
  68. SCM_VALIDATE_OPFPORT (1, old);
  69. SCM_VALIDATE_OPFPORT (2, new);
  70. oldfd = SCM_FPORT_FDES (old);
  71. fp = SCM_FSTREAM (new);
  72. newfd = fp->fdes;
  73. if (oldfd != newfd)
  74. {
  75. scm_t_port *pt = SCM_PTAB_ENTRY (new);
  76. scm_t_port *old_pt = SCM_PTAB_ENTRY (old);
  77. scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (new)];
  78. /* must flush to old fdes. */
  79. if (pt->rw_active == SCM_PORT_WRITE)
  80. ptob->flush (new);
  81. else if (pt->rw_active == SCM_PORT_READ)
  82. scm_end_input (new);
  83. ans = dup2 (oldfd, newfd);
  84. if (ans == -1)
  85. SCM_SYSERROR;
  86. pt->rw_random = old_pt->rw_random;
  87. /* continue using existing buffers, even if inappropriate. */
  88. }
  89. return SCM_UNSPECIFIED;
  90. }
  91. #undef FUNC_NAME
  92. SCM_DEFINE (scm_dup_to_fdes, "dup->fdes", 1, 1, 0,
  93. (SCM fd_or_port, SCM fd),
  94. "Return a new integer file descriptor referring to the open file\n"
  95. "designated by @var{fd_or_port}, which must be either an open\n"
  96. "file port or a file descriptor.")
  97. #define FUNC_NAME s_scm_dup_to_fdes
  98. {
  99. int oldfd, newfd, rv;
  100. fd_or_port = SCM_COERCE_OUTPORT (fd_or_port);
  101. if (scm_is_integer (fd_or_port))
  102. oldfd = scm_to_int (fd_or_port);
  103. else
  104. {
  105. SCM_VALIDATE_OPFPORT (1, fd_or_port);
  106. oldfd = SCM_FPORT_FDES (fd_or_port);
  107. }
  108. if (SCM_UNBNDP (fd))
  109. {
  110. newfd = dup (oldfd);
  111. if (newfd == -1)
  112. SCM_SYSERROR;
  113. fd = scm_from_int (newfd);
  114. }
  115. else
  116. {
  117. newfd = scm_to_int (fd);
  118. if (oldfd != newfd)
  119. {
  120. scm_evict_ports (newfd); /* see scsh manual. */
  121. rv = dup2 (oldfd, newfd);
  122. if (rv == -1)
  123. SCM_SYSERROR;
  124. }
  125. }
  126. return fd;
  127. }
  128. #undef FUNC_NAME
  129. SCM_DEFINE (scm_dup2, "dup2", 2, 0, 0,
  130. (SCM oldfd, SCM newfd),
  131. "A simple wrapper for the @code{dup2} system call.\n"
  132. "Copies the file descriptor @var{oldfd} to descriptor\n"
  133. "number @var{newfd}, replacing the previous meaning\n"
  134. "of @var{newfd}. Both @var{oldfd} and @var{newfd} must\n"
  135. "be integers.\n"
  136. "Unlike for dup->fdes or primitive-move->fdes, no attempt\n"
  137. "is made to move away ports which are using @var{newfd}.\n"
  138. "The return value is unspecified.")
  139. #define FUNC_NAME s_scm_dup2
  140. {
  141. int c_oldfd;
  142. int c_newfd;
  143. int rv;
  144. c_oldfd = scm_to_int (oldfd);
  145. c_newfd = scm_to_int (newfd);
  146. rv = dup2 (c_oldfd, c_newfd);
  147. if (rv == -1)
  148. SCM_SYSERROR;
  149. return SCM_UNSPECIFIED;
  150. }
  151. #undef FUNC_NAME
  152. SCM_DEFINE (scm_fileno, "fileno", 1, 0, 0,
  153. (SCM port),
  154. "Return the integer file descriptor underlying @var{port}. Does\n"
  155. "not change its revealed count.")
  156. #define FUNC_NAME s_scm_fileno
  157. {
  158. port = SCM_COERCE_OUTPORT (port);
  159. SCM_VALIDATE_OPFPORT (1, port);
  160. return scm_from_int (SCM_FPORT_FDES (port));
  161. }
  162. #undef FUNC_NAME
  163. /* GJB:FIXME:: why does this not throw
  164. an error if the arg is not a port?
  165. This proc as is would be better names isattyport?
  166. if it is not going to assume that the arg is a port
  167. [cmm] I don't see any problem with the above. why should a type
  168. predicate assume _anything_ about its argument?
  169. */
  170. SCM_DEFINE (scm_isatty_p, "isatty?", 1, 0, 0,
  171. (SCM port),
  172. "Return @code{#t} if @var{port} is using a serial non--file\n"
  173. "device, otherwise @code{#f}.")
  174. #define FUNC_NAME s_scm_isatty_p
  175. {
  176. int rv;
  177. port = SCM_COERCE_OUTPORT (port);
  178. if (!SCM_OPFPORTP (port))
  179. return SCM_BOOL_F;
  180. rv = isatty (SCM_FPORT_FDES (port));
  181. return scm_from_bool(rv);
  182. }
  183. #undef FUNC_NAME
  184. SCM_DEFINE (scm_fdopen, "fdopen", 2, 0, 0,
  185. (SCM fdes, SCM modes),
  186. "Return a new port based on the file descriptor @var{fdes}.\n"
  187. "Modes are given by the string @var{modes}. The revealed count\n"
  188. "of the port is initialized to zero. The modes string is the\n"
  189. "same as that accepted by @ref{File Ports, open-file}.")
  190. #define FUNC_NAME s_scm_fdopen
  191. {
  192. return scm_i_fdes_to_port (scm_to_int (fdes),
  193. scm_i_mode_bits (modes), SCM_BOOL_F);
  194. }
  195. #undef FUNC_NAME
  196. /* Move a port's underlying file descriptor to a given value.
  197. * Returns #f if fdes is already the given value.
  198. * #t if fdes moved.
  199. * MOVE->FDES is implemented in Scheme and calls this primitive.
  200. */
  201. SCM_DEFINE (scm_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0,
  202. (SCM port, SCM fd),
  203. "Moves the underlying file descriptor for @var{port} to the integer\n"
  204. "value @var{fdes} without changing the revealed count of @var{port}.\n"
  205. "Any other ports already using this descriptor will be automatically\n"
  206. "shifted to new descriptors and their revealed counts reset to zero.\n"
  207. "The return value is @code{#f} if the file descriptor already had the\n"
  208. "required value or @code{#t} if it was moved.")
  209. #define FUNC_NAME s_scm_primitive_move_to_fdes
  210. {
  211. scm_t_fport *stream;
  212. int old_fd;
  213. int new_fd;
  214. int rv;
  215. port = SCM_COERCE_OUTPORT (port);
  216. SCM_VALIDATE_OPFPORT (1, port);
  217. stream = SCM_FSTREAM (port);
  218. old_fd = stream->fdes;
  219. new_fd = scm_to_int (fd);
  220. if (old_fd == new_fd)
  221. {
  222. return SCM_BOOL_F;
  223. }
  224. scm_evict_ports (new_fd);
  225. rv = dup2 (old_fd, new_fd);
  226. if (rv == -1)
  227. SCM_SYSERROR;
  228. stream->fdes = new_fd;
  229. SCM_SYSCALL (close (old_fd));
  230. return SCM_BOOL_T;
  231. }
  232. #undef FUNC_NAME
  233. /* Return a list of ports using a given file descriptor. */
  234. SCM_DEFINE (scm_fdes_to_ports, "fdes->ports", 1, 0, 0,
  235. (SCM fd),
  236. "Return a list of existing ports which have @var{fdes} as an\n"
  237. "underlying file descriptor, without changing their revealed\n"
  238. "counts.")
  239. #define FUNC_NAME s_scm_fdes_to_ports
  240. {
  241. SCM result = SCM_EOL;
  242. int int_fd;
  243. long i;
  244. int_fd = scm_to_int (fd);
  245. scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
  246. for (i = 0; i < scm_i_port_table_size; i++)
  247. {
  248. if (SCM_OPFPORTP (scm_i_port_table[i]->port)
  249. && ((scm_t_fport *) scm_i_port_table[i]->stream)->fdes == int_fd)
  250. result = scm_cons (scm_i_port_table[i]->port, result);
  251. }
  252. scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
  253. return result;
  254. }
  255. #undef FUNC_NAME
  256. void
  257. scm_init_ioext ()
  258. {
  259. scm_add_feature ("i/o-extensions");
  260. #include "libguile/ioext.x"
  261. }
  262. /*
  263. Local Variables:
  264. c-file-style: "gnu"
  265. End:
  266. */