1 /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
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)
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.
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, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
54 #include "scm_validate.h"
62 #ifdef TIME_WITH_SYS_TIME
63 # include <sys/time.h>
67 # include <sys/time.h>
77 #ifdef LIBC_H_WITH_UNISTD_H
81 #ifdef HAVE_SYS_SELECT_H
82 #include <sys/select.h>
89 #include <sys/types.h>
98 # define NAMLEN(dirent) strlen((dirent)->d_name)
100 # define dirent direct
101 # define NAMLEN(dirent) (dirent)->d_namlen
103 # include <sys/ndir.h>
106 # include <sys/dir.h>
113 /* Ultrix has S_IFSOCK, but no S_ISSOCK. Ipe! */
114 #if defined (S_IFSOCK) && ! defined (S_ISSOCK)
115 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
125 GUILE_PROC (scm_chown
, "chown", 3, 0, 0,
126 (SCM object
, SCM owner
, SCM group
),
127 "Change the ownership and group of the file referred to by @var{obj} to
128 the integer userid values @var{owner} and @var{group}. @var{obj} can be
129 a string containing a file name or a port or integer file descriptor
130 which is open on the file (in which case fchown is used as the underlying
131 system call). The return value
134 If @var{obj} is a symbolic link, either the
135 ownership of the link or the ownership of the referenced file will be
136 changed depending on the operating system (lchown is
137 unsupported at present). If @var{owner} or @var{group} is specified
138 as @code{-1}, then that ID is not changed.")
139 #define FUNC_NAME s_scm_chown
144 object
= SCM_COERCE_OUTPORT (object
);
146 SCM_VALIDATE_INT(2,owner
);
147 SCM_VALIDATE_INT(3,group
);
148 if (SCM_INUMP (object
) || (SCM_OPFPORTP (object
)))
150 if (SCM_INUMP (object
))
151 fdes
= SCM_INUM (object
);
153 fdes
= SCM_FPORT_FDES (object
);
154 SCM_SYSCALL (rv
= fchown (fdes
, SCM_INUM (owner
), SCM_INUM (group
)));
158 SCM_ASSERT (SCM_ROSTRINGP (object
),
159 object
, SCM_ARG1
, FUNC_NAME
);
160 SCM_COERCE_SUBSTR (object
);
161 SCM_SYSCALL (rv
= chown (SCM_ROCHARS (object
),
162 SCM_INUM (owner
), SCM_INUM (group
)));
166 return SCM_UNSPECIFIED
;
171 GUILE_PROC (scm_chmod
, "chmod", 2, 0, 0,
172 (SCM object
, SCM mode
),
173 "Changes the permissions of the file referred to by @var{obj}.
174 @var{obj} can be a string containing a file name or a port or integer file
175 descriptor which is open on a file (in which case @code{fchmod} is used
176 as the underlying system call).
178 the new permissions as a decimal number, e.g., @code{(chmod "foo
" #o755)}.
179 The return value is unspecified.")
180 #define FUNC_NAME s_scm_chmod
185 object
= SCM_COERCE_OUTPORT (object
);
187 SCM_VALIDATE_INT(2,mode
);
188 if (SCM_INUMP (object
) || SCM_OPFPORTP (object
))
190 if (SCM_INUMP (object
))
191 fdes
= SCM_INUM (object
);
193 fdes
= SCM_FPORT_FDES (object
);
194 SCM_SYSCALL (rv
= fchmod (fdes
, SCM_INUM (mode
)));
198 SCM_VALIDATE_ROSTRING(1,object
);
199 SCM_COERCE_SUBSTR (object
);
200 SCM_SYSCALL (rv
= chmod (SCM_ROCHARS (object
), SCM_INUM (mode
)));
204 return SCM_UNSPECIFIED
;
208 GUILE_PROC (scm_umask
, "umask", 0, 1, 0,
210 "If @var{mode} is omitted, retuns a decimal number representing the current
211 file creation mask. Otherwise the file creation mask is set to
212 @var{mode} and the previous value is returned.
214 E.g., @code{(umask #o022)} sets the mask to octal 22, decimal 18.")
215 #define FUNC_NAME s_scm_umask
218 if (SCM_UNBNDP (mode
))
225 SCM_VALIDATE_INT(1,mode
);
226 mask
= umask (SCM_INUM (mode
));
228 return SCM_MAKINUM (mask
);
234 GUILE_PROC (scm_open_fdes
, "open-fdes", 2, 1, 0,
235 (SCM path
, SCM flags
, SCM mode
),
236 "Similar to @code{open} but returns a file descriptor instead of a
238 #define FUNC_NAME s_scm_open_fdes
244 SCM_VALIDATE_ROSTRING(1,path
);
245 SCM_COERCE_SUBSTR (path
);
246 SCM_VALIDATE_INT_COPY(2,flags
,iflags
);
247 SCM_VALIDATE_INT_DEF_COPY(3,mode
,0666,imode
);
248 SCM_SYSCALL (fd
= open (SCM_ROCHARS (path
), iflags
, imode
));
251 return SCM_MAKINUM (fd
);
255 GUILE_PROC (scm_open
, "open", 2, 1, 0,
256 (SCM path
, SCM flags
, SCM mode
),
257 "Open the file named by @var{path} for reading and/or writing.
258 @var{flags} is an integer specifying how the file should be opened.
259 @var{mode} is an integer specifying the permission bits of the file, if
260 it needs to be created, before the umask is applied. The default is 666
261 (Unix itself has no default).
263 @var{flags} can be constructed by combining variables using @code{logior}.
267 Open the file read-only.
270 Open the file write-only.
273 Open the file read/write.
276 Append to the file instead of truncating.
279 Create the file if it does not already exist.
282 See the Unix documentation of the @code{open} system call
283 for additional flags.")
284 #define FUNC_NAME s_scm_open
291 fd
= SCM_INUM (scm_open_fdes (path
, flags
, mode
));
292 SCM_VALIDATE_INT_COPY(2,flags
,iflags
);
295 if (iflags
& O_APPEND
)
297 else if (iflags
& O_CREAT
)
303 if (iflags
& O_APPEND
)
305 else if (iflags
& O_WRONLY
)
310 newpt
= scm_fdes_to_port (fd
, port_mode
, path
);
315 GUILE_PROC (scm_close
, "close", 1, 0, 0,
317 "Similar to close-port (@pxref{Generic Port Operations, close-port}),
318 but also works on file descriptors. A side
319 effect of closing a file descriptor is that any ports using that file
320 descriptor are moved to a different file descriptor and have
321 their revealed counts set to zero.")
322 #define FUNC_NAME s_scm_close
327 fd_or_port
= SCM_COERCE_OUTPORT (fd_or_port
);
329 if (SCM_PORTP (fd_or_port
))
330 return scm_close_port (fd_or_port
);
331 SCM_VALIDATE_INT(1,fd_or_port
);
332 fd
= SCM_INUM (fd_or_port
);
333 scm_evict_ports (fd
); /* see scsh manual. */
334 SCM_SYSCALL (rv
= close (fd
));
335 /* following scsh, closing an already closed file descriptor is
337 if (rv
< 0 && errno
!= EBADF
)
339 return SCM_NEGATE_BOOL(rv
< 0);
347 SCM_SYMBOL (scm_sym_regular
, "regular");
348 SCM_SYMBOL (scm_sym_directory
, "directory");
350 SCM_SYMBOL (scm_sym_symlink
, "symlink");
352 SCM_SYMBOL (scm_sym_block_special
, "block-special");
353 SCM_SYMBOL (scm_sym_char_special
, "char-special");
354 SCM_SYMBOL (scm_sym_fifo
, "fifo");
355 SCM_SYMBOL (scm_sym_sock
, "socket");
356 SCM_SYMBOL (scm_sym_unknown
, "unknown");
359 scm_stat2scm (struct stat
*stat_temp
)
361 SCM ans
= scm_make_vector (SCM_MAKINUM (15), SCM_UNSPECIFIED
);
362 SCM
*ve
= SCM_VELTS (ans
);
364 ve
[0] = scm_ulong2num ((unsigned long) stat_temp
->st_dev
);
365 ve
[1] = scm_ulong2num ((unsigned long) stat_temp
->st_ino
);
366 ve
[2] = scm_ulong2num ((unsigned long) stat_temp
->st_mode
);
367 ve
[3] = scm_ulong2num ((unsigned long) stat_temp
->st_nlink
);
368 ve
[4] = scm_ulong2num ((unsigned long) stat_temp
->st_uid
);
369 ve
[5] = scm_ulong2num ((unsigned long) stat_temp
->st_gid
);
371 ve
[6] = scm_ulong2num ((unsigned long) stat_temp
->st_rdev
);
375 ve
[7] = scm_ulong2num ((unsigned long) stat_temp
->st_size
);
376 ve
[8] = scm_ulong2num ((unsigned long) stat_temp
->st_atime
);
377 ve
[9] = scm_ulong2num ((unsigned long) stat_temp
->st_mtime
);
378 ve
[10] = scm_ulong2num ((unsigned long) stat_temp
->st_ctime
);
379 #ifdef HAVE_ST_BLKSIZE
380 ve
[11] = scm_ulong2num ((unsigned long) stat_temp
->st_blksize
);
382 ve
[11] = scm_ulong2num (4096L);
384 #ifdef HAVE_ST_BLOCKS
385 ve
[12] = scm_ulong2num ((unsigned long) stat_temp
->st_blocks
);
390 int mode
= stat_temp
->st_mode
;
393 ve
[13] = scm_sym_regular
;
394 else if (S_ISDIR (mode
))
395 ve
[13] = scm_sym_directory
;
397 else if (S_ISLNK (mode
))
398 ve
[13] = scm_sym_symlink
;
400 else if (S_ISBLK (mode
))
401 ve
[13] = scm_sym_block_special
;
402 else if (S_ISCHR (mode
))
403 ve
[13] = scm_sym_char_special
;
404 else if (S_ISFIFO (mode
))
405 ve
[13] = scm_sym_fifo
;
406 else if (S_ISSOCK (mode
))
407 ve
[13] = scm_sym_sock
;
409 ve
[13] = scm_sym_unknown
;
411 ve
[14] = SCM_MAKINUM ((~S_IFMT
) & mode
);
413 /* the layout of the bits in ve[14] is intended to be portable.
414 If there are systems that don't follow the usual convention,
415 the following could be used:
418 if (S_ISUID & mode) tmp += 1;
420 if (S_IRGRP & mode) tmp += 1;
422 if (S_ISVTX & mode) tmp += 1;
424 if (S_IRUSR & mode) tmp += 1;
426 if (S_IWUSR & mode) tmp += 1;
428 if (S_IXUSR & mode) tmp += 1;
430 if (S_IWGRP & mode) tmp += 1;
432 if (S_IXGRP & mode) tmp += 1;
434 if (S_IROTH & mode) tmp += 1;
436 if (S_IWOTH & mode) tmp += 1;
438 if (S_IXOTH & mode) tmp += 1;
440 ve[14] = SCM_MAKINUM (tmp);
448 GUILE_PROC (scm_stat
, "stat", 1, 0, 0,
450 "Returns an object containing various information
451 about the file determined by @var{obj}.
452 @var{obj} can be a string containing a file name or a port or integer file
453 descriptor which is open on a file (in which case @code{fstat} is used
454 as the underlying system call).
456 The object returned by @code{stat} can be passed as a single parameter
457 to the following procedures, all of which return integers:
461 The device containing the file.
463 The file serial number, which distinguishes this file from all other
464 files on the same device.
466 The mode of the file. This includes file type information
467 and the file permission bits. See @code{stat:type} and @code{stat:perms}
470 The number of hard links to the file.
472 The user ID of the file's owner.
474 The group ID of the file.
476 Device ID; this entry is defined only for character or block
479 The size of a regular file in bytes.
481 The last access time for the file.
483 The last modification time for the file.
485 The last modification time for the attributes of the file.
487 The optimal block size for reading or writing the file, in bytes.
489 The amount of disk space that the file occupies measured in units of
493 In addition, the following procedures return the information
494 from stat:mode in a more convenient form:
498 A symbol representing the type of file. Possible values are
499 regular, directory, symlink, block-special, char-special,
500 fifo, socket and unknown
502 An integer representing the access permission bits.
504 #define FUNC_NAME s_scm_stat
508 struct stat stat_temp
;
510 if (SCM_INUMP (object
))
511 SCM_SYSCALL (rv
= fstat (SCM_INUM (object
), &stat_temp
));
514 SCM_VALIDATE_NIM (1,object
);
515 if (SCM_ROSTRINGP (object
))
517 SCM_COERCE_SUBSTR (object
);
518 SCM_SYSCALL (rv
= stat (SCM_ROCHARS (object
), &stat_temp
));
522 object
= SCM_COERCE_OUTPORT (object
);
523 SCM_ASSERT (SCM_OPFPORTP (object
), object
, SCM_ARG1
, FUNC_NAME
);
524 fdes
= SCM_FPORT_FDES (object
);
525 SCM_SYSCALL (rv
= fstat (fdes
, &stat_temp
));
532 scm_syserror_msg (FUNC_NAME
, "%s: %S",
533 scm_listify (scm_makfrom0str (strerror (errno
)),
538 return scm_stat2scm (&stat_temp
);
543 /* {Modifying Directories}
546 GUILE_PROC (scm_link
, "link", 2, 0, 0,
547 (SCM oldpath
, SCM newpath
),
548 "Creates a new name @var{path-to} in the file system for the file
549 named by @var{path-from}. If @var{path-from} is a symbolic link, the
550 link may or may not be followed depending on the system.")
551 #define FUNC_NAME s_scm_link
555 SCM_VALIDATE_ROSTRING(1,oldpath
);
556 if (SCM_SUBSTRP (oldpath
))
557 oldpath
= scm_makfromstr (SCM_ROCHARS (oldpath
),
558 SCM_ROLENGTH (oldpath
), 0);
559 SCM_VALIDATE_ROSTRING(2,newpath
);
560 if (SCM_SUBSTRP (newpath
))
561 newpath
= scm_makfromstr (SCM_ROCHARS (newpath
),
562 SCM_ROLENGTH (newpath
), 0);
563 SCM_SYSCALL (val
= link (SCM_ROCHARS (oldpath
), SCM_ROCHARS (newpath
)));
566 return SCM_UNSPECIFIED
;
572 GUILE_PROC (scm_rename
, "rename-file", 2, 0, 0,
573 (SCM oldname
, SCM newname
),
574 "Renames the file specified by @var{path-from} to @var{path-to}.
575 The return value is unspecified.")
576 #define FUNC_NAME s_scm_rename
579 SCM_VALIDATE_ROSTRING(1,oldname
);
580 SCM_VALIDATE_ROSTRING(2,newname
);
581 SCM_COERCE_SUBSTR (oldname
);
582 SCM_COERCE_SUBSTR (newname
);
584 SCM_SYSCALL (rv
= rename (SCM_ROCHARS (oldname
), SCM_ROCHARS (newname
)));
586 SCM_SYSCALL (rv
= link (SCM_ROCHARS (oldname
), SCM_ROCHARS (newname
)));
589 SCM_SYSCALL (rv
= unlink (SCM_ROCHARS (oldname
)));;
591 /* unlink failed. remove new name */
592 SCM_SYSCALL (unlink (SCM_ROCHARS (newname
)));
597 return SCM_UNSPECIFIED
;
602 GUILE_PROC(scm_delete_file
, "delete-file", 1, 0, 0,
604 "Deletes (or \"unlinks\") the file specified by @var{path}.")
605 #define FUNC_NAME s_scm_delete_file
608 SCM_VALIDATE_ROSTRING(1,str
);
609 SCM_COERCE_SUBSTR (str
);
610 SCM_SYSCALL (ans
= unlink (SCM_ROCHARS (str
)));
613 return SCM_UNSPECIFIED
;
617 GUILE_PROC (scm_mkdir
, "mkdir", 1, 1, 0,
618 (SCM path
, SCM mode
),
619 "Create a new directory named by @var{path}. If @var{mode} is omitted
620 then the permissions of the directory file are set using the current
621 umask. Otherwise they are set to the decimal value specified with
622 @var{mode}. The return value is unspecified.")
623 #define FUNC_NAME s_scm_mkdir
628 SCM_VALIDATE_ROSTRING(1,path
);
629 SCM_COERCE_SUBSTR (path
);
630 if (SCM_UNBNDP (mode
))
634 SCM_SYSCALL (rv
= mkdir (SCM_ROCHARS (path
), 0777 ^ mask
));
638 SCM_VALIDATE_INT(2,mode
);
639 SCM_SYSCALL (rv
= mkdir (SCM_ROCHARS (path
), SCM_INUM (mode
)));
643 return SCM_UNSPECIFIED
;
653 GUILE_PROC (scm_rmdir
, "rmdir", 1, 0, 0,
655 "Remove the existing directory named by @var{path}. The directory must
656 be empty for this to succeed. The return value is unspecified.")
657 #define FUNC_NAME s_scm_rmdir
662 SCM_VALIDATE_ROSTRING(1,path
);
663 SCM_COERCE_SUBSTR (path
);
664 SCM_SYSCALL (val
= rmdir (SCM_ROCHARS (path
)));
667 return SCM_UNSPECIFIED
;
677 /* {Examining Directories}
682 GUILE_PROC (scm_directory_stream_p
, "directory-stream?", 1, 0, 0,
684 "Returns a boolean indicating whether @var{object} is a directory stream
685 as returned by @code{opendir}.")
686 #define FUNC_NAME s_scm_directory_stream_p
688 return SCM_BOOL(SCM_DIRP (obj
));
692 GUILE_PROC (scm_opendir
, "opendir", 1, 0, 0,
694 "Open the directory specified by @var{path} and return a directory
696 #define FUNC_NAME s_scm_opendir
699 SCM_VALIDATE_ROSTRING(1,dirname
);
700 SCM_COERCE_SUBSTR (dirname
);
701 SCM_SYSCALL (ds
= opendir (SCM_ROCHARS (dirname
)));
704 SCM_RETURN_NEWSMOB (scm_tc16_dir
| SCM_OPN
, ds
);
709 GUILE_PROC (scm_readdir
, "readdir", 1, 0, 0,
711 "Return (as a string) the next directory entry from the directory stream
712 @var{stream}. If there is no remaining entry to be read then the
713 end of file object is returned.")
714 #define FUNC_NAME s_scm_readdir
716 struct dirent
*rdent
;
717 SCM_VALIDATE_OPDIR(1,port
);
719 SCM_SYSCALL (rdent
= readdir ((DIR *) SCM_CDR (port
)));
722 return (rdent
? scm_makfromstr (rdent
->d_name
, NAMLEN (rdent
), 0)
729 GUILE_PROC (scm_rewinddir
, "rewinddir", 1, 0, 0,
731 "Reset the directory port @var{stream} so that the next call to
732 @code{readdir} will return the first directory entry.")
733 #define FUNC_NAME s_scm_rewinddir
735 SCM_VALIDATE_OPDIR(1,port
);
736 rewinddir ((DIR *) SCM_CDR (port
));
737 return SCM_UNSPECIFIED
;
743 GUILE_PROC (scm_closedir
, "closedir", 1, 0, 0,
745 "Close the directory stream @var{stream}.
746 The return value is unspecified.")
747 #define FUNC_NAME s_scm_closedir
751 SCM_VALIDATE_DIR(1,port
);
752 if (SCM_CLOSEDP (port
))
754 return SCM_UNSPECIFIED
;
756 SCM_SYSCALL (sts
= closedir ((DIR *) SCM_CDR (port
)));
759 SCM_SETCAR (port
, scm_tc16_dir
);
760 return SCM_UNSPECIFIED
;
768 scm_dir_print (SCM exp
, SCM port
, scm_print_state
*pstate
)
770 scm_puts ("#<", port
);
771 if (SCM_CLOSEDP (exp
))
772 scm_puts ("closed: ", port
);
773 scm_puts ("directory stream ", port
);
774 scm_intprint (SCM_CDR (exp
), 16, port
);
775 scm_putc ('>', port
);
784 closedir ((DIR *) SCM_CDR (p
));
789 /* {Navigating Directories}
793 GUILE_PROC (scm_chdir
, "chdir", 1, 0, 0,
795 "Change the current working directory to @var{path}.
796 The return value is unspecified.")
797 #define FUNC_NAME s_scm_chdir
801 SCM_VALIDATE_ROSTRING(1,str
);
802 SCM_COERCE_SUBSTR (str
);
803 SCM_SYSCALL (ans
= chdir (SCM_ROCHARS (str
)));
806 return SCM_UNSPECIFIED
;
812 GUILE_PROC (scm_getcwd
, "getcwd", 0, 0, 0,
814 "Returns the name of the current working directory.")
815 #define FUNC_NAME s_scm_getcwd
820 scm_sizet size
= 100;
824 wd
= scm_must_malloc (size
, FUNC_NAME
);
825 while ((rv
= getcwd (wd
, size
)) == 0 && errno
== ERANGE
)
829 wd
= scm_must_malloc (size
, FUNC_NAME
);
833 result
= scm_makfromstr (wd
, strlen (wd
), 0);
847 set_element (SELECT_TYPE
*set
, SCM element
, int arg
)
850 element
= SCM_COERCE_OUTPORT (element
);
851 if (SCM_OPFPORTP (element
))
852 fd
= SCM_FPORT_FDES (element
);
854 SCM_ASSERT (SCM_INUMP (element
), element
, arg
, "select");
855 fd
= SCM_INUM (element
);
862 fill_select_type (SELECT_TYPE
*set
, SCM list
, int arg
)
865 if (SCM_VECTORP (list
))
867 int len
= SCM_LENGTH (list
);
868 SCM
*ve
= SCM_VELTS (list
);
872 fd
= set_element (set
, ve
[len
- 1], arg
);
880 while (list
!= SCM_EOL
)
882 fd
= set_element (set
, SCM_CAR (list
), arg
);
885 list
= SCM_CDR (list
);
893 get_element (SELECT_TYPE
*set
, SCM element
, SCM list
)
895 element
= SCM_COERCE_OUTPORT (element
);
896 if (SCM_OPFPORTP (element
))
898 if (FD_ISSET (SCM_FPORT_FDES (element
), set
))
899 list
= scm_cons (element
, list
);
901 else if (SCM_INUMP (element
))
903 if (FD_ISSET (SCM_INUM (element
), set
))
904 list
= scm_cons (element
, list
);
910 retrieve_select_type (SELECT_TYPE
*set
, SCM list
)
912 SCM answer_list
= SCM_EOL
;
914 if (SCM_VECTORP (list
))
916 int len
= SCM_LENGTH (list
);
917 SCM
*ve
= SCM_VELTS (list
);
921 answer_list
= get_element (set
, ve
[len
- 1], answer_list
);
924 return scm_vector (answer_list
);
928 /* list is a list. */
929 while (list
!= SCM_EOL
)
931 answer_list
= get_element (set
, SCM_CAR (list
), answer_list
);
932 list
= SCM_CDR (list
);
938 /* Static helper functions above refer to s_scm_select directly as s_select */
939 GUILE_PROC (scm_select
, "select", 3, 2, 0,
940 (SCM reads
, SCM writes
, SCM excepts
, SCM secs
, SCM usecs
),
941 "@var{reads}, @var{writes} and @var{excepts} can be lists or vectors: it
942 doesn't matter which, but the corresponding object returned will be
944 Each element is a port or file descriptor on which to wait for
945 readability, writeability
946 or exceptional conditions respectively. @var{secs} and @var{usecs}
947 optionally specify a timeout: @var{secs} can be specified alone, as
948 either an integer or a real number, or both @var{secs} and @var{usecs}
949 can be specified as integers, in which case @var{usecs} is an additional
950 timeout expressed in microseconds.
952 Buffered input or output data is (currently, but this may change)
953 ignored: select uses the underlying file descriptor of a port
954 (@code{char-ready?} will check input buffers, output buffers are
957 The return value is a list of subsets of the input lists or vectors for
958 which the requested condition has been met.
960 It is not quite compatible with scsh's select: scsh checks port buffers,
961 doesn't accept input lists or a microsecond timeout, returns multiple
962 values instead of a list and has an additional select! interface.
964 #define FUNC_NAME s_scm_select
967 struct timeval timeout
;
968 struct timeval
* time_p
;
969 SELECT_TYPE read_set
;
970 SELECT_TYPE write_set
;
971 SELECT_TYPE except_set
;
975 #define assert_set(x, arg) \
976 SCM_ASSERT (scm_ilength (x) >= 0 || (SCM_VECTORP (x)), \
978 assert_set (reads
, SCM_ARG1
);
979 assert_set (writes
, SCM_ARG2
);
980 assert_set (excepts
, SCM_ARG3
);
984 FD_ZERO (&write_set
);
985 FD_ZERO (&except_set
);
987 max_fd
= fill_select_type (&read_set
, reads
, SCM_ARG1
);
988 fd
= fill_select_type (&write_set
, writes
, SCM_ARG2
);
991 fd
= fill_select_type (&except_set
, excepts
, SCM_ARG3
);
995 if (SCM_UNBNDP (secs
) || SCM_FALSEP (secs
))
999 if (SCM_INUMP (secs
))
1001 timeout
.tv_sec
= SCM_INUM (secs
);
1002 if (SCM_UNBNDP (usecs
))
1003 timeout
.tv_usec
= 0;
1006 SCM_VALIDATE_INT(5,usecs
);
1007 timeout
.tv_usec
= SCM_INUM (usecs
);
1012 double fl
= scm_num2dbl (secs
, FUNC_NAME
);
1014 if (!SCM_UNBNDP (usecs
))
1015 scm_wrong_type_arg (FUNC_NAME
, 4, secs
);
1017 scm_out_of_range (FUNC_NAME
, secs
);
1018 timeout
.tv_sec
= (long) fl
;
1019 timeout
.tv_usec
= (long) ((fl
- timeout
.tv_sec
) * 1000000);
1024 #ifdef GUILE_ISELECT
1025 sreturn
= scm_internal_select (max_fd
+ 1,
1026 &read_set
, &write_set
, &except_set
, time_p
);
1028 sreturn
= select (max_fd
+ 1,
1029 &read_set
, &write_set
, &except_set
, time_p
);
1033 return scm_listify (retrieve_select_type (&read_set
, reads
),
1034 retrieve_select_type (&write_set
, writes
),
1035 retrieve_select_type (&except_set
, excepts
),
1047 GUILE_PROC (scm_fcntl
, "fcntl", 2, 0, 1,
1048 (SCM object
, SCM cmd
, SCM value
),
1049 "Apply @var{command} to the specified file descriptor or the underlying
1050 file descriptor of the specified port. @var{value} is an optional
1053 Values for @var{command} are:
1057 Duplicate a file descriptor
1059 Get flags associated with the file descriptor.
1061 Set flags associated with the file descriptor to @var{value}.
1063 Get flags associated with the open file.
1065 Set flags associated with the open file to @var{value}
1067 Get the process ID of a socket's owner, for @code{SIGIO} signals.
1069 Set the process that owns a socket to @var{value}, for @code{SIGIO} signals.
1071 The value used to indicate the "close on exec
" flag with @code{F_GETFL} or
1074 #define FUNC_NAME s_scm_fcntl
1080 object
= SCM_COERCE_OUTPORT (object
);
1082 SCM_VALIDATE_INT(2,cmd
);
1083 if (SCM_OPFPORTP (object
))
1084 fdes
= SCM_FPORT_FDES (object
);
1087 SCM_VALIDATE_INT(1,object
);
1088 fdes
= SCM_INUM (object
);
1090 if (SCM_NULLP (value
))
1094 SCM_ASSERT (SCM_INUMP (SCM_CAR (value
)), value
, SCM_ARG3
, FUNC_NAME
);
1095 ivalue
= SCM_INUM (SCM_CAR (value
));
1097 SCM_SYSCALL (rv
= fcntl (fdes
, SCM_INUM (cmd
), ivalue
));
1100 return SCM_MAKINUM (rv
);
1104 GUILE_PROC (scm_fsync
, "fsync", 1, 0, 0,
1106 "Copies any unwritten data for the specified output file descriptor to disk.
1107 If @var{port/fd} is a port, its buffer is flushed before the underlying
1108 file descriptor is fsync'd.
1109 The return value is unspecified.")
1110 #define FUNC_NAME s_scm_fsync
1114 object
= SCM_COERCE_OUTPORT (object
);
1116 if (SCM_OPFPORTP (object
))
1119 fdes
= SCM_FPORT_FDES (object
);
1123 SCM_VALIDATE_INT(1,object
);
1124 fdes
= SCM_INUM (object
);
1126 if (fsync (fdes
) == -1)
1128 return SCM_UNSPECIFIED
;
1132 GUILE_PROC (scm_symlink
, "symlink", 2, 0, 0,
1133 (SCM oldpath
, SCM newpath
),
1134 "Create a symbolic link named @var{path-to} with the value (i.e., pointing to)
1135 @var{path-from}. The return value is unspecified.")
1136 #define FUNC_NAME s_scm_symlink
1141 SCM_VALIDATE_ROSTRING(1,oldpath
);
1142 SCM_VALIDATE_ROSTRING(2,newpath
);
1143 SCM_COERCE_SUBSTR (oldpath
);
1144 SCM_COERCE_SUBSTR (newpath
);
1145 SCM_SYSCALL (val
= symlink(SCM_ROCHARS(oldpath
), SCM_ROCHARS(newpath
)));
1148 return SCM_UNSPECIFIED
;
1158 GUILE_PROC (scm_readlink
, "readlink", 1, 0, 0,
1160 "Returns the value of the symbolic link named by
1161 @var{path} (a string), i.e., the
1162 file that the link points to.")
1163 #define FUNC_NAME s_scm_readlink
1165 #ifdef HAVE_READLINK
1170 SCM_VALIDATE_ROSTRING(1,path
);
1171 SCM_COERCE_SUBSTR (path
);
1172 buf
= scm_must_malloc (size
, FUNC_NAME
);
1173 while ((rv
= readlink (SCM_ROCHARS (path
), buf
, size
)) == size
)
1175 scm_must_free (buf
);
1177 buf
= scm_must_malloc (size
, FUNC_NAME
);
1181 result
= scm_makfromstr (buf
, rv
, 0);
1182 scm_must_free (buf
);
1193 GUILE_PROC (scm_lstat
, "lstat", 1, 0, 0,
1195 "Similar to @code{stat}, but does not follow symbolic links, i.e.,
1196 it will return information about a symbolic link itself, not the
1197 file it points to. @var{path} must be a string.")
1198 #define FUNC_NAME s_scm_lstat
1202 struct stat stat_temp
;
1204 SCM_VALIDATE_ROSTRING(1,str
);
1205 SCM_COERCE_SUBSTR (str
);
1206 SCM_SYSCALL(rv
= lstat(SCM_ROCHARS(str
), &stat_temp
));
1211 scm_syserror_msg (FUNC_NAME
, "%s: %S",
1212 scm_listify (scm_makfrom0str (strerror (errno
)),
1217 return scm_stat2scm(&stat_temp
);
1227 GUILE_PROC (scm_copy_file
, "copy-file", 2, 0, 0,
1228 (SCM oldfile
, SCM newfile
),
1229 "Copy the file specified by @var{path-from} to @var{path-to}.
1230 The return value is unspecified.")
1231 #define FUNC_NAME s_scm_copy_file
1236 struct stat oldstat
;
1238 SCM_VALIDATE_ROSTRING(1,oldfile
);
1239 if (SCM_SUBSTRP (oldfile
))
1240 oldfile
= scm_makfromstr (SCM_ROCHARS (oldfile
), SCM_ROLENGTH (oldfile
), 0);
1241 SCM_VALIDATE_ROSTRING(2,newfile
);
1242 if (SCM_SUBSTRP (newfile
))
1243 newfile
= scm_makfromstr (SCM_ROCHARS (newfile
), SCM_ROLENGTH (newfile
), 0);
1244 if (stat (SCM_ROCHARS (oldfile
), &oldstat
) == -1)
1246 oldfd
= open (SCM_ROCHARS (oldfile
), O_RDONLY
);
1250 /* use POSIX flags instead of 07777?. */
1251 newfd
= open (SCM_ROCHARS (newfile
), O_WRONLY
| O_CREAT
| O_TRUNC
,
1252 oldstat
.st_mode
& 07777);
1256 while ((n
= read (oldfd
, buf
, sizeof buf
)) > 0)
1257 if (write (newfd
, buf
, n
) != n
)
1264 if (close (newfd
) == -1)
1266 return SCM_UNSPECIFIED
;
1271 /* Filename manipulation */
1275 GUILE_PROC (scm_dirname
, "dirname", 1, 0, 0,
1278 #define FUNC_NAME s_scm_dirname
1282 SCM_VALIDATE_ROSTRING(1,filename
);
1283 s
= SCM_ROCHARS (filename
);
1284 len
= SCM_LENGTH (filename
);
1286 while (i
>= 0 && s
[i
] == '/') --i
;
1287 while (i
>= 0 && s
[i
] != '/') --i
;
1288 while (i
>= 0 && s
[i
] == '/') --i
;
1291 if (len
> 0 && s
[0] == '/')
1292 return scm_make_shared_substring (filename
, SCM_INUM0
, SCM_MAKINUM (1));
1294 return scm_dot_string
;
1297 return scm_make_shared_substring (filename
, SCM_INUM0
, SCM_MAKINUM (i
+ 1));
1301 GUILE_PROC (scm_basename
, "basename", 1, 1, 0,
1302 (SCM filename
, SCM suffix
),
1304 #define FUNC_NAME s_scm_basename
1308 SCM_VALIDATE_ROSTRING(1,filename
);
1309 SCM_ASSERT (SCM_UNBNDP (suffix
)
1310 || (SCM_ROSTRINGP (suffix
)),
1314 f
= SCM_ROCHARS (filename
);
1315 if (SCM_UNBNDP (suffix
))
1319 s
= SCM_ROCHARS (suffix
);
1320 j
= SCM_LENGTH (suffix
) - 1;
1322 len
= SCM_LENGTH (filename
);
1324 while (i
>= 0 && f
[i
] == '/') --i
;
1326 while (i
>= 0 && j
>= 0 && f
[i
] == s
[j
]) --i
, --j
;
1329 while (i
>= 0 && f
[i
] != '/') --i
;
1332 if (len
> 0 && f
[0] == '/')
1333 return scm_make_shared_substring (filename
, SCM_INUM0
, SCM_MAKINUM (1));
1335 return scm_dot_string
;
1338 return scm_make_shared_substring (filename
,
1339 SCM_MAKINUM (i
+ 1),
1340 SCM_MAKINUM (end
+ 1));
1351 scm_tc16_dir
= scm_make_smob_type_mfpe ("directory", 0,
1352 NULL
, scm_dir_free
,scm_dir_print
, NULL
);
1354 scm_dot_string
= scm_permanent_object (scm_makfrom0str ("."));
1357 scm_sysintern ("O_RDONLY", scm_long2num (O_RDONLY
));
1360 scm_sysintern ("O_WRONLY", scm_long2num (O_WRONLY
));
1363 scm_sysintern ("O_RDWR", scm_long2num (O_RDWR
));
1366 scm_sysintern ("O_CREAT", scm_long2num (O_CREAT
));
1369 scm_sysintern ("O_EXCL", scm_long2num (O_EXCL
));
1372 scm_sysintern ("O_NOCTTY", scm_long2num (O_NOCTTY
));
1375 scm_sysintern ("O_TRUNC", scm_long2num (O_TRUNC
));
1378 scm_sysintern ("O_APPEND", scm_long2num (O_APPEND
));
1381 scm_sysintern ("O_NONBLOCK", scm_long2num (O_NONBLOCK
));
1384 scm_sysintern ("O_NDELAY", scm_long2num (O_NDELAY
));
1387 scm_sysintern ("O_SYNC", scm_long2num (O_SYNC
));
1391 scm_sysintern ("F_DUPFD", scm_long2num (F_DUPFD
));
1394 scm_sysintern ("F_GETFD", scm_long2num (F_GETFD
));
1397 scm_sysintern ("F_SETFD", scm_long2num (F_SETFD
));
1400 scm_sysintern ("F_GETFL", scm_long2num (F_GETFL
));
1403 scm_sysintern ("F_SETFL", scm_long2num (F_SETFL
));
1406 scm_sysintern ("F_GETOWN", scm_long2num (F_GETOWN
));
1409 scm_sysintern ("F_SETOWN", scm_long2num (F_SETOWN
));
1412 scm_sysintern ("FD_CLOEXEC", scm_long2num (FD_CLOEXEC
));
1415 #include "filesys.x"