some updates on gh_ and also incorporated Jim Blandy's essay in the ref manual
[bpt/guile.git] / libguile / ioext.c
CommitLineData
0f2d19dd
JB
1/* Copyright (C) 1995 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program 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
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
19 *
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
25 *
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
28 *
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
36 *
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice.
40 */
41\f
42
43
44#include <stdio.h>
0f2d19dd
JB
45#include "fd.h"
46#include "_scm.h"
20e6290e
JB
47#include "fports.h"
48
49#include "ioext.h"
0f2d19dd 50
95b88819
GH
51#ifdef HAVE_STRING_H
52#include <string.h>
53#endif
54#ifdef HAVE_UNISTD_H
55#include <unistd.h>
56#endif
0f2d19dd
JB
57\f
58
02b754d3 59SCM_PROC (s_sys_ftell, "ftell", 1, 0, 0, scm_sys_ftell);
1cc91f1b 60
0f2d19dd
JB
61SCM
62scm_sys_ftell (port)
63 SCM port;
0f2d19dd
JB
64{
65 long pos;
66 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_ftell);
67 SCM_SYSCALL (pos = ftell ((FILE *)SCM_STREAM (port)));
68 if (pos < 0)
52859adf 69 scm_syserror (s_sys_ftell);
0f2d19dd
JB
70 if (pos > 0 && SCM_CRDYP (port))
71 pos--;
8588fa12 72 return scm_long2num (pos);
0f2d19dd
JB
73}
74
75
76
02b754d3 77SCM_PROC (s_sys_fseek, "fseek", 3, 0, 0, scm_sys_fseek);
1cc91f1b 78
0f2d19dd
JB
79SCM
80scm_sys_fseek (port, offset, whence)
81 SCM port;
82 SCM offset;
83 SCM whence;
0f2d19dd
JB
84{
85 int rv;
8588fa12
GH
86 long loff;
87
0f2d19dd 88 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_fseek);
8588fa12 89 loff = scm_num2long (offset, (char *)SCM_ARG2, s_sys_fseek);
0f2d19dd
JB
90 SCM_ASSERT (SCM_INUMP (whence) && (SCM_INUM (whence) < 3) && (SCM_INUM (whence) >= 0),
91 whence, SCM_ARG3, s_sys_fseek);
8588fa12 92
0f2d19dd
JB
93 SCM_CLRDY (port); /* Clear ungetted char */
94 /* Values of whence are interned in scm_init_ioext. */
8588fa12 95 rv = fseek ((FILE *)SCM_STREAM (port), loff, SCM_INUM (whence));
02b754d3 96 if (rv != 0)
52859adf 97 scm_syserror (s_sys_fseek);
02b754d3 98 return SCM_UNSPECIFIED;
0f2d19dd
JB
99}
100
101
102
02b754d3 103SCM_PROC (s_sys_freopen, "freopen", 3, 0, 0, scm_sys_freopen);
1cc91f1b 104
0f2d19dd
JB
105SCM
106scm_sys_freopen (filename, modes, port)
107 SCM filename;
108 SCM modes;
109 SCM port;
0f2d19dd
JB
110{
111 FILE *f;
112 SCM_ASSERT (SCM_NIMP (filename) && SCM_STRINGP (filename), filename, SCM_ARG1, s_sys_freopen);
113 SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_freopen);
114 SCM_DEFER_INTS;
115 SCM_ASSERT (SCM_NIMP (port) && SCM_FPORTP (port), port, SCM_ARG3, s_sys_freopen);
116 SCM_SYSCALL (f = freopen (SCM_CHARS (filename), SCM_CHARS (modes), (FILE *)SCM_STREAM (port)));
117 if (!f)
118 {
119 SCM p;
120 p = port;
121 port = SCM_MAKINUM (errno);
898a256f 122 SCM_SETAND_CAR (p, ~SCM_OPN);
0f2d19dd
JB
123 scm_remove_from_port_table (p);
124 }
125 else
126 {
898a256f 127 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes)));
0f2d19dd 128 SCM_SETSTREAM (port, (SCM)f);
898a256f
MD
129 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes)));
130 if (SCM_BUF0 & SCM_CAR (port))
0f2d19dd
JB
131 scm_setbuf0 (port);
132 }
133 SCM_ALLOW_INTS;
134 return port;
135}
136
137
138
02b754d3 139SCM_PROC (s_sys_duplicate_port, "duplicate-port", 2, 0, 0, scm_sys_duplicate_port);
1cc91f1b 140
0f2d19dd
JB
141SCM
142scm_sys_duplicate_port (oldpt, modes)
143 SCM oldpt;
144 SCM modes;
0f2d19dd
JB
145{
146 int oldfd;
147 int newfd;
148 FILE *f;
149 SCM newpt;
150 SCM_ASSERT (SCM_NIMP (oldpt) && SCM_OPPORTP (oldpt), oldpt, SCM_ARG1, s_sys_duplicate_port);
151 SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_duplicate_port);
152 SCM_NEWCELL (newpt);
153 SCM_DEFER_INTS;
154 oldfd = fileno ((FILE *)SCM_STREAM (oldpt));
155 if (oldfd == -1)
52859adf 156 scm_syserror (s_sys_duplicate_port);
0f2d19dd
JB
157 SCM_SYSCALL (newfd = dup (oldfd));
158 if (newfd == -1)
52859adf 159 scm_syserror (s_sys_duplicate_port);
0f2d19dd
JB
160 f = fdopen (newfd, SCM_CHARS (modes));
161 if (!f)
162 {
163 SCM_SYSCALL (close (newfd));
52859adf 164 scm_syserror (s_sys_duplicate_port);
0f2d19dd
JB
165 }
166 {
167 struct scm_port_table * pt;
168 pt = scm_add_to_port_table (newpt);
169 SCM_SETPTAB_ENTRY (newpt, pt);
898a256f
MD
170 SCM_SETCAR (newpt, scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes)));
171 if (SCM_BUF0 & SCM_CAR (newpt))
0f2d19dd
JB
172 scm_setbuf0 (newpt);
173 SCM_SETSTREAM (newpt, (SCM)f);
ebf7394e 174 SCM_PTAB_ENTRY (newpt)->file_name = SCM_PTAB_ENTRY (oldpt)->file_name;
0f2d19dd
JB
175 }
176 SCM_ALLOW_INTS;
177 return newpt;
178}
179
180
181
02b754d3 182SCM_PROC (s_sys_redirect_port, "redirect-port", 2, 0, 0, scm_sys_redirect_port);
1cc91f1b 183
0f2d19dd
JB
184SCM
185scm_sys_redirect_port (into_pt, from_pt)
186 SCM into_pt;
187 SCM from_pt;
0f2d19dd
JB
188{
189 int ans, oldfd, newfd;
190 SCM_DEFER_INTS;
191 SCM_ASSERT (SCM_NIMP (into_pt) && SCM_OPPORTP (into_pt), into_pt, SCM_ARG1, s_sys_redirect_port);
192 SCM_ASSERT (SCM_NIMP (from_pt) && SCM_OPPORTP (from_pt), from_pt, SCM_ARG2, s_sys_redirect_port);
193 oldfd = fileno ((FILE *)SCM_STREAM (into_pt));
02b754d3 194 if (oldfd == -1)
52859adf 195 scm_syserror (s_sys_redirect_port);
0f2d19dd 196 newfd = fileno ((FILE *)SCM_STREAM (from_pt));
02b754d3 197 if (newfd == -1)
52859adf 198 scm_syserror (s_sys_redirect_port);
02b754d3
GH
199 SCM_SYSCALL (ans = dup2 (oldfd, newfd));
200 if (ans == -1)
52859adf 201 scm_syserror (s_sys_redirect_port);
0f2d19dd 202 SCM_ALLOW_INTS;
02b754d3 203 return SCM_UNSPECIFIED;
0f2d19dd
JB
204}
205
8b13c6b3 206SCM_PROC (s_sys_fileno, "fileno", 1, 0, 0, scm_sys_fileno);
1cc91f1b 207
0f2d19dd
JB
208SCM
209scm_sys_fileno (port)
210 SCM port;
0f2d19dd
JB
211{
212 int fd;
213 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_fileno);
214 fd = fileno ((FILE *)SCM_STREAM (port));
02b754d3 215 if (fd == -1)
52859adf 216 scm_syserror (s_sys_fileno);
02b754d3 217 return SCM_MAKINUM (fd);
0f2d19dd
JB
218}
219
02b754d3 220SCM_PROC (s_sys_isatty, "isatty?", 1, 0, 0, scm_sys_isatty_p);
1cc91f1b 221
0f2d19dd
JB
222SCM
223scm_sys_isatty_p (port)
224 SCM port;
0f2d19dd
JB
225{
226 int rv;
227 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_isatty);
228 rv = fileno ((FILE *)SCM_STREAM (port));
229 if (rv == -1)
52859adf 230 scm_syserror (s_sys_isatty);
02b754d3
GH
231 rv = isatty (rv);
232 return rv ? SCM_BOOL_T : SCM_BOOL_F;
0f2d19dd
JB
233}
234
235
236
02b754d3 237SCM_PROC (s_sys_fdopen, "fdopen", 2, 0, 0, scm_sys_fdopen);
1cc91f1b 238
0f2d19dd
JB
239SCM
240scm_sys_fdopen (fdes, modes)
241 SCM fdes;
242 SCM modes;
0f2d19dd
JB
243{
244 FILE *f;
245 SCM port;
8b13c6b3 246 struct scm_port_table * pt;
0f2d19dd
JB
247
248 SCM_ASSERT (SCM_INUMP (fdes), fdes, SCM_ARG1, s_sys_fdopen);
249 SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_fdopen);
8b13c6b3 250 SCM_NEWCELL (port);
0f2d19dd
JB
251 SCM_DEFER_INTS;
252 f = fdopen (SCM_INUM (fdes), SCM_CHARS (modes));
253 if (f == NULL)
52859adf 254 scm_syserror (s_sys_fdopen);
8b13c6b3
GH
255 pt = scm_add_to_port_table (port);
256 SCM_SETPTAB_ENTRY (port, pt);
898a256f
MD
257 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes)));
258 if (SCM_BUF0 & SCM_CAR (port))
8b13c6b3
GH
259 scm_setbuf0 (port);
260 SCM_SETSTREAM (port, (SCM)f);
0f2d19dd
JB
261 SCM_ALLOW_INTS;
262 return port;
263}
264
265
266
267/* Move a port's underlying file descriptor to a given value.
8b13c6b3
GH
268 * Returns #f if fdes is already the given value.
269 * #t if fdes moved.
0f2d19dd
JB
270 * MOVE->FDES is implemented in Scheme and calls this primitive.
271 */
02b754d3 272SCM_PROC (s_sys_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0, scm_sys_primitive_move_to_fdes);
1cc91f1b 273
0f2d19dd
JB
274SCM
275scm_sys_primitive_move_to_fdes (port, fd)
276 SCM port;
277 SCM fd;
0f2d19dd
JB
278{
279 FILE *stream;
280 int old_fd;
281 int new_fd;
282 int rv;
283
284 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_primitive_move_to_fdes);
285 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG2, s_sys_primitive_move_to_fdes);
286 SCM_DEFER_INTS;
287 stream = (FILE *)SCM_STREAM (port);
288 old_fd = fileno (stream);
289 new_fd = SCM_INUM (fd);
290 if (old_fd == new_fd)
291 {
292 SCM_ALLOW_INTS;
8b13c6b3 293 return SCM_BOOL_F;
0f2d19dd
JB
294 }
295 scm_evict_ports (new_fd);
296 rv = dup2 (old_fd, new_fd);
297 if (rv == -1)
52859adf 298 scm_syserror (s_sys_primitive_move_to_fdes);
0f2d19dd
JB
299 scm_setfileno (stream, new_fd);
300 SCM_SYSCALL (close (old_fd));
301 SCM_ALLOW_INTS;
8b13c6b3 302 return SCM_BOOL_T;
0f2d19dd
JB
303}
304
1cc91f1b 305
0f2d19dd
JB
306void
307scm_setfileno (fs, fd)
308 FILE *fs;
309 int fd;
0f2d19dd
JB
310{
311#ifdef SET_FILE_FD_FIELD
312 SET_FILE_FD_FIELD(fs, fd);
313#else
314 Configure could not guess the name of the correct field in a FILE *.
315
316 This function needs to be ported to your system.
317
318 SET_FILE_FD_FIELD should change the descriptor refered to by a stdio
319 stream, and nothing else.
320
321 The way to port this file is to add cases to configure.in. Search
322 that file for "SET_FILE_FD_FIELD" and follow the examples there.
323#endif
324}
325
326/* Move ports with the specified file descriptor to new descriptors,
327 * reseting the revealed count to 0.
328 * Should be called with SCM_DEFER_INTS active.
329 */
1cc91f1b 330
0f2d19dd
JB
331void
332scm_evict_ports (fd)
333 int fd;
0f2d19dd
JB
334{
335 int i;
336
337 for (i = 0; i < scm_port_table_size; i++)
338 {
339 if (SCM_FPORTP (scm_port_table[i]->port)
340 && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == fd)
341 {
342 scm_setfileno ((FILE *)SCM_STREAM (scm_port_table[i]->port), dup (fd));
343 scm_set_port_revealed_x (scm_port_table[i]->port, SCM_MAKINUM (0));
344 }
345 }
346}
347
348/* Return a list of ports using a given file descriptor. */
349SCM_PROC(s_fdes_to_ports, "fdes->ports", 1, 0, 0, scm_fdes_to_ports);
1cc91f1b 350
0f2d19dd
JB
351SCM
352scm_fdes_to_ports (fd)
353 SCM fd;
0f2d19dd
JB
354{
355 SCM result = SCM_EOL;
356 int int_fd;
357 int i;
358
359 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG1, s_fdes_to_ports);
360 int_fd = SCM_INUM (fd);
361
362 SCM_DEFER_INTS;
363 for (i = 0; i < scm_port_table_size; i++)
364 {
365 if (SCM_FPORTP (scm_port_table[i]->port)
366 && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == int_fd)
367 result = scm_cons (scm_port_table[i]->port, result);
368 }
369 SCM_ALLOW_INTS;
370 return result;
371}
372
1cc91f1b 373
0f2d19dd
JB
374void
375scm_init_ioext ()
0f2d19dd
JB
376{
377 /* fseek() symbols. */
378 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
379 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
380 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
381
0f2d19dd
JB
382 /* File type/permission bits. */
383#ifdef S_IRUSR
384 scm_sysintern ("S_IRUSR", SCM_MAKINUM (S_IRUSR));
385#endif
386#ifdef S_IWUSR
387 scm_sysintern ("S_IWUSR", SCM_MAKINUM (S_IWUSR));
388#endif
389#ifdef S_IXUSR
390 scm_sysintern ("S_IXUSR", SCM_MAKINUM (S_IXUSR));
391#endif
392#ifdef S_IRWXU
393 scm_sysintern ("S_IRWXU", SCM_MAKINUM (S_IRWXU));
394#endif
395
396#ifdef S_IRGRP
397 scm_sysintern ("S_IRGRP", SCM_MAKINUM (S_IRGRP));
398#endif
399#ifdef S_IWGRP
400 scm_sysintern ("S_IWGRP", SCM_MAKINUM (S_IWGRP));
401#endif
402#ifdef S_IXGRP
403 scm_sysintern ("S_IXGRP", SCM_MAKINUM (S_IXGRP));
404#endif
405#ifdef S_IRWXG
406 scm_sysintern ("S_IRWXG", SCM_MAKINUM (S_IRWXG));
407#endif
408
409#ifdef S_IROTH
410 scm_sysintern ("S_IROTH", SCM_MAKINUM (S_IROTH));
411#endif
412#ifdef S_IWOTH
413 scm_sysintern ("S_IWOTH", SCM_MAKINUM (S_IWOTH));
414#endif
415#ifdef S_IXOTH
416 scm_sysintern ("S_IXOTH", SCM_MAKINUM (S_IXOTH));
417#endif
418#ifdef S_IRWXO
419 scm_sysintern ("S_IRWXO", SCM_MAKINUM (S_IRWXO));
420#endif
421
422#ifdef S_ISUID
423 scm_sysintern ("S_ISUID", SCM_MAKINUM (S_ISUID));
424#endif
425#ifdef S_ISGID
426 scm_sysintern ("S_ISGID", SCM_MAKINUM (S_ISGID));
427#endif
428#ifdef S_ISVTX
429 scm_sysintern ("S_ISVTX", SCM_MAKINUM (S_ISVTX));
430#endif
431
432#ifdef S_IFMT
433 scm_sysintern ("S_IFMT", SCM_MAKINUM (S_IFMT));
434#endif
435#ifdef S_IFDIR
436 scm_sysintern ("S_IFDIR", SCM_MAKINUM (S_IFDIR));
437#endif
438#ifdef S_IFCHR
439 scm_sysintern ("S_IFCHR", SCM_MAKINUM (S_IFCHR));
440#endif
441#ifdef S_IFBLK
442 scm_sysintern ("S_IFBLK", SCM_MAKINUM (S_IFBLK));
443#endif
444#ifdef S_IFREG
445 scm_sysintern ("S_IFREG", SCM_MAKINUM (S_IFREG));
446#endif
447#ifdef S_IFLNK
448 scm_sysintern ("S_IFLNK", SCM_MAKINUM (S_IFLNK));
449#endif
450#ifdef S_IFSOCK
451 scm_sysintern ("S_IFSOCK", SCM_MAKINUM (S_IFSOCK));
452#endif
453#ifdef S_IFIFO
454 scm_sysintern ("S_IFIFO", SCM_MAKINUM (S_IFIFO));
455#endif
456#include "ioext.x"
457}
458