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