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