]> git.donarmstrong.com Git - lilypond.git/blob - guile18/libguile/posix.c
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / libguile / posix.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
2  * 
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library 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 GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17
18
19 \f
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <errno.h>
27
28 #include "libguile/_scm.h"
29 #include "libguile/dynwind.h"
30 #include "libguile/fports.h"
31 #include "libguile/scmsigs.h"
32 #include "libguile/feature.h"
33 #include "libguile/strings.h"
34 #include "libguile/srfi-13.h"
35 #include "libguile/srfi-14.h"
36 #include "libguile/vectors.h"
37 #include "libguile/lang.h"
38
39 #include "libguile/validate.h"
40 #include "libguile/posix.h"
41 #include "libguile/i18n.h"
42 #include "libguile/threads.h"
43 \f
44
45 #ifdef HAVE_STRING_H
46 #include <string.h>
47 #endif
48 #ifdef TIME_WITH_SYS_TIME
49 # include <sys/time.h>
50 # include <time.h>
51 #else
52 # if HAVE_SYS_TIME_H
53 #  include <sys/time.h>
54 # else
55 #  include <time.h>
56 # endif
57 #endif
58
59 #ifdef HAVE_UNISTD_H
60 #include <unistd.h>
61 #else
62 #ifndef ttyname
63 extern char *ttyname();
64 #endif
65 #endif
66
67 #ifdef LIBC_H_WITH_UNISTD_H
68 #include <libc.h>
69 #endif
70
71 #include <sys/types.h>
72 #include <sys/stat.h>
73 #include <fcntl.h>
74
75 #ifdef HAVE_PWD_H
76 #include <pwd.h>
77 #endif
78 #ifdef HAVE_IO_H
79 #include <io.h>
80 #endif
81 #ifdef HAVE_WINSOCK2_H
82 #include <winsock2.h>
83 #endif
84
85 #ifdef __MINGW32__
86 /* Some defines for Windows here. */
87 # include <process.h>
88 # define pipe(fd) _pipe (fd, 256, O_BINARY)
89 #endif /* __MINGW32__ */
90
91 #if HAVE_SYS_WAIT_H
92 # include <sys/wait.h>
93 #endif
94 #ifndef WEXITSTATUS
95 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
96 #endif
97 #ifndef WIFEXITED
98 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
99 #endif
100
101 #include <signal.h>
102
103 extern char ** environ;
104
105 #ifdef HAVE_GRP_H
106 #include <grp.h>
107 #endif
108 #ifdef HAVE_SYS_UTSNAME_H
109 #include <sys/utsname.h>
110 #endif
111
112 #ifdef HAVE_SETLOCALE
113 #include <locale.h>
114 #endif
115
116 #if HAVE_CRYPT_H
117 #  include <crypt.h>
118 #endif
119
120 #ifdef HAVE_NETDB_H
121 #include <netdb.h>      /* for MAXHOSTNAMELEN on Solaris */
122 #endif
123
124 #ifdef HAVE_SYS_PARAM_H
125 #include <sys/param.h>  /* for MAXHOSTNAMELEN */
126 #endif
127
128 #if HAVE_SYS_RESOURCE_H
129 #  include <sys/resource.h>
130 #endif
131
132 #if HAVE_SYS_FILE_H
133 # include <sys/file.h>
134 #endif
135
136 #if HAVE_CRT_EXTERNS_H
137 #include <crt_externs.h>  /* for Darwin _NSGetEnviron */
138 #endif
139
140 /* Some Unix systems don't define these.  CPP hair is dangerous, but
141    this seems safe enough... */
142 #ifndef R_OK
143 #define R_OK 4
144 #endif
145
146 #ifndef W_OK
147 #define W_OK 2
148 #endif
149
150 #ifndef X_OK
151 #define X_OK 1
152 #endif
153
154 #ifndef F_OK
155 #define F_OK 0
156 #endif
157
158 /* No prototype for this on Solaris 10.  The man page says it's in
159    <unistd.h> ... but it lies. */
160 #if ! HAVE_DECL_SETHOSTNAME
161 int sethostname (char *name, size_t namelen);
162 #endif
163
164 /* On NextStep, <utime.h> doesn't define struct utime, unless we
165    #define _POSIX_SOURCE before #including it.  I think this is less
166    of a kludge than defining struct utimbuf ourselves.  */
167 #ifdef UTIMBUF_NEEDS_POSIX
168 #define _POSIX_SOURCE
169 #endif
170
171 #ifdef HAVE_SYS_UTIME_H
172 #include <sys/utime.h>
173 #endif
174
175 #ifdef HAVE_UTIME_H
176 #include <utime.h>
177 #endif
178
179 /* Please don't add any more #includes or #defines here.  The hack
180    above means that _POSIX_SOURCE may be #defined, which will
181    encourage header files to do strange things.
182
183    FIXME: Maybe should undef _POSIX_SOURCE after it's done its job.
184
185    FIXME: Probably should do all the includes first, then all the fallback
186    declarations and defines, in case things are not in the header we
187    imagine.  */
188
189
190
191
192 /* On Apple Darwin in a shared library there's no "environ" to access
193    directly, instead the address of that variable must be obtained with
194    _NSGetEnviron().  */
195 #if HAVE__NSGETENVIRON && defined (PIC)
196 #define environ (*_NSGetEnviron())
197 #endif
198
199 \f
200
201 /* Two often used patterns
202  */
203
204 #define WITH_STRING(str,cstr,code)             \
205   do {                                         \
206     char *cstr = scm_to_locale_string (str);   \
207     code;                                      \
208     free (cstr);                               \
209   } while (0)
210
211 #define STRING_SYSCALL(str,cstr,code)        \
212   do {                                       \
213     int eno;                                 \
214     char *cstr = scm_to_locale_string (str); \
215     SCM_SYSCALL (code);                      \
216     eno = errno; free (cstr); errno = eno;   \
217   } while (0)
218
219
220 \f
221 SCM_SYMBOL (sym_read_pipe, "read pipe");
222 SCM_SYMBOL (sym_write_pipe, "write pipe");
223
224 SCM_DEFINE (scm_pipe, "pipe", 0, 0, 0,
225             (),
226             "Return a newly created pipe: a pair of ports which are linked\n"
227             "together on the local machine.  The @emph{car} is the input\n"
228             "port and the @emph{cdr} is the output port.  Data written (and\n"
229             "flushed) to the output port can be read from the input port.\n"
230             "Pipes are commonly used for communication with a newly forked\n"
231             "child process.  The need to flush the output port can be\n"
232             "avoided by making it unbuffered using @code{setvbuf}.\n"
233             "\n"
234             "Writes occur atomically provided the size of the data in bytes\n"
235             "is not greater than the value of @code{PIPE_BUF}.  Note that\n"
236             "the output port is likely to block if too much data (typically\n"
237             "equal to @code{PIPE_BUF}) has been written but not yet read\n"
238             "from the input port.")
239 #define FUNC_NAME s_scm_pipe
240 {
241   int fd[2], rv;
242   SCM p_rd, p_wt;
243
244   rv = pipe (fd);
245   if (rv)
246     SCM_SYSERROR;
247   
248   p_rd = scm_fdes_to_port (fd[0], "r", sym_read_pipe);
249   p_wt = scm_fdes_to_port (fd[1], "w", sym_write_pipe);
250   return scm_cons (p_rd, p_wt);
251 }
252 #undef FUNC_NAME
253
254
255 #ifdef HAVE_GETGROUPS
256 SCM_DEFINE (scm_getgroups, "getgroups", 0, 0, 0,
257             (),
258             "Return a vector of integers representing the current\n"
259             "supplementary group IDs.")
260 #define FUNC_NAME s_scm_getgroups
261 {
262   SCM result;
263   int ngroups;
264   size_t size;
265   GETGROUPS_T *groups;
266
267   ngroups = getgroups (0, NULL);
268   if (ngroups <= 0)
269     SCM_SYSERROR;
270
271   size = ngroups * sizeof (GETGROUPS_T);
272   groups = scm_malloc (size);
273   ngroups = getgroups (ngroups, groups);
274
275   result = scm_c_make_vector (ngroups, SCM_BOOL_F);
276   while (--ngroups >= 0) 
277     SCM_SIMPLE_VECTOR_SET (result, ngroups, scm_from_ulong (groups[ngroups]));
278
279   free (groups);
280   return result;
281 }
282 #undef FUNC_NAME  
283 #endif
284
285 #ifdef HAVE_SETGROUPS
286 SCM_DEFINE (scm_setgroups, "setgroups", 1, 0, 0,
287             (SCM group_vec),
288             "Set the current set of supplementary group IDs to the integers\n"
289             "in the given vector @var{vec}.  The return value is\n"
290             "unspecified.\n"
291             "\n"
292             "Generally only the superuser can set the process group IDs.")
293 #define FUNC_NAME s_scm_setgroups
294 {
295   size_t ngroups;
296   size_t size;
297   size_t i;
298   int result;
299   int save_errno;
300   GETGROUPS_T *groups;
301
302   SCM_VALIDATE_VECTOR (SCM_ARG1, group_vec);
303
304   ngroups = SCM_SIMPLE_VECTOR_LENGTH (group_vec);
305
306   /* validate before allocating, so we don't have to worry about leaks */
307   for (i = 0; i < ngroups; i++)
308     {
309       unsigned long ulong_gid;
310       GETGROUPS_T gid;
311       SCM_VALIDATE_ULONG_COPY (1, SCM_SIMPLE_VECTOR_REF (group_vec, i),
312                                ulong_gid);
313       gid = ulong_gid;
314       if (gid != ulong_gid)
315         SCM_OUT_OF_RANGE (1, SCM_SIMPLE_VECTOR_REF (group_vec, i));
316     }
317
318   size = ngroups * sizeof (GETGROUPS_T);
319   if (size / sizeof (GETGROUPS_T) != ngroups)
320     SCM_OUT_OF_RANGE (SCM_ARG1, scm_from_int (ngroups));
321   groups = scm_malloc (size);
322   for(i = 0; i < ngroups; i++)
323     groups [i] = SCM_NUM2ULONG (1, SCM_SIMPLE_VECTOR_REF (group_vec, i));
324
325   result = setgroups (ngroups, groups);
326   save_errno = errno; /* don't let free() touch errno */
327   free (groups);
328   errno = save_errno;
329   if (result < 0)
330     SCM_SYSERROR;
331   return SCM_UNSPECIFIED;
332 }
333 #undef FUNC_NAME
334 #endif
335
336 #ifdef HAVE_GETPWENT
337 SCM_DEFINE (scm_getpwuid, "getpw", 0, 1, 0,
338             (SCM user),
339             "Look up an entry in the user database.  @var{obj} can be an integer,\n"
340             "a string, or omitted, giving the behaviour of getpwuid, getpwnam\n"
341             "or getpwent respectively.")
342 #define FUNC_NAME s_scm_getpwuid
343 {
344   struct passwd *entry;
345
346   SCM result = scm_c_make_vector (7, SCM_UNSPECIFIED);
347   if (SCM_UNBNDP (user) || scm_is_false (user))
348     {
349       SCM_SYSCALL (entry = getpwent ());
350       if (! entry)
351         {
352           return SCM_BOOL_F;
353         }
354     }
355   else if (scm_is_integer (user))
356     {
357       entry = getpwuid (scm_to_int (user));
358     }
359   else
360     {
361       WITH_STRING (user, c_user,
362                    entry = getpwnam (c_user));
363     }
364   if (!entry)
365     SCM_MISC_ERROR ("entry not found", SCM_EOL);
366
367   SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->pw_name));
368   SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_locale_string (entry->pw_passwd));
369   SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_ulong (entry->pw_uid));
370   SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_ulong (entry->pw_gid));
371   SCM_SIMPLE_VECTOR_SET(result, 4, scm_from_locale_string (entry->pw_gecos));
372   if (!entry->pw_dir)
373     SCM_SIMPLE_VECTOR_SET(result, 5, scm_from_locale_string (""));
374   else
375     SCM_SIMPLE_VECTOR_SET(result, 5, scm_from_locale_string (entry->pw_dir));
376   if (!entry->pw_shell)
377     SCM_SIMPLE_VECTOR_SET(result, 6, scm_from_locale_string (""));
378   else
379     SCM_SIMPLE_VECTOR_SET(result, 6, scm_from_locale_string (entry->pw_shell));
380   return result;
381 }
382 #undef FUNC_NAME
383 #endif /* HAVE_GETPWENT */
384
385
386 #ifdef HAVE_SETPWENT
387 SCM_DEFINE (scm_setpwent, "setpw", 0, 1, 0,
388             (SCM arg),
389             "If called with a true argument, initialize or reset the password data\n"
390             "stream.  Otherwise, close the stream.  The @code{setpwent} and\n"
391             "@code{endpwent} procedures are implemented on top of this.")
392 #define FUNC_NAME s_scm_setpwent
393 {
394   if (SCM_UNBNDP (arg) || scm_is_false (arg))
395     endpwent ();
396   else
397     setpwent ();
398   return SCM_UNSPECIFIED;
399 }
400 #undef FUNC_NAME
401 #endif
402
403
404 #ifdef HAVE_GETGRENT
405 /* Combines getgrgid and getgrnam.  */
406 SCM_DEFINE (scm_getgrgid, "getgr", 0, 1, 0,
407             (SCM name),
408             "Look up an entry in the group database.  @var{obj} can be an integer,\n"
409             "a string, or omitted, giving the behaviour of getgrgid, getgrnam\n"
410             "or getgrent respectively.")
411 #define FUNC_NAME s_scm_getgrgid
412 {
413   struct group *entry;
414   SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
415
416   if (SCM_UNBNDP (name) || scm_is_false (name))
417     {
418       SCM_SYSCALL (entry = getgrent ());
419       if (! entry)
420         {
421           return SCM_BOOL_F;
422         }
423     }
424   else if (scm_is_integer (name))
425     SCM_SYSCALL (entry = getgrgid (scm_to_int (name)));
426   else
427     STRING_SYSCALL (name, c_name,
428                     entry = getgrnam (c_name));
429   if (!entry)
430     SCM_SYSERROR;
431
432   SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->gr_name));
433   SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_locale_string (entry->gr_passwd));
434   SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_ulong  (entry->gr_gid));
435   SCM_SIMPLE_VECTOR_SET(result, 3, scm_makfromstrs (-1, entry->gr_mem));
436   return result;
437 }
438 #undef FUNC_NAME
439
440
441
442 SCM_DEFINE (scm_setgrent, "setgr", 0, 1, 0, 
443             (SCM arg),
444             "If called with a true argument, initialize or reset the group data\n"
445             "stream.  Otherwise, close the stream.  The @code{setgrent} and\n"
446             "@code{endgrent} procedures are implemented on top of this.")
447 #define FUNC_NAME s_scm_setgrent
448 {
449   if (SCM_UNBNDP (arg) || scm_is_false (arg))
450     endgrent ();
451   else
452     setgrent ();
453   return SCM_UNSPECIFIED;
454 }
455 #undef FUNC_NAME
456 #endif /* HAVE_GETGRENT */
457
458
459 SCM_DEFINE (scm_kill, "kill", 2, 0, 0,
460             (SCM pid, SCM sig),
461             "Sends a signal to the specified process or group of processes.\n\n"
462             "@var{pid} specifies the processes to which the signal is sent:\n\n"
463             "@table @r\n"
464             "@item @var{pid} greater than 0\n"
465             "The process whose identifier is @var{pid}.\n"
466             "@item @var{pid} equal to 0\n"
467             "All processes in the current process group.\n"
468             "@item @var{pid} less than -1\n"
469             "The process group whose identifier is -@var{pid}\n"
470             "@item @var{pid} equal to -1\n"
471             "If the process is privileged, all processes except for some special\n"
472             "system processes.  Otherwise, all processes with the current effective\n"
473             "user ID.\n"
474             "@end table\n\n"
475             "@var{sig} should be specified using a variable corresponding to\n"
476             "the Unix symbolic name, e.g.,\n\n"
477             "@defvar SIGHUP\n"
478             "Hang-up signal.\n"
479             "@end defvar\n\n"
480             "@defvar SIGINT\n"
481             "Interrupt signal.\n"
482             "@end defvar")
483 #define FUNC_NAME s_scm_kill
484 {
485   /* Signal values are interned in scm_init_posix().  */
486 #ifdef HAVE_KILL
487   if (kill (scm_to_int (pid), scm_to_int  (sig)) != 0)
488     SCM_SYSERROR;
489 #else
490   /* Mingw has raise(), but not kill().  (Other raw DOS environments might
491      be similar.)  Use raise() when the requested pid is our own process,
492      otherwise bomb.  */
493   if (scm_to_int (pid) == getpid ())
494     {
495       if (raise (scm_to_int (sig)) != 0)
496         {
497         err:
498           SCM_SYSERROR;
499         }
500       else
501         {
502           errno = ENOSYS;
503           goto err;
504         }
505     }
506 #endif
507   return SCM_UNSPECIFIED;
508 }
509 #undef FUNC_NAME
510
511 #ifdef HAVE_WAITPID
512 SCM_DEFINE (scm_waitpid, "waitpid", 1, 1, 0,
513             (SCM pid, SCM options),
514             "This procedure collects status information from a child process which\n"
515             "has terminated or (optionally) stopped.  Normally it will\n"
516             "suspend the calling process until this can be done.  If more than one\n"
517             "child process is eligible then one will be chosen by the operating system.\n\n"
518             "The value of @var{pid} determines the behaviour:\n\n"
519             "@table @r\n"
520             "@item @var{pid} greater than 0\n"
521             "Request status information from the specified child process.\n"
522             "@item @var{pid} equal to -1 or WAIT_ANY\n"
523             "Request status information for any child process.\n"
524             "@item @var{pid} equal to 0 or WAIT_MYPGRP\n"
525             "Request status information for any child process in the current process\n"
526             "group.\n"
527             "@item @var{pid} less than -1\n"
528             "Request status information for any child process whose process group ID\n"
529             "is -@var{PID}.\n"
530             "@end table\n\n"
531             "The @var{options} argument, if supplied, should be the bitwise OR of the\n"
532             "values of zero or more of the following variables:\n\n"
533             "@defvar WNOHANG\n"
534             "Return immediately even if there are no child processes to be collected.\n"
535             "@end defvar\n\n"
536             "@defvar WUNTRACED\n"
537             "Report status information for stopped processes as well as terminated\n"
538             "processes.\n"
539             "@end defvar\n\n"
540             "The return value is a pair containing:\n\n"
541             "@enumerate\n"
542             "@item\n"
543             "The process ID of the child process, or 0 if @code{WNOHANG} was\n"
544             "specified and no process was collected.\n"
545             "@item\n"
546             "The integer status value.\n"
547             "@end enumerate")
548 #define FUNC_NAME s_scm_waitpid
549 {
550   int i;
551   int status;
552   int ioptions;
553   if (SCM_UNBNDP (options))
554     ioptions = 0;
555   else
556     {
557       /* Flags are interned in scm_init_posix.  */
558       ioptions = scm_to_int (options);
559     }
560   SCM_SYSCALL (i = waitpid (scm_to_int (pid), &status, ioptions));
561   if (i == -1)
562     SCM_SYSERROR;
563   return scm_cons (scm_from_int (i), scm_from_int (status));
564 }
565 #undef FUNC_NAME
566 #endif /* HAVE_WAITPID */
567
568 #ifndef __MINGW32__
569 SCM_DEFINE (scm_status_exit_val, "status:exit-val", 1, 0, 0, 
570             (SCM status),
571             "Return the exit status value, as would be set if a process\n"
572             "ended normally through a call to @code{exit} or @code{_exit},\n"
573             "if any, otherwise @code{#f}.")
574 #define FUNC_NAME s_scm_status_exit_val
575 {
576   int lstatus;
577
578   /* On Ultrix, the WIF... macros assume their argument is an lvalue;
579      go figure.  */
580   lstatus = scm_to_int (status);
581   if (WIFEXITED (lstatus))
582     return (scm_from_int (WEXITSTATUS (lstatus)));
583   else
584     return SCM_BOOL_F;
585 }
586 #undef FUNC_NAME
587
588 SCM_DEFINE (scm_status_term_sig, "status:term-sig", 1, 0, 0, 
589             (SCM status),
590             "Return the signal number which terminated the process, if any,\n"
591             "otherwise @code{#f}.")
592 #define FUNC_NAME s_scm_status_term_sig
593 {
594   int lstatus;
595
596   lstatus = scm_to_int (status);
597   if (WIFSIGNALED (lstatus))
598     return scm_from_int (WTERMSIG (lstatus));
599   else
600     return SCM_BOOL_F;
601 }
602 #undef FUNC_NAME
603
604 SCM_DEFINE (scm_status_stop_sig, "status:stop-sig", 1, 0, 0, 
605             (SCM status),
606             "Return the signal number which stopped the process, if any,\n"
607             "otherwise @code{#f}.")
608 #define FUNC_NAME s_scm_status_stop_sig
609 {
610   int lstatus;
611
612   lstatus = scm_to_int (status);
613   if (WIFSTOPPED (lstatus))
614     return scm_from_int (WSTOPSIG (lstatus));
615   else
616     return SCM_BOOL_F;
617 }
618 #undef FUNC_NAME
619 #endif /* __MINGW32__ */
620
621 #ifdef HAVE_GETPPID
622 SCM_DEFINE (scm_getppid, "getppid", 0, 0, 0,
623             (),
624             "Return an integer representing the process ID of the parent\n"
625             "process.")
626 #define FUNC_NAME s_scm_getppid
627 {
628   return scm_from_int (getppid ());
629 }
630 #undef FUNC_NAME
631 #endif /* HAVE_GETPPID */
632
633
634 #ifndef __MINGW32__
635 SCM_DEFINE (scm_getuid, "getuid", 0, 0, 0,
636             (),
637             "Return an integer representing the current real user ID.")
638 #define FUNC_NAME s_scm_getuid
639 {
640   return scm_from_int (getuid ());
641 }
642 #undef FUNC_NAME
643
644
645
646 SCM_DEFINE (scm_getgid, "getgid", 0, 0, 0,
647             (),
648             "Return an integer representing the current real group ID.")
649 #define FUNC_NAME s_scm_getgid
650 {
651   return scm_from_int (getgid ());
652 }
653 #undef FUNC_NAME
654
655
656
657 SCM_DEFINE (scm_geteuid, "geteuid", 0, 0, 0,
658             (),
659             "Return an integer representing the current effective user ID.\n"
660             "If the system does not support effective IDs, then the real ID\n"
661             "is returned.  @code{(provided? 'EIDs)} reports whether the\n"
662             "system supports effective IDs.")
663 #define FUNC_NAME s_scm_geteuid
664 {
665 #ifdef HAVE_GETEUID
666   return scm_from_int (geteuid ());
667 #else
668   return scm_from_int (getuid ());
669 #endif
670 }
671 #undef FUNC_NAME
672
673
674 SCM_DEFINE (scm_getegid, "getegid", 0, 0, 0,
675             (),
676             "Return an integer representing the current effective group ID.\n"
677             "If the system does not support effective IDs, then the real ID\n"
678             "is returned.  @code{(provided? 'EIDs)} reports whether the\n"
679             "system supports effective IDs.")
680 #define FUNC_NAME s_scm_getegid
681 {
682 #ifdef HAVE_GETEUID
683   return scm_from_int (getegid ());
684 #else
685   return scm_from_int (getgid ());
686 #endif
687 }
688 #undef FUNC_NAME
689
690
691 SCM_DEFINE (scm_setuid, "setuid", 1, 0, 0, 
692             (SCM id),
693             "Sets both the real and effective user IDs to the integer @var{id}, provided\n"
694             "the process has appropriate privileges.\n"
695             "The return value is unspecified.")
696 #define FUNC_NAME s_scm_setuid
697 {
698   if (setuid (scm_to_int (id)) != 0)
699     SCM_SYSERROR;
700   return SCM_UNSPECIFIED;
701 }
702 #undef FUNC_NAME
703
704 SCM_DEFINE (scm_setgid, "setgid", 1, 0, 0, 
705             (SCM id),
706             "Sets both the real and effective group IDs to the integer @var{id}, provided\n"
707             "the process has appropriate privileges.\n"
708             "The return value is unspecified.")
709 #define FUNC_NAME s_scm_setgid
710 {
711   if (setgid (scm_to_int (id)) != 0)
712     SCM_SYSERROR;
713   return SCM_UNSPECIFIED;
714 }
715 #undef FUNC_NAME
716
717 SCM_DEFINE (scm_seteuid, "seteuid", 1, 0, 0, 
718             (SCM id),
719             "Sets the effective user ID to the integer @var{id}, provided the process\n"
720             "has appropriate privileges.  If effective IDs are not supported, the\n"
721             "real ID is set instead -- @code{(provided? 'EIDs)} reports whether the\n"
722             "system supports effective IDs.\n"
723             "The return value is unspecified.")
724 #define FUNC_NAME s_scm_seteuid
725 {
726   int rv;
727
728 #ifdef HAVE_SETEUID
729   rv = seteuid (scm_to_int (id));
730 #else
731   rv = setuid (scm_to_int (id));
732 #endif
733   if (rv != 0)
734     SCM_SYSERROR;
735   return SCM_UNSPECIFIED;
736 }
737 #undef FUNC_NAME
738 #endif /* __MINGW32__ */
739
740
741 #ifdef HAVE_SETEGID
742 SCM_DEFINE (scm_setegid, "setegid", 1, 0, 0, 
743             (SCM id),
744             "Sets the effective group ID to the integer @var{id}, provided the process\n"
745             "has appropriate privileges.  If effective IDs are not supported, the\n"
746             "real ID is set instead -- @code{(provided? 'EIDs)} reports whether the\n"
747             "system supports effective IDs.\n"
748             "The return value is unspecified.")
749 #define FUNC_NAME s_scm_setegid
750 {
751   int rv;
752
753 #ifdef HAVE_SETEUID
754   rv = setegid (scm_to_int (id));
755 #else
756   rv = setgid (scm_to_int (id));
757 #endif
758   if (rv != 0)
759     SCM_SYSERROR;
760   return SCM_UNSPECIFIED;
761     
762 }
763 #undef FUNC_NAME
764 #endif
765
766
767 #ifdef HAVE_GETPGRP
768 SCM_DEFINE (scm_getpgrp, "getpgrp", 0, 0, 0,
769             (),
770             "Return an integer representing the current process group ID.\n"
771             "This is the POSIX definition, not BSD.")
772 #define FUNC_NAME s_scm_getpgrp
773 {
774   int (*fn)();
775   fn = (int (*) ()) getpgrp;
776   return scm_from_int (fn (0));
777 }
778 #undef FUNC_NAME
779 #endif /* HAVE_GETPGRP */
780
781
782 #ifdef HAVE_SETPGID
783 SCM_DEFINE (scm_setpgid, "setpgid", 2, 0, 0, 
784             (SCM pid, SCM pgid),
785             "Move the process @var{pid} into the process group @var{pgid}.  @var{pid} or\n"
786             "@var{pgid} must be integers: they can be zero to indicate the ID of the\n"
787             "current process.\n"
788             "Fails on systems that do not support job control.\n"
789             "The return value is unspecified.")
790 #define FUNC_NAME s_scm_setpgid
791 {
792   /* FIXME(?): may be known as setpgrp.  */
793   if (setpgid (scm_to_int (pid), scm_to_int (pgid)) != 0)
794     SCM_SYSERROR;
795   return SCM_UNSPECIFIED;
796 }
797 #undef FUNC_NAME
798 #endif /* HAVE_SETPGID */
799
800 #ifdef HAVE_SETSID
801 SCM_DEFINE (scm_setsid, "setsid", 0, 0, 0,
802             (),
803             "Creates a new session.  The current process becomes the session leader\n"
804             "and is put in a new process group.  The process will be detached\n"
805             "from its controlling terminal if it has one.\n"
806             "The return value is an integer representing the new process group ID.")
807 #define FUNC_NAME s_scm_setsid
808 {
809   pid_t sid = setsid ();
810   if (sid == -1)
811     SCM_SYSERROR;
812   return SCM_UNSPECIFIED;
813 }
814 #undef FUNC_NAME
815 #endif /* HAVE_SETSID */
816
817
818 /* ttyname returns its result in a single static buffer, hence
819    scm_i_misc_mutex for thread safety.  In glibc 2.3.2 two threads
820    continuously calling ttyname will otherwise get an overwrite quite
821    easily.
822
823    ttyname_r (when available) could be used instead of scm_i_misc_mutex, but
824    there's probably little to be gained in either speed or parallelism.  */
825
826 #ifdef HAVE_TTYNAME
827 SCM_DEFINE (scm_ttyname, "ttyname", 1, 0, 0, 
828             (SCM port),
829             "Return a string with the name of the serial terminal device\n"
830             "underlying @var{port}.")
831 #define FUNC_NAME s_scm_ttyname
832 {
833   char *result;
834   int fd, err;
835   SCM ret = SCM_BOOL_F;
836
837   port = SCM_COERCE_OUTPORT (port);
838   SCM_VALIDATE_OPPORT (1, port);
839   if (!SCM_FPORTP (port))
840     return SCM_BOOL_F;
841   fd = SCM_FPORT_FDES (port);
842
843   scm_i_scm_pthread_mutex_lock (&scm_i_misc_mutex);
844
845   SCM_SYSCALL (result = ttyname (fd));
846   err = errno;
847   if (result != NULL)
848     result = strdup (result);
849
850   scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
851
852   if (!result)
853     {
854       errno = err;
855       SCM_SYSERROR;
856     }
857   else
858     ret = scm_take_locale_string (result);
859
860   return ret;
861 }
862 #undef FUNC_NAME
863 #endif /* HAVE_TTYNAME */
864
865
866 /* For thread safety "buf" is used instead of NULL for the ctermid static
867    buffer.  Actually it's unlikely the controlling terminal will change
868    during program execution, and indeed on glibc (2.3.2) it's always just
869    "/dev/tty", but L_ctermid on the stack is easy and fast and guarantees
870    safety everywhere.  */
871 #ifdef HAVE_CTERMID
872 SCM_DEFINE (scm_ctermid, "ctermid", 0, 0, 0,
873             (),
874             "Return a string containing the file name of the controlling\n"
875             "terminal for the current process.")
876 #define FUNC_NAME s_scm_ctermid
877 {
878   char buf[L_ctermid];
879   char *result = ctermid (buf);
880   if (*result == '\0')
881     SCM_SYSERROR;
882   return scm_from_locale_string (result);
883 }
884 #undef FUNC_NAME
885 #endif /* HAVE_CTERMID */
886
887 #ifdef HAVE_TCGETPGRP
888 SCM_DEFINE (scm_tcgetpgrp, "tcgetpgrp", 1, 0, 0, 
889             (SCM port),
890             "Return the process group ID of the foreground process group\n"
891             "associated with the terminal open on the file descriptor\n"
892             "underlying @var{port}.\n"
893             "\n"
894             "If there is no foreground process group, the return value is a\n"
895             "number greater than 1 that does not match the process group ID\n"
896             "of any existing process group.  This can happen if all of the\n"
897             "processes in the job that was formerly the foreground job have\n"
898             "terminated, and no other job has yet been moved into the\n"
899             "foreground.")
900 #define FUNC_NAME s_scm_tcgetpgrp
901 {
902   int fd;
903   pid_t pgid;
904
905   port = SCM_COERCE_OUTPORT (port);
906
907   SCM_VALIDATE_OPFPORT (1, port);
908   fd = SCM_FPORT_FDES (port);
909   if ((pgid = tcgetpgrp (fd)) == -1)
910     SCM_SYSERROR;
911   return scm_from_int (pgid);
912 }
913 #undef FUNC_NAME    
914 #endif /* HAVE_TCGETPGRP */
915
916 #ifdef HAVE_TCSETPGRP
917 SCM_DEFINE (scm_tcsetpgrp, "tcsetpgrp", 2, 0, 0,
918             (SCM port, SCM pgid),
919             "Set the foreground process group ID for the terminal used by the file\n"
920             "descriptor underlying @var{port} to the integer @var{pgid}.\n"
921             "The calling process\n"
922             "must be a member of the same session as @var{pgid} and must have the same\n"
923             "controlling terminal.  The return value is unspecified.")
924 #define FUNC_NAME s_scm_tcsetpgrp
925 {
926   int fd;
927
928   port = SCM_COERCE_OUTPORT (port);
929
930   SCM_VALIDATE_OPFPORT (1, port);
931   fd = SCM_FPORT_FDES (port);
932   if (tcsetpgrp (fd, scm_to_int (pgid)) == -1)
933     SCM_SYSERROR;
934   return SCM_UNSPECIFIED;
935 }
936 #undef FUNC_NAME
937 #endif /* HAVE_TCSETPGRP */
938
939 static void
940 free_string_pointers (void *data)
941 {
942   scm_i_free_string_pointers ((char **)data);
943 }
944
945 SCM_DEFINE (scm_execl, "execl", 1, 0, 1, 
946             (SCM filename, SCM args),
947             "Executes the file named by @var{path} as a new process image.\n"
948             "The remaining arguments are supplied to the process; from a C program\n"
949             "they are accessible as the @code{argv} argument to @code{main}.\n"
950             "Conventionally the first @var{arg} is the same as @var{path}.\n"
951             "All arguments must be strings.\n\n"
952             "If @var{arg} is missing, @var{path} is executed with a null\n"
953             "argument list, which may have system-dependent side-effects.\n\n"
954             "This procedure is currently implemented using the @code{execv} system\n"
955             "call, but we call it @code{execl} because of its Scheme calling interface.")
956 #define FUNC_NAME s_scm_execl
957 {
958   char *exec_file;
959   char **exec_argv;
960
961   scm_dynwind_begin (0);
962
963   exec_file = scm_to_locale_string (filename);
964   scm_dynwind_free (exec_file);
965
966   exec_argv = scm_i_allocate_string_pointers (args);
967   scm_dynwind_unwind_handler (free_string_pointers, exec_argv, 
968                             SCM_F_WIND_EXPLICITLY);
969
970   execv (exec_file,
971 #ifdef __MINGW32__
972          /* extra "const" in mingw formals, provokes warning from gcc */
973          (const char * const *)
974 #endif
975          exec_argv);
976   SCM_SYSERROR;
977
978   /* not reached.  */
979   scm_dynwind_end ();
980   return SCM_BOOL_F;
981 }
982 #undef FUNC_NAME
983
984 SCM_DEFINE (scm_execlp, "execlp", 1, 0, 1, 
985             (SCM filename, SCM args),
986             "Similar to @code{execl}, however if\n"
987             "@var{filename} does not contain a slash\n"
988             "then the file to execute will be located by searching the\n"
989             "directories listed in the @code{PATH} environment variable.\n\n"
990             "This procedure is currently implemented using the @code{execvp} system\n"
991             "call, but we call it @code{execlp} because of its Scheme calling interface.")
992 #define FUNC_NAME s_scm_execlp
993 {
994   char *exec_file;
995   char **exec_argv;
996
997   scm_dynwind_begin (0);
998
999   exec_file = scm_to_locale_string (filename);
1000   scm_dynwind_free (exec_file);
1001
1002   exec_argv = scm_i_allocate_string_pointers (args);
1003   scm_dynwind_unwind_handler (free_string_pointers, exec_argv, 
1004                             SCM_F_WIND_EXPLICITLY);
1005
1006   execvp (exec_file,
1007 #ifdef __MINGW32__
1008           /* extra "const" in mingw formals, provokes warning from gcc */
1009           (const char * const *)
1010 #endif
1011           exec_argv);
1012   SCM_SYSERROR;
1013
1014   /* not reached.  */
1015   scm_dynwind_end ();
1016   return SCM_BOOL_F;
1017 }
1018 #undef FUNC_NAME
1019
1020
1021 /* OPTIMIZE-ME: scm_execle doesn't need malloced copies of the environment
1022    list strings the way environ_list_to_c gives.  */
1023
1024 SCM_DEFINE (scm_execle, "execle", 2, 0, 1, 
1025             (SCM filename, SCM env, SCM args),
1026             "Similar to @code{execl}, but the environment of the new process is\n"
1027             "specified by @var{env}, which must be a list of strings as returned by the\n"
1028             "@code{environ} procedure.\n\n"
1029             "This procedure is currently implemented using the @code{execve} system\n"
1030             "call, but we call it @code{execle} because of its Scheme calling interface.")
1031 #define FUNC_NAME s_scm_execle
1032 {
1033   char **exec_argv;
1034   char **exec_env;
1035   char *exec_file;
1036
1037   scm_dynwind_begin (0);
1038
1039   exec_file = scm_to_locale_string (filename);
1040   scm_dynwind_free (exec_file);
1041
1042   exec_argv = scm_i_allocate_string_pointers (args);
1043   scm_dynwind_unwind_handler (free_string_pointers, exec_argv,
1044                             SCM_F_WIND_EXPLICITLY);
1045
1046   exec_env = scm_i_allocate_string_pointers (env);
1047   scm_dynwind_unwind_handler (free_string_pointers, exec_env,
1048                             SCM_F_WIND_EXPLICITLY);
1049
1050   execve (exec_file,
1051 #ifdef __MINGW32__
1052           /* extra "const" in mingw formals, provokes warning from gcc */
1053           (const char * const *)
1054 #endif
1055           exec_argv,
1056 #ifdef __MINGW32__
1057           /* extra "const" in mingw formals, provokes warning from gcc */
1058           (const char * const *)
1059 #endif
1060           exec_env);
1061   SCM_SYSERROR;
1062
1063   /* not reached.  */
1064   scm_dynwind_end ();
1065   return SCM_BOOL_F;
1066 }
1067 #undef FUNC_NAME
1068
1069 #ifdef HAVE_FORK
1070 SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0,
1071             (),
1072             "Creates a new \"child\" process by duplicating the current \"parent\" process.\n"
1073             "In the child the return value is 0.  In the parent the return value is\n"
1074             "the integer process ID of the child.\n\n"
1075             "This procedure has been renamed from @code{fork} to avoid a naming conflict\n"
1076             "with the scsh fork.")
1077 #define FUNC_NAME s_scm_fork
1078 {
1079   int pid;
1080   pid = fork ();
1081   if (pid == -1)
1082     SCM_SYSERROR;
1083   return scm_from_int (pid);
1084 }
1085 #undef FUNC_NAME
1086 #endif /* HAVE_FORK */
1087
1088 #ifdef __MINGW32__
1089 # include "win32-uname.h"
1090 #endif
1091
1092 #if defined (HAVE_UNAME) || defined (__MINGW32__)
1093 SCM_DEFINE (scm_uname, "uname", 0, 0, 0,
1094             (),
1095             "Return an object with some information about the computer\n"
1096             "system the program is running on.")
1097 #define FUNC_NAME s_scm_uname
1098 {
1099   struct utsname buf;
1100   SCM result = scm_c_make_vector (5, SCM_UNSPECIFIED);
1101   if (uname (&buf) < 0)
1102     SCM_SYSERROR;
1103   SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (buf.sysname));
1104   SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_locale_string (buf.nodename));
1105   SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_locale_string (buf.release));
1106   SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_locale_string (buf.version));
1107   SCM_SIMPLE_VECTOR_SET(result, 4, scm_from_locale_string (buf.machine));
1108 /* 
1109    a linux special?
1110   SCM_SIMPLE_VECTOR_SET(result, 5, scm_from_locale_string (buf.domainname));
1111 */
1112   return result;
1113 }
1114 #undef FUNC_NAME
1115 #endif /* HAVE_UNAME */
1116
1117 SCM_DEFINE (scm_environ, "environ", 0, 1, 0, 
1118             (SCM env),
1119             "If @var{env} is omitted, return the current environment (in the\n"
1120             "Unix sense) as a list of strings.  Otherwise set the current\n"
1121             "environment, which is also the default environment for child\n"
1122             "processes, to the supplied list of strings.  Each member of\n"
1123             "@var{env} should be of the form @code{NAME=VALUE} and values of\n"
1124             "@code{NAME} should not be duplicated.  If @var{env} is supplied\n"
1125             "then the return value is unspecified.")
1126 #define FUNC_NAME s_scm_environ
1127 {
1128   if (SCM_UNBNDP (env))
1129     return scm_makfromstrs (-1, environ);
1130   else
1131     {
1132       char **new_environ;
1133
1134       new_environ = scm_i_allocate_string_pointers (env);
1135       /* Free the old environment, except when called for the first
1136        * time.
1137        */
1138       {
1139         static int first = 1;
1140         if (!first)
1141           scm_i_free_string_pointers (environ);
1142         first = 0;
1143       }
1144       environ = new_environ;
1145       return SCM_UNSPECIFIED;
1146     }
1147 }
1148 #undef FUNC_NAME
1149
1150 #ifdef L_tmpnam
1151
1152 SCM_DEFINE (scm_tmpnam, "tmpnam", 0, 0, 0,
1153             (),
1154             "Return a name in the file system that does not match any\n"
1155             "existing file.  However there is no guarantee that another\n"
1156             "process will not create the file after @code{tmpnam} is called.\n"
1157             "Care should be taken if opening the file, e.g., use the\n"
1158             "@code{O_EXCL} open flag or use @code{mkstemp!} instead.")
1159 #define FUNC_NAME s_scm_tmpnam
1160 {
1161   char name[L_tmpnam];
1162   char *rv;
1163
1164   SCM_SYSCALL (rv = tmpnam (name));
1165   if (rv == NULL)
1166     /* not SCM_SYSERROR since errno probably not set.  */
1167     SCM_MISC_ERROR ("tmpnam failed", SCM_EOL);
1168   return scm_from_locale_string (name);
1169 }
1170 #undef FUNC_NAME
1171
1172 #endif
1173
1174 #ifndef HAVE_MKSTEMP
1175 extern int mkstemp (char *);
1176 #endif
1177
1178 SCM_DEFINE (scm_mkstemp, "mkstemp!", 1, 0, 0,
1179             (SCM tmpl),
1180             "Create a new unique file in the file system and return a new\n"
1181             "buffered port open for reading and writing to the file.\n"
1182             "\n"
1183             "@var{tmpl} is a string specifying where the file should be\n"
1184             "created: it must end with @samp{XXXXXX} and those @samp{X}s\n"
1185             "will be changed in the string to return the name of the file.\n"
1186             "(@code{port-filename} on the port also gives the name.)\n"
1187             "\n"
1188             "POSIX doesn't specify the permissions mode of the file, on GNU\n"
1189             "and most systems it's @code{#o600}.  An application can use\n"
1190             "@code{chmod} to relax that if desired.  For example\n"
1191             "@code{#o666} less @code{umask}, which is usual for ordinary\n"
1192             "file creation,\n"
1193             "\n"
1194             "@example\n"
1195             "(let ((port (mkstemp! (string-copy \"/tmp/myfile-XXXXXX\"))))\n"
1196             "  (chmod port (logand #o666 (lognot (umask))))\n"
1197             "  ...)\n"
1198             "@end example")
1199 #define FUNC_NAME s_scm_mkstemp
1200 {
1201   char *c_tmpl;
1202   int rv;
1203   
1204   scm_dynwind_begin (0);
1205
1206   c_tmpl = scm_to_locale_string (tmpl);
1207   scm_dynwind_free (c_tmpl);
1208
1209   SCM_SYSCALL (rv = mkstemp (c_tmpl));
1210   if (rv == -1)
1211     SCM_SYSERROR;
1212
1213   scm_substring_move_x (scm_from_locale_string (c_tmpl),
1214                         SCM_INUM0, scm_string_length (tmpl),
1215                         tmpl, SCM_INUM0);
1216
1217   scm_dynwind_end ();
1218   return scm_fdes_to_port (rv, "w+", tmpl);
1219 }
1220 #undef FUNC_NAME
1221
1222 SCM_DEFINE (scm_utime, "utime", 1, 2, 0,
1223             (SCM pathname, SCM actime, SCM modtime),
1224             "@code{utime} sets the access and modification times for the\n"
1225             "file named by @var{path}.  If @var{actime} or @var{modtime} is\n"
1226             "not supplied, then the current time is used.  @var{actime} and\n"
1227             "@var{modtime} must be integer time values as returned by the\n"
1228             "@code{current-time} procedure.\n"
1229             "@lisp\n"
1230             "(utime \"foo\" (- (current-time) 3600))\n"
1231             "@end lisp\n"
1232             "will set the access time to one hour in the past and the\n"
1233             "modification time to the current time.")
1234 #define FUNC_NAME s_scm_utime
1235 {
1236   int rv;
1237   struct utimbuf utm_tmp;
1238
1239   if (SCM_UNBNDP (actime))
1240     SCM_SYSCALL (time (&utm_tmp.actime));
1241   else
1242     utm_tmp.actime = SCM_NUM2ULONG (2, actime);
1243
1244   if (SCM_UNBNDP (modtime))
1245     SCM_SYSCALL (time (&utm_tmp.modtime));
1246   else
1247     utm_tmp.modtime = SCM_NUM2ULONG (3, modtime);
1248
1249   STRING_SYSCALL (pathname, c_pathname,
1250                   rv = utime (c_pathname, &utm_tmp));
1251   if (rv != 0)
1252     SCM_SYSERROR;
1253   return SCM_UNSPECIFIED;
1254 }
1255 #undef FUNC_NAME
1256
1257 SCM_DEFINE (scm_access, "access?", 2, 0, 0,
1258             (SCM path, SCM how),
1259             "Test accessibility of a file under the real UID and GID of the\n"
1260             "calling process.  The return is @code{#t} if @var{path} exists\n"
1261             "and the permissions requested by @var{how} are all allowed, or\n"
1262             "@code{#f} if not.\n"
1263             "\n"
1264             "@var{how} is an integer which is one of the following values,\n"
1265             "or a bitwise-OR (@code{logior}) of multiple values.\n"
1266             "\n"
1267             "@defvar R_OK\n"
1268             "Test for read permission.\n"
1269             "@end defvar\n"
1270             "@defvar W_OK\n"
1271             "Test for write permission.\n"
1272             "@end defvar\n"
1273             "@defvar X_OK\n"
1274             "Test for execute permission.\n"
1275             "@end defvar\n"
1276             "@defvar F_OK\n"
1277             "Test for existence of the file.  This is implied by each of the\n"
1278             "other tests, so there's no need to combine it with them.\n"
1279             "@end defvar\n"
1280             "\n"
1281             "It's important to note that @code{access?} does not simply\n"
1282             "indicate what will happen on attempting to read or write a\n"
1283             "file.  In normal circumstances it does, but in a set-UID or\n"
1284             "set-GID program it doesn't because @code{access?} tests the\n"
1285             "real ID, whereas an open or execute attempt uses the effective\n"
1286             "ID.\n"
1287             "\n"
1288             "A program which will never run set-UID/GID can ignore the\n"
1289             "difference between real and effective IDs, but for maximum\n"
1290             "generality, especially in library functions, it's best not to\n"
1291             "use @code{access?} to predict the result of an open or execute,\n"
1292             "instead simply attempt that and catch any exception.\n"
1293             "\n"
1294             "The main use for @code{access?} is to let a set-UID/GID program\n"
1295             "determine what the invoking user would have been allowed to do,\n"
1296             "without the greater (or perhaps lesser) privileges afforded by\n"
1297             "the effective ID.  For more on this, see ``Testing File\n"
1298             "Access'' in The GNU C Library Reference Manual.")
1299 #define FUNC_NAME s_scm_access
1300 {
1301   int rv;
1302
1303   WITH_STRING (path, c_path,
1304                rv = access (c_path, scm_to_int (how)));
1305   return scm_from_bool (!rv);
1306 }
1307 #undef FUNC_NAME
1308
1309 SCM_DEFINE (scm_getpid, "getpid", 0, 0, 0,
1310             (),
1311             "Return an integer representing the current process ID.")
1312 #define FUNC_NAME s_scm_getpid
1313 {
1314   return scm_from_ulong (getpid ());
1315 }
1316 #undef FUNC_NAME
1317
1318 SCM_DEFINE (scm_putenv, "putenv", 1, 0, 0, 
1319             (SCM str),
1320             "Modifies the environment of the current process, which is\n"
1321             "also the default environment inherited by child processes.\n\n"
1322             "If @var{string} is of the form @code{NAME=VALUE} then it will be written\n"
1323             "directly into the environment, replacing any existing environment string\n"
1324             "with\n"
1325             "name matching @code{NAME}.  If @var{string} does not contain an equal\n"
1326             "sign, then any existing string with name matching @var{string} will\n"
1327             "be removed.\n\n"
1328             "The return value is unspecified.")
1329 #define FUNC_NAME s_scm_putenv
1330 {
1331   int rv;
1332   char *c_str = scm_to_locale_string (str);
1333
1334   if (strchr (c_str, '=') == NULL)
1335     {
1336       /* We want no "=" in the argument to mean remove the variable from the
1337          environment, but not all putenv()s understand this, for example
1338          FreeBSD 4.8 doesn't.  Getting it happening everywhere is a bit
1339          painful.  When unsetenv() exists, we use that, of course.
1340
1341          Traditionally putenv("NAME") removes a variable, for example that's
1342          what we have to do on Solaris 9 (it doesn't have an unsetenv).
1343
1344          But on DOS and on that DOS overlay manager thing called W-whatever,
1345          putenv("NAME=") must be used (it too doesn't have an unsetenv).
1346
1347          Supposedly on AIX a putenv("NAME") could cause a segfault, but also
1348          supposedly AIX 5.3 and up has unsetenv() available so should be ok
1349          with the latter there.
1350
1351          For the moment we hard code the DOS putenv("NAME=") style under
1352          __MINGW32__ and do the traditional everywhere else.  Such
1353          system-name tests are bad, of course.  It'd be possible to use a
1354          configure test when doing a a native build.  For example GNU R has
1355          such a test (see R_PUTENV_AS_UNSETENV in
1356          https://svn.r-project.org/R/trunk/m4/R.m4).  But when cross
1357          compiling there'd want to be a guess, one probably based on the
1358          system name (ie. mingw or not), thus landing back in basically the
1359          present hard-coded situation.  Another possibility for a cross
1360          build would be to try "NAME" then "NAME=" at runtime, if that's not
1361          too much like overkill.  */
1362
1363 #if defined HAVE_UNSETENV && HAVE_DECL_UNSETENV
1364       /* when unsetenv() exists then we use it */
1365       unsetenv (c_str);
1366       free (c_str);
1367 #elif defined (__MINGW32__)
1368       /* otherwise putenv("NAME=") on DOS */
1369       int e;
1370       size_t len = strlen (c_str);
1371       char *ptr = scm_malloc (len + 2);
1372       strcpy (ptr, c_str);
1373       strcpy (ptr+len, "=");
1374       rv = putenv (ptr);
1375       e = errno; free (ptr); free (c_str); errno = e;
1376       if (rv < 0)
1377         SCM_SYSERROR;
1378 #else
1379       /* otherwise traditional putenv("NAME") */
1380       rv = putenv (c_str);
1381       if (rv < 0)
1382         SCM_SYSERROR;
1383 #endif
1384     }
1385   else
1386     {
1387 #ifdef __MINGW32__
1388       /* If str is "FOO=", ie. attempting to set an empty string, then
1389          we need to see if it's been successful.  On MINGW, "FOO="
1390          means remove FOO from the environment.  As a workaround, we
1391          set "FOO= ", ie. a space, and then modify the string returned
1392          by getenv.  It's not enough just to modify the string we set,
1393          because MINGW putenv copies it.  */
1394
1395       {
1396         size_t len = strlen (c_str);
1397         if (c_str[len-1] == '=')
1398           {
1399             char *ptr = scm_malloc (len+2);
1400             strcpy (ptr, c_str);
1401             strcpy (ptr+len, " ");
1402             rv = putenv (ptr);
1403             if (rv < 0)
1404               {
1405                 int eno = errno;
1406                 free (c_str);
1407                 errno = eno;
1408                 SCM_SYSERROR;
1409               }
1410             /* truncate to just the name */
1411             c_str[len-1] = '\0';
1412             ptr = getenv (c_str);
1413             if (ptr)
1414               ptr[0] = '\0';
1415             return SCM_UNSPECIFIED;
1416           }
1417       }
1418 #endif /* __MINGW32__ */
1419
1420       /* Leave c_str in the environment.  */
1421
1422       rv = putenv (c_str);
1423       if (rv < 0)
1424         SCM_SYSERROR;
1425     }
1426   return SCM_UNSPECIFIED;
1427 }
1428 #undef FUNC_NAME
1429
1430 #ifdef HAVE_SETLOCALE
1431 SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
1432             (SCM category, SCM locale),
1433             "If @var{locale} is omitted, return the current value of the\n"
1434             "specified locale category as a system-dependent string.\n"
1435             "@var{category} should be specified using the values\n"
1436             "@code{LC_COLLATE}, @code{LC_ALL} etc.\n"
1437             "\n"
1438             "Otherwise the specified locale category is set to the string\n"
1439             "@var{locale} and the new value is returned as a\n"
1440             "system-dependent string.  If @var{locale} is an empty string,\n"
1441             "the locale will be set using environment variables.")
1442 #define FUNC_NAME s_scm_setlocale
1443 {
1444   char *clocale;
1445   char *rv;
1446
1447   scm_dynwind_begin (0);
1448
1449   if (SCM_UNBNDP (locale))
1450     {
1451       clocale = NULL;
1452     }
1453   else
1454     {
1455       clocale = scm_to_locale_string (locale);
1456       scm_dynwind_free (clocale);
1457     }
1458
1459   rv = setlocale (scm_i_to_lc_category (category, 1), clocale);
1460   if (rv == NULL)
1461     {
1462       /* POSIX and C99 don't say anything about setlocale setting errno, so
1463          force a sensible value here.  glibc leaves ENOENT, which would be
1464          fine, but it's not a documented feature.  */
1465       errno = EINVAL;
1466       SCM_SYSERROR;
1467     }
1468
1469   /* Recompute the standard SRFI-14 character sets in a locale-dependent
1470      (actually charset-dependent) way.  */
1471   scm_srfi_14_compute_char_sets ();
1472
1473   scm_dynwind_end ();
1474   return scm_from_locale_string (rv);
1475 }
1476 #undef FUNC_NAME
1477 #endif /* HAVE_SETLOCALE */
1478
1479 #ifdef HAVE_MKNOD
1480 SCM_DEFINE (scm_mknod, "mknod", 4, 0, 0,
1481             (SCM path, SCM type, SCM perms, SCM dev),
1482             "Creates a new special file, such as a file corresponding to a device.\n"
1483             "@var{path} specifies the name of the file.  @var{type} should\n"
1484             "be one of the following symbols:\n"
1485             "regular, directory, symlink, block-special, char-special,\n"
1486             "fifo, or socket.  @var{perms} (an integer) specifies the file permissions.\n"
1487             "@var{dev} (an integer) specifies which device the special file refers\n"
1488             "to.  Its exact interpretation depends on the kind of special file\n"
1489             "being created.\n\n"
1490             "E.g.,\n"
1491             "@lisp\n"
1492             "(mknod \"/dev/fd0\" 'block-special #o660 (+ (* 2 256) 2))\n"
1493             "@end lisp\n\n"
1494             "The return value is unspecified.")
1495 #define FUNC_NAME s_scm_mknod
1496 {
1497   int val;
1498   const char *p;
1499   int ctype = 0;
1500
1501   SCM_VALIDATE_STRING (1, path);
1502   SCM_VALIDATE_SYMBOL (2, type);
1503
1504   p = scm_i_symbol_chars (type);
1505   if (strcmp (p, "regular") == 0)
1506     ctype = S_IFREG;
1507   else if (strcmp (p, "directory") == 0)
1508     ctype = S_IFDIR;
1509 #ifdef S_IFLNK
1510   /* systems without symlinks probably don't have S_IFLNK defined */
1511   else if (strcmp (p, "symlink") == 0)
1512     ctype = S_IFLNK;
1513 #endif
1514   else if (strcmp (p, "block-special") == 0)
1515     ctype = S_IFBLK;
1516   else if (strcmp (p, "char-special") == 0)
1517     ctype = S_IFCHR;
1518   else if (strcmp (p, "fifo") == 0)
1519     ctype = S_IFIFO;
1520 #ifdef S_IFSOCK
1521   else if (strcmp (p, "socket") == 0)
1522     ctype = S_IFSOCK;
1523 #endif
1524   else
1525     SCM_OUT_OF_RANGE (2, type);
1526
1527   STRING_SYSCALL (path, c_path,
1528                   val = mknod (c_path,
1529                                ctype | scm_to_int (perms),
1530                                scm_to_int (dev)));
1531   if (val != 0)
1532     SCM_SYSERROR;
1533   return SCM_UNSPECIFIED;
1534 }
1535 #undef FUNC_NAME
1536 #endif /* HAVE_MKNOD */
1537
1538 #ifdef HAVE_NICE
1539 SCM_DEFINE (scm_nice, "nice", 1, 0, 0, 
1540             (SCM incr),
1541             "Increment the priority of the current process by @var{incr}.  A higher\n"
1542             "priority value means that the process runs less often.\n"
1543             "The return value is unspecified.")
1544 #define FUNC_NAME s_scm_nice
1545 {
1546   int nice_value;
1547
1548   /* nice() returns "prio-NZERO" on success or -1 on error, but -1 can arise
1549      from "prio-NZERO", so an error must be detected from errno changed */
1550   errno = 0;
1551   nice_value = nice (scm_to_int (incr));
1552   if (errno != 0)
1553     SCM_SYSERROR;
1554
1555   return SCM_UNSPECIFIED;
1556 }
1557 #undef FUNC_NAME
1558 #endif /* HAVE_NICE */
1559
1560 #ifdef HAVE_SYNC
1561 SCM_DEFINE (scm_sync, "sync", 0, 0, 0,
1562             (),
1563             "Flush the operating system disk buffers.\n"
1564             "The return value is unspecified.")
1565 #define FUNC_NAME s_scm_sync
1566 {
1567   sync();
1568   return SCM_UNSPECIFIED;
1569 }
1570 #undef FUNC_NAME
1571 #endif /* HAVE_SYNC */
1572
1573
1574 /* crypt() returns a pointer to a static buffer, so we use scm_i_misc_mutex
1575    to avoid another thread overwriting it.  A test program running crypt
1576    continuously in two threads can be quickly seen tripping this problem.
1577    crypt() is pretty slow normally, so a mutex shouldn't add much overhead.
1578
1579    glibc has a thread-safe crypt_r, but (in version 2.3.2) it runs a lot
1580    slower (about 5x) than plain crypt if you pass an uninitialized data
1581    block each time.  Presumably there's some one-time setups.  The best way
1582    to use crypt_r for parallel execution in multiple threads would probably
1583    be to maintain a little pool of initialized crypt_data structures, take
1584    one and use it, then return it to the pool.  That pool could be garbage
1585    collected so it didn't add permanently to memory use if only a few crypt
1586    calls are made.  But we expect crypt will be used rarely, and even more
1587    rarely will there be any desire for lots of parallel execution on
1588    multiple cpus.  So for now we don't bother with anything fancy, just
1589    ensure it works.  */
1590
1591 #if HAVE_CRYPT
1592 SCM_DEFINE (scm_crypt, "crypt", 2, 0, 0,
1593             (SCM key, SCM salt),
1594             "Encrypt @var{key} using @var{salt} as the salt value to the\n"
1595             "crypt(3) library call.")
1596 #define FUNC_NAME s_scm_crypt
1597 {
1598   SCM ret;
1599   char *c_key, *c_salt, *c_ret;
1600
1601   scm_dynwind_begin (0);
1602   scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
1603
1604   c_key = scm_to_locale_string (key);
1605   scm_dynwind_free (c_key);
1606   c_salt = scm_to_locale_string (salt);
1607   scm_dynwind_free (c_salt);
1608
1609   /* The Linux crypt(3) man page says crypt will return NULL and set errno
1610      on error.  (Eg. ENOSYS if legal restrictions mean it cannot be
1611      implemented).  */
1612   c_ret = crypt (c_key, c_salt);
1613   if (c_ret == NULL)
1614     SCM_SYSERROR;
1615
1616   ret = scm_from_locale_string (c_ret);
1617   scm_dynwind_end ();
1618   return ret;
1619 }
1620 #undef FUNC_NAME
1621 #endif /* HAVE_CRYPT */
1622
1623 #if HAVE_CHROOT
1624 SCM_DEFINE (scm_chroot, "chroot", 1, 0, 0, 
1625             (SCM path),
1626             "Change the root directory to that specified in @var{path}.\n"
1627             "This directory will be used for path names beginning with\n"
1628             "@file{/}.  The root directory is inherited by all children\n"
1629             "of the current process.  Only the superuser may change the\n"
1630             "root directory.")
1631 #define FUNC_NAME s_scm_chroot
1632 {
1633   int rv;
1634
1635   WITH_STRING (path, c_path,
1636                rv = chroot (c_path));
1637   if (rv == -1)
1638     SCM_SYSERROR;
1639   return SCM_UNSPECIFIED;
1640 }
1641 #undef FUNC_NAME
1642 #endif /* HAVE_CHROOT */
1643
1644
1645 #ifdef __MINGW32__
1646 /* Wrapper function to supplying `getlogin()' under Windows.  */
1647 static char * getlogin (void)
1648 {
1649   static char user[256];
1650   static unsigned long len = 256;
1651
1652   if (!GetUserName (user, &len))
1653     return NULL;
1654   return user;
1655 }
1656 #endif /* __MINGW32__ */
1657
1658
1659 #if defined (HAVE_GETLOGIN) || defined (__MINGW32__)
1660 SCM_DEFINE (scm_getlogin, "getlogin", 0, 0, 0, 
1661             (void),
1662             "Return a string containing the name of the user logged in on\n"
1663             "the controlling terminal of the process, or @code{#f} if this\n"
1664             "information cannot be obtained.")
1665 #define FUNC_NAME s_scm_getlogin
1666 {
1667   char * p;
1668
1669   p = getlogin ();
1670   if (!p || !*p)
1671     return SCM_BOOL_F;
1672   return scm_from_locale_string (p);
1673 }
1674 #undef FUNC_NAME
1675 #endif /* HAVE_GETLOGIN */
1676
1677 #if HAVE_CUSERID
1678
1679 # if !HAVE_DECL_CUSERID
1680 extern char *cuserid (char *);
1681 # endif
1682
1683 SCM_DEFINE (scm_cuserid, "cuserid", 0, 0, 0, 
1684             (void),
1685             "Return a string containing a user name associated with the\n"
1686             "effective user id of the process.  Return @code{#f} if this\n"
1687             "information cannot be obtained.")
1688 #define FUNC_NAME s_scm_cuserid
1689 {
1690   char buf[L_cuserid];
1691   char * p;
1692
1693   p = cuserid (buf);
1694   if (!p || !*p)
1695     return SCM_BOOL_F;
1696   return scm_from_locale_string (p);
1697 }
1698 #undef FUNC_NAME
1699 #endif /* HAVE_CUSERID */
1700
1701 #if HAVE_GETPRIORITY
1702 SCM_DEFINE (scm_getpriority, "getpriority", 2, 0, 0, 
1703             (SCM which, SCM who),
1704             "Return the scheduling priority of the process, process group\n"
1705             "or user, as indicated by @var{which} and @var{who}. @var{which}\n"
1706             "is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP}\n"
1707             "or @code{PRIO_USER}, and @var{who} is interpreted relative to\n"
1708             "@var{which} (a process identifier for @code{PRIO_PROCESS},\n"
1709             "process group identifier for @code{PRIO_PGRP}, and a user\n"
1710             "identifier for @code{PRIO_USER}.  A zero value of @var{who}\n"
1711             "denotes the current process, process group, or user.  Return\n"
1712             "the highest priority (lowest numerical value) of any of the\n"
1713             "specified processes.")
1714 #define FUNC_NAME s_scm_getpriority
1715 {
1716   int cwhich, cwho, ret;
1717
1718   cwhich = scm_to_int (which);
1719   cwho = scm_to_int (who);
1720
1721   /* We have to clear errno and examine it later, because -1 is a
1722      legal return value for getpriority().  */
1723   errno = 0;
1724   ret = getpriority (cwhich, cwho);
1725   if (errno != 0)
1726     SCM_SYSERROR;
1727   return scm_from_int (ret);
1728 }
1729 #undef FUNC_NAME
1730 #endif /* HAVE_GETPRIORITY */
1731
1732 #if HAVE_SETPRIORITY
1733 SCM_DEFINE (scm_setpriority, "setpriority", 3, 0, 0, 
1734             (SCM which, SCM who, SCM prio),
1735             "Set the scheduling priority of the process, process group\n"
1736             "or user, as indicated by @var{which} and @var{who}. @var{which}\n"
1737             "is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP}\n"
1738             "or @code{PRIO_USER}, and @var{who} is interpreted relative to\n"
1739             "@var{which} (a process identifier for @code{PRIO_PROCESS},\n"
1740             "process group identifier for @code{PRIO_PGRP}, and a user\n"
1741             "identifier for @code{PRIO_USER}.  A zero value of @var{who}\n"
1742             "denotes the current process, process group, or user.\n"
1743             "@var{prio} is a value in the range -20 and 20, the default\n"
1744             "priority is 0; lower priorities cause more favorable\n"
1745             "scheduling.  Sets the priority of all of the specified\n"
1746             "processes.  Only the super-user may lower priorities.\n"
1747             "The return value is not specified.")
1748 #define FUNC_NAME s_scm_setpriority
1749 {
1750   int cwhich, cwho, cprio;
1751
1752   cwhich = scm_to_int (which);
1753   cwho = scm_to_int (who);
1754   cprio = scm_to_int (prio);
1755
1756   if (setpriority (cwhich, cwho, cprio) == -1)
1757     SCM_SYSERROR;
1758   return SCM_UNSPECIFIED;
1759 }
1760 #undef FUNC_NAME
1761 #endif /* HAVE_SETPRIORITY */
1762
1763 #if HAVE_GETPASS
1764 SCM_DEFINE (scm_getpass, "getpass", 1, 0, 0, 
1765             (SCM prompt),
1766             "Display @var{prompt} to the standard error output and read\n"
1767             "a password from @file{/dev/tty}.  If this file is not\n"
1768             "accessible, it reads from standard input.  The password may be\n"
1769             "up to 127 characters in length.  Additional characters and the\n"
1770             "terminating newline character are discarded.  While reading\n"
1771             "the password, echoing and the generation of signals by special\n"
1772             "characters is disabled.")
1773 #define FUNC_NAME s_scm_getpass
1774 {
1775   char * p;
1776   SCM passwd;
1777
1778   SCM_VALIDATE_STRING (1, prompt);
1779
1780   WITH_STRING (prompt, c_prompt, 
1781                p = getpass(c_prompt));
1782   passwd = scm_from_locale_string (p);
1783
1784   /* Clear out the password in the static buffer.  */
1785   memset (p, 0, strlen (p));
1786
1787   return passwd;
1788 }
1789 #undef FUNC_NAME
1790 #endif /* HAVE_GETPASS */
1791
1792 /* Wrapper function for flock() support under M$-Windows. */
1793 #ifdef __MINGW32__
1794 # include <io.h>
1795 # include <sys/locking.h>
1796 # include <errno.h>
1797 # ifndef _LK_UNLCK
1798    /* Current MinGW package fails to define this. *sigh* */
1799 #  define _LK_UNLCK 0
1800 # endif
1801 # define LOCK_EX 1
1802 # define LOCK_UN 2
1803 # define LOCK_SH 4
1804 # define LOCK_NB 8
1805
1806 static int flock (int fd, int operation)
1807 {
1808   long pos, len;
1809   int ret, err;
1810
1811   /* Disable invalid arguments. */
1812   if (((operation & (LOCK_EX | LOCK_SH)) == (LOCK_EX | LOCK_SH)) ||
1813       ((operation & (LOCK_EX | LOCK_UN)) == (LOCK_EX | LOCK_UN)) ||
1814       ((operation & (LOCK_SH | LOCK_UN)) == (LOCK_SH | LOCK_UN)))
1815     {
1816       errno = EINVAL;
1817       return -1;
1818     }
1819
1820   /* Determine mode of operation and discard unsupported ones. */
1821   if (operation == (LOCK_NB | LOCK_EX))
1822     operation = _LK_NBLCK;
1823   else if (operation & LOCK_UN)
1824     operation = _LK_UNLCK;
1825   else if (operation == LOCK_EX)
1826     operation = _LK_LOCK;
1827   else
1828     {
1829       errno = EINVAL;
1830       return -1;
1831     }
1832
1833   /* Save current file pointer and seek to beginning. */
1834   if ((pos = lseek (fd, 0, SEEK_CUR)) == -1 || (len = filelength (fd)) == -1)
1835     return -1;
1836   lseek (fd, 0L, SEEK_SET);
1837
1838   /* Deadlock if necessary. */
1839   do
1840     {
1841       ret = _locking (fd, operation, len);
1842     }
1843   while (ret == -1 && errno == EDEADLOCK);
1844
1845   /* Produce meaningful error message. */
1846   if (errno == EACCES && operation == _LK_NBLCK)
1847     err = EDEADLOCK;
1848   else
1849     err = errno;
1850
1851   /* Return to saved file position pointer. */
1852   lseek (fd, pos, SEEK_SET);
1853   errno = err;
1854   return ret;
1855 }
1856 #endif /* __MINGW32__ */
1857
1858 #if HAVE_FLOCK || defined (__MINGW32__)
1859
1860 #ifndef __MINGW32__
1861 # if !HAVE_DECL_FLOCK
1862 extern int flock (int, int);
1863 # endif
1864 #endif
1865
1866 SCM_DEFINE (scm_flock, "flock", 2, 0, 0, 
1867             (SCM file, SCM operation),
1868             "Apply or remove an advisory lock on an open file.\n"
1869             "@var{operation} specifies the action to be done:\n"
1870             "\n"
1871             "@defvar LOCK_SH\n"
1872             "Shared lock.  More than one process may hold a shared lock\n"
1873             "for a given file at a given time.\n"
1874             "@end defvar\n"
1875             "@defvar LOCK_EX\n"
1876             "Exclusive lock.  Only one process may hold an exclusive lock\n"
1877             "for a given file at a given time.\n"
1878             "@end defvar\n"
1879             "@defvar LOCK_UN\n"
1880             "Unlock the file.\n"
1881             "@end defvar\n"
1882             "@defvar LOCK_NB\n"
1883             "Don't block when locking.  This is combined with one of the\n"
1884             "other operations using @code{logior}.  If @code{flock} would\n"
1885             "block an @code{EWOULDBLOCK} error is thrown.\n"
1886             "@end defvar\n"
1887             "\n"
1888             "The return value is not specified. @var{file} may be an open\n"
1889             "file descriptor or an open file descriptor port.\n"
1890             "\n"
1891             "Note that @code{flock} does not lock files across NFS.")
1892 #define FUNC_NAME s_scm_flock
1893 {
1894   int fdes;
1895
1896   if (scm_is_integer (file))
1897     fdes = scm_to_int (file);
1898   else
1899     {
1900       SCM_VALIDATE_OPFPORT (2, file);
1901
1902       fdes = SCM_FPORT_FDES (file);
1903     }
1904   if (flock (fdes, scm_to_int (operation)) == -1)
1905     SCM_SYSERROR;
1906   return SCM_UNSPECIFIED;
1907 }
1908 #undef FUNC_NAME
1909 #endif /* HAVE_FLOCK */
1910
1911 #if HAVE_SETHOSTNAME
1912 SCM_DEFINE (scm_sethostname, "sethostname", 1, 0, 0, 
1913             (SCM name),
1914             "Set the host name of the current processor to @var{name}. May\n"
1915             "only be used by the superuser.  The return value is not\n"
1916             "specified.")
1917 #define FUNC_NAME s_scm_sethostname
1918 {
1919   int rv;
1920
1921   WITH_STRING (name, c_name,
1922                rv = sethostname (c_name, strlen(c_name)));
1923   if (rv == -1)
1924     SCM_SYSERROR;
1925   return SCM_UNSPECIFIED;
1926 }
1927 #undef FUNC_NAME
1928 #endif /* HAVE_SETHOSTNAME */
1929
1930
1931 #if HAVE_GETHOSTNAME
1932 SCM_DEFINE (scm_gethostname, "gethostname", 0, 0, 0, 
1933             (void),
1934             "Return the host name of the current processor.")
1935 #define FUNC_NAME s_scm_gethostname
1936 {
1937 #ifdef MAXHOSTNAMELEN
1938
1939   /* Various systems define MAXHOSTNAMELEN (including Solaris in fact).
1940    * On GNU/Linux this doesn't include the terminating '\0', hence "+ 1".  */
1941   const int len = MAXHOSTNAMELEN + 1;
1942   char *const p = scm_malloc (len);
1943   const int res = gethostname (p, len);
1944
1945   scm_dynwind_begin (0);
1946   scm_dynwind_unwind_handler (free, p, 0);
1947
1948 #else
1949
1950   /* Default 256 is for Solaris, under Linux ENAMETOOLONG is returned if not
1951    * large enough.  SUSv2 specifies 255 maximum too, apparently.  */
1952   int len = 256;
1953   int res;
1954   char *p;
1955
1956 #  if HAVE_SYSCONF && defined (_SC_HOST_NAME_MAX)
1957
1958   /* POSIX specifies the HOST_NAME_MAX system parameter for the max size,
1959    * which may reflect a particular kernel configuration.
1960    * Must watch out for this existing but giving -1, as happens for instance
1961    * in gnu/linux glibc 2.3.2.  */
1962   {
1963     const long int n = sysconf (_SC_HOST_NAME_MAX);
1964     if (n != -1L)
1965       len = n;
1966   }
1967
1968 #  endif
1969
1970   p = scm_malloc (len);
1971
1972   scm_dynwind_begin (0);
1973   scm_dynwind_unwind_handler (free, p, 0);
1974
1975   res = gethostname (p, len);
1976   while (res == -1 && errno == ENAMETOOLONG)
1977     {
1978       len *= 2;
1979
1980       /* scm_realloc may throw an exception.  */
1981       p = scm_realloc (p, len);
1982       res = gethostname (p, len);
1983     }
1984
1985 #endif
1986
1987   if (res == -1)
1988     {
1989       const int save_errno = errno;
1990
1991       /* No guile exceptions can occur before we have freed p's memory. */
1992       scm_dynwind_end ();
1993       free (p);
1994
1995       errno = save_errno;
1996       SCM_SYSERROR;
1997     }
1998   else
1999     {
2000       /* scm_from_locale_string may throw an exception.  */
2001       const SCM name = scm_from_locale_string (p);
2002
2003       /* No guile exceptions can occur before we have freed p's memory. */
2004       scm_dynwind_end ();
2005       free (p);
2006
2007       return name;
2008     }
2009 }
2010 #undef FUNC_NAME
2011 #endif /* HAVE_GETHOSTNAME */
2012
2013
2014 void 
2015 scm_init_posix ()
2016 {
2017   scm_add_feature ("posix");
2018 #ifdef HAVE_GETEUID
2019   scm_add_feature ("EIDs");
2020 #endif
2021 #ifdef WAIT_ANY
2022   scm_c_define ("WAIT_ANY", scm_from_int (WAIT_ANY));
2023 #endif
2024 #ifdef WAIT_MYPGRP
2025   scm_c_define ("WAIT_MYPGRP", scm_from_int (WAIT_MYPGRP));
2026 #endif
2027 #ifdef WNOHANG
2028   scm_c_define ("WNOHANG", scm_from_int (WNOHANG));
2029 #endif
2030 #ifdef WUNTRACED
2031   scm_c_define ("WUNTRACED", scm_from_int (WUNTRACED));
2032 #endif
2033
2034   /* access() symbols.  */
2035   scm_c_define ("R_OK", scm_from_int (R_OK));
2036   scm_c_define ("W_OK", scm_from_int (W_OK));
2037   scm_c_define ("X_OK", scm_from_int (X_OK));
2038   scm_c_define ("F_OK", scm_from_int (F_OK));
2039
2040 #ifdef LC_COLLATE
2041   scm_c_define ("LC_COLLATE", scm_from_int (LC_COLLATE));
2042 #endif
2043 #ifdef LC_CTYPE
2044   scm_c_define ("LC_CTYPE", scm_from_int (LC_CTYPE));
2045 #endif
2046 #ifdef LC_MONETARY
2047   scm_c_define ("LC_MONETARY", scm_from_int (LC_MONETARY));
2048 #endif
2049 #ifdef LC_NUMERIC
2050   scm_c_define ("LC_NUMERIC", scm_from_int (LC_NUMERIC));
2051 #endif
2052 #ifdef LC_TIME
2053   scm_c_define ("LC_TIME", scm_from_int (LC_TIME));
2054 #endif
2055 #ifdef LC_MESSAGES
2056   scm_c_define ("LC_MESSAGES", scm_from_int (LC_MESSAGES));
2057 #endif
2058 #ifdef LC_ALL
2059   scm_c_define ("LC_ALL", scm_from_int (LC_ALL));
2060 #endif
2061 #ifdef LC_PAPER
2062   scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
2063 #endif
2064 #ifdef LC_NAME
2065   scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
2066 #endif
2067 #ifdef LC_ADDRESS
2068   scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
2069 #endif
2070 #ifdef LC_TELEPHONE
2071   scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
2072 #endif
2073 #ifdef LC_MEASUREMENT
2074   scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
2075 #endif
2076 #ifdef LC_IDENTIFICATION
2077   scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
2078 #endif
2079 #ifdef PIPE_BUF
2080   scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));
2081 #endif
2082
2083 #ifdef PRIO_PROCESS
2084   scm_c_define ("PRIO_PROCESS", scm_from_int (PRIO_PROCESS));
2085 #endif
2086 #ifdef PRIO_PGRP
2087   scm_c_define ("PRIO_PGRP", scm_from_int (PRIO_PGRP));
2088 #endif
2089 #ifdef PRIO_USER
2090   scm_c_define ("PRIO_USER", scm_from_int (PRIO_USER));
2091 #endif
2092
2093 #ifdef LOCK_SH
2094   scm_c_define ("LOCK_SH", scm_from_int (LOCK_SH));
2095 #endif
2096 #ifdef LOCK_EX
2097   scm_c_define ("LOCK_EX", scm_from_int (LOCK_EX));
2098 #endif
2099 #ifdef LOCK_UN
2100   scm_c_define ("LOCK_UN", scm_from_int (LOCK_UN));
2101 #endif
2102 #ifdef LOCK_NB
2103   scm_c_define ("LOCK_NB", scm_from_int (LOCK_NB));
2104 #endif
2105
2106 #include "libguile/cpp_sig_symbols.c"
2107 #include "libguile/posix.x"
2108 }
2109
2110 /*
2111   Local Variables:
2112   c-file-style: "gnu"
2113   End:
2114 */