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