* __scm.h, alist.c, alist.h, append.c, append.h, appinit.c,
[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);
0f2d19dd
JB
60#ifdef __STDC__
61SCM
62scm_sys_ftell (SCM port)
63#else
64SCM
65scm_sys_ftell (port)
66 SCM port;
67#endif
68{
69 long pos;
70 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_ftell);
71 SCM_SYSCALL (pos = ftell ((FILE *)SCM_STREAM (port)));
72 if (pos < 0)
52859adf 73 scm_syserror (s_sys_ftell);
0f2d19dd
JB
74 if (pos > 0 && SCM_CRDYP (port))
75 pos--;
76 return SCM_MAKINUM (pos);
77}
78
79
80
02b754d3 81SCM_PROC (s_sys_fseek, "fseek", 3, 0, 0, scm_sys_fseek);
0f2d19dd
JB
82#ifdef __STDC__
83SCM
84scm_sys_fseek (SCM port, SCM offset, SCM whence)
85#else
86SCM
87scm_sys_fseek (port, offset, whence)
88 SCM port;
89 SCM offset;
90 SCM whence;
91#endif
92{
93 int rv;
94 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_fseek);
95 SCM_ASSERT (SCM_INUMP (offset), offset, SCM_ARG2, s_sys_fseek);
96 SCM_ASSERT (SCM_INUMP (whence) && (SCM_INUM (whence) < 3) && (SCM_INUM (whence) >= 0),
97 whence, SCM_ARG3, s_sys_fseek);
98 SCM_CLRDY (port); /* Clear ungetted char */
99 /* Values of whence are interned in scm_init_ioext. */
100 rv = fseek ((FILE *)SCM_STREAM (port), SCM_INUM (offset), SCM_INUM (whence));
02b754d3 101 if (rv != 0)
52859adf 102 scm_syserror (s_sys_fseek);
02b754d3 103 return SCM_UNSPECIFIED;
0f2d19dd
JB
104}
105
106
107
02b754d3 108SCM_PROC (s_sys_freopen, "freopen", 3, 0, 0, scm_sys_freopen);
0f2d19dd
JB
109#ifdef __STDC__
110SCM
111scm_sys_freopen (SCM filename, SCM modes, SCM port)
112#else
113SCM
114scm_sys_freopen (filename, modes, port)
115 SCM filename;
116 SCM modes;
117 SCM port;
118#endif
119{
120 FILE *f;
121 SCM_ASSERT (SCM_NIMP (filename) && SCM_STRINGP (filename), filename, SCM_ARG1, s_sys_freopen);
122 SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_freopen);
123 SCM_DEFER_INTS;
124 SCM_ASSERT (SCM_NIMP (port) && SCM_FPORTP (port), port, SCM_ARG3, s_sys_freopen);
125 SCM_SYSCALL (f = freopen (SCM_CHARS (filename), SCM_CHARS (modes), (FILE *)SCM_STREAM (port)));
126 if (!f)
127 {
128 SCM p;
129 p = port;
130 port = SCM_MAKINUM (errno);
131 SCM_CAR (p) &= ~SCM_OPN;
132 scm_remove_from_port_table (p);
133 }
134 else
135 {
136 SCM_CAR (port) = scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes));
137 SCM_SETSTREAM (port, (SCM)f);
138 if (SCM_BUF0 & (SCM_CAR (port) = scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes))))
139 scm_setbuf0 (port);
140 }
141 SCM_ALLOW_INTS;
142 return port;
143}
144
145
146
02b754d3 147SCM_PROC (s_sys_duplicate_port, "duplicate-port", 2, 0, 0, scm_sys_duplicate_port);
0f2d19dd
JB
148#ifdef __STDC__
149SCM
150scm_sys_duplicate_port (SCM oldpt, SCM modes)
151#else
152SCM
153scm_sys_duplicate_port (oldpt, modes)
154 SCM oldpt;
155 SCM modes;
156#endif
157{
158 int oldfd;
159 int newfd;
160 FILE *f;
161 SCM newpt;
162 SCM_ASSERT (SCM_NIMP (oldpt) && SCM_OPPORTP (oldpt), oldpt, SCM_ARG1, s_sys_duplicate_port);
163 SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_duplicate_port);
164 SCM_NEWCELL (newpt);
165 SCM_DEFER_INTS;
166 oldfd = fileno ((FILE *)SCM_STREAM (oldpt));
167 if (oldfd == -1)
52859adf 168 scm_syserror (s_sys_duplicate_port);
0f2d19dd
JB
169 SCM_SYSCALL (newfd = dup (oldfd));
170 if (newfd == -1)
52859adf 171 scm_syserror (s_sys_duplicate_port);
0f2d19dd
JB
172 f = fdopen (newfd, SCM_CHARS (modes));
173 if (!f)
174 {
175 SCM_SYSCALL (close (newfd));
52859adf 176 scm_syserror (s_sys_duplicate_port);
0f2d19dd
JB
177 }
178 {
179 struct scm_port_table * pt;
180 pt = scm_add_to_port_table (newpt);
181 SCM_SETPTAB_ENTRY (newpt, pt);
182 if (SCM_BUF0 & (SCM_CAR (newpt) = scm_tc16_fport | scm_mode_bits (SCM_CHARS (modes))))
183 scm_setbuf0 (newpt);
184 SCM_SETSTREAM (newpt, (SCM)f);
ebf7394e 185 SCM_PTAB_ENTRY (newpt)->file_name = SCM_PTAB_ENTRY (oldpt)->file_name;
0f2d19dd
JB
186 }
187 SCM_ALLOW_INTS;
188 return newpt;
189}
190
191
192
02b754d3 193SCM_PROC (s_sys_redirect_port, "redirect-port", 2, 0, 0, scm_sys_redirect_port);
0f2d19dd
JB
194#ifdef __STDC__
195SCM
196scm_sys_redirect_port (SCM into_pt, SCM from_pt)
197#else
198SCM
199scm_sys_redirect_port (into_pt, from_pt)
200 SCM into_pt;
201 SCM from_pt;
202#endif
203{
204 int ans, oldfd, newfd;
205 SCM_DEFER_INTS;
206 SCM_ASSERT (SCM_NIMP (into_pt) && SCM_OPPORTP (into_pt), into_pt, SCM_ARG1, s_sys_redirect_port);
207 SCM_ASSERT (SCM_NIMP (from_pt) && SCM_OPPORTP (from_pt), from_pt, SCM_ARG2, s_sys_redirect_port);
208 oldfd = fileno ((FILE *)SCM_STREAM (into_pt));
02b754d3 209 if (oldfd == -1)
52859adf 210 scm_syserror (s_sys_redirect_port);
0f2d19dd 211 newfd = fileno ((FILE *)SCM_STREAM (from_pt));
02b754d3 212 if (newfd == -1)
52859adf 213 scm_syserror (s_sys_redirect_port);
02b754d3
GH
214 SCM_SYSCALL (ans = dup2 (oldfd, newfd));
215 if (ans == -1)
52859adf 216 scm_syserror (s_sys_redirect_port);
0f2d19dd 217 SCM_ALLOW_INTS;
02b754d3 218 return SCM_UNSPECIFIED;
0f2d19dd
JB
219}
220
8b13c6b3 221SCM_PROC (s_sys_fileno, "fileno", 1, 0, 0, scm_sys_fileno);
0f2d19dd
JB
222#ifdef __STDC__
223SCM
224scm_sys_fileno (SCM port)
225#else
226SCM
227scm_sys_fileno (port)
228 SCM port;
229#endif
230{
231 int fd;
232 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_fileno);
233 fd = fileno ((FILE *)SCM_STREAM (port));
02b754d3 234 if (fd == -1)
52859adf 235 scm_syserror (s_sys_fileno);
02b754d3 236 return SCM_MAKINUM (fd);
0f2d19dd
JB
237}
238
02b754d3 239SCM_PROC (s_sys_isatty, "isatty?", 1, 0, 0, scm_sys_isatty_p);
0f2d19dd
JB
240#ifdef __STDC__
241SCM
242scm_sys_isatty_p (SCM port)
243#else
244SCM
245scm_sys_isatty_p (port)
246 SCM port;
247#endif
248{
249 int rv;
250 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_isatty);
251 rv = fileno ((FILE *)SCM_STREAM (port));
252 if (rv == -1)
52859adf 253 scm_syserror (s_sys_isatty);
02b754d3
GH
254 rv = isatty (rv);
255 return rv ? SCM_BOOL_T : SCM_BOOL_F;
0f2d19dd
JB
256}
257
258
259
02b754d3 260SCM_PROC (s_sys_fdopen, "fdopen", 2, 0, 0, scm_sys_fdopen);
0f2d19dd
JB
261#ifdef __STDC__
262SCM
263scm_sys_fdopen (SCM fdes, SCM modes)
264#else
265SCM
266scm_sys_fdopen (fdes, modes)
267 SCM fdes;
268 SCM modes;
269#endif
270{
271 FILE *f;
272 SCM port;
8b13c6b3 273 struct scm_port_table * pt;
0f2d19dd
JB
274
275 SCM_ASSERT (SCM_INUMP (fdes), fdes, SCM_ARG1, s_sys_fdopen);
276 SCM_ASSERT (SCM_NIMP (modes) && SCM_STRINGP (modes), modes, SCM_ARG2, s_sys_fdopen);
8b13c6b3 277 SCM_NEWCELL (port);
0f2d19dd
JB
278 SCM_DEFER_INTS;
279 f = fdopen (SCM_INUM (fdes), SCM_CHARS (modes));
280 if (f == NULL)
52859adf 281 scm_syserror (s_sys_fdopen);
8b13c6b3
GH
282 pt = scm_add_to_port_table (port);
283 SCM_SETPTAB_ENTRY (port, pt);
284 if (SCM_BUF0 & (SCM_CAR (port) = scm_tc16_fport
285 | scm_mode_bits (SCM_CHARS (modes))))
286 scm_setbuf0 (port);
287 SCM_SETSTREAM (port, (SCM)f);
0f2d19dd
JB
288 SCM_ALLOW_INTS;
289 return port;
290}
291
292
293
294/* Move a port's underlying file descriptor to a given value.
8b13c6b3
GH
295 * Returns #f if fdes is already the given value.
296 * #t if fdes moved.
0f2d19dd
JB
297 * MOVE->FDES is implemented in Scheme and calls this primitive.
298 */
02b754d3 299SCM_PROC (s_sys_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0, scm_sys_primitive_move_to_fdes);
0f2d19dd
JB
300#ifdef __STDC__
301SCM
302scm_sys_primitive_move_to_fdes (SCM port, SCM fd)
303#else
304SCM
305scm_sys_primitive_move_to_fdes (port, fd)
306 SCM port;
307 SCM fd;
308#endif
309{
310 FILE *stream;
311 int old_fd;
312 int new_fd;
313 int rv;
314
315 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_sys_primitive_move_to_fdes);
316 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG2, s_sys_primitive_move_to_fdes);
317 SCM_DEFER_INTS;
318 stream = (FILE *)SCM_STREAM (port);
319 old_fd = fileno (stream);
320 new_fd = SCM_INUM (fd);
321 if (old_fd == new_fd)
322 {
323 SCM_ALLOW_INTS;
8b13c6b3 324 return SCM_BOOL_F;
0f2d19dd
JB
325 }
326 scm_evict_ports (new_fd);
327 rv = dup2 (old_fd, new_fd);
328 if (rv == -1)
52859adf 329 scm_syserror (s_sys_primitive_move_to_fdes);
0f2d19dd
JB
330 scm_setfileno (stream, new_fd);
331 SCM_SYSCALL (close (old_fd));
332 SCM_ALLOW_INTS;
8b13c6b3 333 return SCM_BOOL_T;
0f2d19dd
JB
334}
335
0f2d19dd
JB
336#ifdef __STDC__
337void
338scm_setfileno (FILE *fs, int fd)
339#else
340void
341scm_setfileno (fs, fd)
342 FILE *fs;
343 int fd;
344#endif
345{
346#ifdef SET_FILE_FD_FIELD
347 SET_FILE_FD_FIELD(fs, fd);
348#else
349 Configure could not guess the name of the correct field in a FILE *.
350
351 This function needs to be ported to your system.
352
353 SET_FILE_FD_FIELD should change the descriptor refered to by a stdio
354 stream, and nothing else.
355
356 The way to port this file is to add cases to configure.in. Search
357 that file for "SET_FILE_FD_FIELD" and follow the examples there.
358#endif
359}
360
361/* Move ports with the specified file descriptor to new descriptors,
362 * reseting the revealed count to 0.
363 * Should be called with SCM_DEFER_INTS active.
364 */
365#ifdef __STDC__
366void
367scm_evict_ports (int fd)
368#else
369void
370scm_evict_ports (fd)
371 int fd;
372#endif
373{
374 int i;
375
376 for (i = 0; i < scm_port_table_size; i++)
377 {
378 if (SCM_FPORTP (scm_port_table[i]->port)
379 && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == fd)
380 {
381 scm_setfileno ((FILE *)SCM_STREAM (scm_port_table[i]->port), dup (fd));
382 scm_set_port_revealed_x (scm_port_table[i]->port, SCM_MAKINUM (0));
383 }
384 }
385}
386
387/* Return a list of ports using a given file descriptor. */
388SCM_PROC(s_fdes_to_ports, "fdes->ports", 1, 0, 0, scm_fdes_to_ports);
389#ifdef __STDC__
390SCM
391scm_fdes_to_ports (SCM fd)
392#else
393SCM
394scm_fdes_to_ports (fd)
395 SCM fd;
396#endif
397{
398 SCM result = SCM_EOL;
399 int int_fd;
400 int i;
401
402 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG1, s_fdes_to_ports);
403 int_fd = SCM_INUM (fd);
404
405 SCM_DEFER_INTS;
406 for (i = 0; i < scm_port_table_size; i++)
407 {
408 if (SCM_FPORTP (scm_port_table[i]->port)
409 && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == int_fd)
410 result = scm_cons (scm_port_table[i]->port, result);
411 }
412 SCM_ALLOW_INTS;
413 return result;
414}
415
416#ifdef __STDC__
417void
418scm_init_ioext (void)
419#else
420void
421scm_init_ioext ()
422#endif
423{
424 /* fseek() symbols. */
425 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
426 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
427 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
428
0f2d19dd
JB
429 /* File type/permission bits. */
430#ifdef S_IRUSR
431 scm_sysintern ("S_IRUSR", SCM_MAKINUM (S_IRUSR));
432#endif
433#ifdef S_IWUSR
434 scm_sysintern ("S_IWUSR", SCM_MAKINUM (S_IWUSR));
435#endif
436#ifdef S_IXUSR
437 scm_sysintern ("S_IXUSR", SCM_MAKINUM (S_IXUSR));
438#endif
439#ifdef S_IRWXU
440 scm_sysintern ("S_IRWXU", SCM_MAKINUM (S_IRWXU));
441#endif
442
443#ifdef S_IRGRP
444 scm_sysintern ("S_IRGRP", SCM_MAKINUM (S_IRGRP));
445#endif
446#ifdef S_IWGRP
447 scm_sysintern ("S_IWGRP", SCM_MAKINUM (S_IWGRP));
448#endif
449#ifdef S_IXGRP
450 scm_sysintern ("S_IXGRP", SCM_MAKINUM (S_IXGRP));
451#endif
452#ifdef S_IRWXG
453 scm_sysintern ("S_IRWXG", SCM_MAKINUM (S_IRWXG));
454#endif
455
456#ifdef S_IROTH
457 scm_sysintern ("S_IROTH", SCM_MAKINUM (S_IROTH));
458#endif
459#ifdef S_IWOTH
460 scm_sysintern ("S_IWOTH", SCM_MAKINUM (S_IWOTH));
461#endif
462#ifdef S_IXOTH
463 scm_sysintern ("S_IXOTH", SCM_MAKINUM (S_IXOTH));
464#endif
465#ifdef S_IRWXO
466 scm_sysintern ("S_IRWXO", SCM_MAKINUM (S_IRWXO));
467#endif
468
469#ifdef S_ISUID
470 scm_sysintern ("S_ISUID", SCM_MAKINUM (S_ISUID));
471#endif
472#ifdef S_ISGID
473 scm_sysintern ("S_ISGID", SCM_MAKINUM (S_ISGID));
474#endif
475#ifdef S_ISVTX
476 scm_sysintern ("S_ISVTX", SCM_MAKINUM (S_ISVTX));
477#endif
478
479#ifdef S_IFMT
480 scm_sysintern ("S_IFMT", SCM_MAKINUM (S_IFMT));
481#endif
482#ifdef S_IFDIR
483 scm_sysintern ("S_IFDIR", SCM_MAKINUM (S_IFDIR));
484#endif
485#ifdef S_IFCHR
486 scm_sysintern ("S_IFCHR", SCM_MAKINUM (S_IFCHR));
487#endif
488#ifdef S_IFBLK
489 scm_sysintern ("S_IFBLK", SCM_MAKINUM (S_IFBLK));
490#endif
491#ifdef S_IFREG
492 scm_sysintern ("S_IFREG", SCM_MAKINUM (S_IFREG));
493#endif
494#ifdef S_IFLNK
495 scm_sysintern ("S_IFLNK", SCM_MAKINUM (S_IFLNK));
496#endif
497#ifdef S_IFSOCK
498 scm_sysintern ("S_IFSOCK", SCM_MAKINUM (S_IFSOCK));
499#endif
500#ifdef S_IFIFO
501 scm_sysintern ("S_IFIFO", SCM_MAKINUM (S_IFIFO));
502#endif
503#include "ioext.x"
504}
505