* validate.h
[bpt/guile.git] / libguile / posix.c
index 7b8ed97..83e8bac 100644 (file)
@@ -1,4 +1,4 @@
-/*     Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * If you write modifications of your own for GUILE, it is your choice
  * whether to permit this exception to apply to your modifications.
  * If you do not wish that, delete this exception notice.  */
+
+/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
+   gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
+
 \f
 
+/* Make GNU/Linux libc declare everything it has. */
+#define _GNU_SOURCE
+
 #include <stdio.h>
-#include "_scm.h"
-#include "fports.h"
-#include "scmsigs.h"
-#include "feature.h"
+#include <errno.h>
+
+#include "libguile/_scm.h"
+#include "libguile/fports.h"
+#include "libguile/scmsigs.h"
+#include "libguile/feature.h"
+#include "libguile/strings.h"
+#include "libguile/vectors.h"
 
-#include "posix.h"
+#include "libguile/validate.h"
+#include "libguile/posix.h"
 \f
 
 #ifdef HAVE_STRING_H
@@ -93,7 +105,6 @@ extern char *ttyname();
 
 #include <signal.h>
 
-extern FILE *popen ();
 extern char ** environ;
 
 #include <grp.h>
@@ -120,6 +131,18 @@ extern char ** environ;
 #include <locale.h>
 #endif
 
+#if HAVE_LIBCRYPT && HAVE_CRYPT_H
+#  include <crypt.h>
+#endif
+
+#if HAVE_SYS_RESOURCE_H
+#  include <sys/resource.h>
+#endif
+
+#if HAVE_SYS_FILE_H
+# include <sys/file.h>
+#endif
+
 /* Some Unix systems don't define these.  CPP hair is dangerous, but
    this seems safe enough... */
 #ifndef R_OK
@@ -161,117 +184,103 @@ extern char ** environ;
 SCM_SYMBOL (sym_read_pipe, "read pipe");
 SCM_SYMBOL (sym_write_pipe, "write pipe");
 
-SCM_PROC (s_pipe, "pipe", 0, 0, 0, scm_pipe);
-
-SCM 
-scm_pipe ()
+SCM_DEFINE (scm_pipe, "pipe", 0, 0, 0,
+            (),
+           "Return a newly created pipe: a pair of ports which are linked\n"
+           "together on the local machine.  The @emph{car} is the input\n"
+           "port and the @emph{cdr} is the output port.  Data written (and\n"
+           "flushed) to the output port can be read from the input port.\n"
+           "Pipes are commonly used for communication with a newly forked\n"
+           "child process.  The need to flush the output port can be\n"
+           "avoided by making it unbuffered using @code{setvbuf}.\n"
+           "\n"
+           "Writes occur atomically provided the size of the data in bytes\n"
+           "is not greater than the value of @code{PIPE_BUF}.  Note that\n"
+           "the output port is likely to block if too much data (typically\n"
+           "equal to @code{PIPE_BUF}) has been written but not yet read\n"
+           "from the input port.")
+#define FUNC_NAME s_scm_pipe
 {
   int fd[2], rv;
-  FILE *f_rd, *f_wt;
   SCM p_rd, p_wt;
 
   rv = pipe (fd);
   if (rv)
-    scm_syserror (s_pipe);
-  f_rd = fdopen (fd[0], "r");
-  if (!f_rd)
-    {
-      SCM_SYSCALL (close (fd[0]));
-      SCM_SYSCALL (close (fd[1]));
-      scm_syserror (s_pipe);
-    }
-  f_wt = fdopen (fd[1], "w");
-  if (!f_wt)
-    {
-      int en;
-      en = errno;
-      fclose (f_rd);
-      SCM_SYSCALL (close (fd[1]));
-      errno = en;
-      scm_syserror (s_pipe);
-    }
-
-  p_rd = scm_stdio_to_port (f_rd, "r", sym_read_pipe);
-  p_wt = scm_stdio_to_port (f_wt, "w", sym_write_pipe);
-
-  SCM_ALLOW_INTS;
+    SCM_SYSERROR;
+  
+  p_rd = scm_fdes_to_port (fd[0], "r", sym_read_pipe);
+  p_wt = scm_fdes_to_port (fd[1], "w", sym_write_pipe);
   return scm_cons (p_rd, p_wt);
 }
+#undef FUNC_NAME
 
 
 #ifdef HAVE_GETGROUPS
-SCM_PROC (s_getgroups, "getgroups", 0, 0, 0, scm_getgroups);
-
-SCM
-scm_getgroups()
+SCM_DEFINE (scm_getgroups, "getgroups", 0, 0, 0,
+            (),
+           "Return a vector of integers representing the current\n"
+           "supplimentary group IDs.")
+#define FUNC_NAME s_scm_getgroups
 {
-  SCM grps, ans;
-  int ngroups = getgroups (0, NULL);
-  if (!ngroups)
-    scm_syserror (s_getgroups);
-  SCM_NEWCELL(grps);
-  SCM_DEFER_INTS;
-  {
-    GETGROUPS_T *groups;
-    int val;
-
-    groups = (GETGROUPS_T *) scm_must_malloc(ngroups * sizeof(GETGROUPS_T),
-                                            s_getgroups);
-    val = getgroups(ngroups, groups);
-    if (val < 0)
-      {
-       scm_must_free((char *)groups);
-       scm_syserror (s_getgroups);
-      }
-    SCM_SETCHARS(grps, groups);        /* set up grps as a GC protect */
-    SCM_SETLENGTH(grps, 0L + ngroups * sizeof(GETGROUPS_T), scm_tc7_string);
-    SCM_ALLOW_INTS;
-    ans = scm_make_vector (SCM_MAKINUM(ngroups), SCM_UNDEFINED);
-    while (--ngroups >= 0) SCM_VELTS(ans)[ngroups] = SCM_MAKINUM(groups[ngroups]);
-    SCM_SETCHARS(grps, groups);        /* to make sure grps stays around. */
-    return ans;
-  }
-}  
-#endif
+  SCM ans;
+  int ngroups;
+  size_t size;
+  GETGROUPS_T *groups;
+
+  ngroups = getgroups (0, NULL);
+  if (ngroups <= 0)
+    SCM_SYSERROR;
+
+  size = ngroups * sizeof (GETGROUPS_T);
+  groups = scm_must_malloc (size, FUNC_NAME);
+  getgroups (ngroups, groups);
+
+  ans = scm_c_make_vector (ngroups, SCM_UNDEFINED);
+  while (--ngroups >= 0) 
+    SCM_VELTS (ans) [ngroups] = SCM_MAKINUM (groups [ngroups]);
 
+  scm_must_free (groups);
+  scm_done_free (size);
 
-SCM_PROC (s_getpwuid, "getpw", 0, 1, 0, scm_getpwuid);
+  return ans;
+}
+#undef FUNC_NAME  
+#endif
 
-SCM 
-scm_getpwuid (user)
-     SCM user;
+
+SCM_DEFINE (scm_getpwuid, "getpw", 0, 1, 0,
+            (SCM user),
+           "Look up an entry in the user database.  @var{obj} can be an integer,\n"
+           "a string, or omitted, giving the behaviour of getpwuid, getpwnam\n"
+           "or getpwent respectively.")
+#define FUNC_NAME s_scm_getpwuid
 {
   SCM result;
   struct passwd *entry;
   SCM *ve;
 
-  result = scm_make_vector (SCM_MAKINUM (7), SCM_UNSPECIFIED);
+  result = scm_c_make_vector (7, SCM_UNSPECIFIED);
   ve = SCM_VELTS (result);
   if (SCM_UNBNDP (user) || SCM_FALSEP (user))
     {
-      SCM_DEFER_INTS;
       SCM_SYSCALL (entry = getpwent ());
       if (! entry)
        {
-         SCM_ALLOW_INTS;
          return SCM_BOOL_F;
        }
     }
   else if (SCM_INUMP (user))
     {
-      SCM_DEFER_INTS;
       entry = getpwuid (SCM_INUM (user));
     }
   else
     {
-      SCM_ASSERT (SCM_NIMP (user) && SCM_ROSTRINGP (user), user, SCM_ARG1, s_getpwuid);
-      if (SCM_SUBSTRP (user))
-       user = scm_makfromstr (SCM_ROCHARS (user), SCM_ROLENGTH (user), 0);
-      SCM_DEFER_INTS;
-      entry = getpwnam (SCM_ROCHARS (user));
+      SCM_VALIDATE_STRING (1, user);
+      SCM_STRING_COERCE_0TERMINATION_X (user);
+      entry = getpwnam (SCM_STRING_CHARS (user));
     }
   if (!entry)
-    scm_misc_error (s_getpwuid, "entry not found", SCM_EOL);
+    SCM_MISC_ERROR ("entry not found", SCM_EOL);
 
   ve[0] = scm_makfrom0str (entry->pw_name);
   ve[1] = scm_makfrom0str (entry->pw_passwd);
@@ -286,17 +295,18 @@ scm_getpwuid (user)
     ve[6] = scm_makfrom0str ("");
   else
     ve[6] = scm_makfrom0str (entry->pw_shell);
-  SCM_ALLOW_INTS;
   return result;
 }
+#undef FUNC_NAME
 
 
 #ifdef HAVE_SETPWENT
-SCM_PROC (s_setpwent, "setpw", 0, 1, 0, scm_setpwent);
-
-SCM 
-scm_setpwent (arg)
-     SCM arg;
+SCM_DEFINE (scm_setpwent, "setpw", 0, 1, 0,
+            (SCM arg),
+           "If called with a true argument, initialize or reset the password data\n"
+           "stream.  Otherwise, close the stream.  The @code{setpwent} and\n"
+           "@code{endpwent} procedures are implemented on top of this.")
+#define FUNC_NAME s_scm_setpwent
 {
   if (SCM_UNBNDP (arg) || SCM_FALSEP (arg))
     endpwent ();
@@ -304,29 +314,29 @@ scm_setpwent (arg)
     setpwent ();
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
 #endif
 
 
 
 /* Combines getgrgid and getgrnam.  */
-SCM_PROC (s_getgrgid, "getgr", 0, 1, 0, scm_getgrgid);
-
-SCM 
-scm_getgrgid (name)
-     SCM name;
+SCM_DEFINE (scm_getgrgid, "getgr", 0, 1, 0,
+            (SCM name),
+           "Look up an entry in the group database.  @var{obj} can be an integer,\n"
+           "a string, or omitted, giving the behaviour of getgrgid, getgrnam\n"
+           "or getgrent respectively.")
+#define FUNC_NAME s_scm_getgrgid
 {
   SCM result;
   struct group *entry;
   SCM *ve;
-  result = scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED);
+  result = scm_c_make_vector (4, SCM_UNSPECIFIED);
   ve = SCM_VELTS (result);
-  SCM_DEFER_INTS;
-  if (SCM_UNBNDP (name) || (name == SCM_BOOL_F))
+  if (SCM_UNBNDP (name) || SCM_FALSEP (name))
     {
       SCM_SYSCALL (entry = getgrent ());
       if (! entry)
        {
-         SCM_ALLOW_INTS;
          return SCM_BOOL_F;
        }
     }
@@ -334,29 +344,29 @@ scm_getgrgid (name)
     SCM_SYSCALL (entry = getgrgid (SCM_INUM (name)));
   else
     {
-      SCM_ASSERT (SCM_NIMP (name) && SCM_ROSTRINGP (name), name, SCM_ARG1,
-                 s_getgrgid);
-      SCM_COERCE_SUBSTR (name);
-      SCM_SYSCALL (entry = getgrnam (SCM_ROCHARS (name)));
+      SCM_VALIDATE_STRING (1, name);
+      SCM_STRING_COERCE_0TERMINATION_X (name);
+      SCM_SYSCALL (entry = getgrnam (SCM_STRING_CHARS (name)));
     }
   if (!entry)
-    scm_syserror (s_getgrgid);
+    SCM_SYSERROR;
 
   ve[0] = scm_makfrom0str (entry->gr_name);
   ve[1] = scm_makfrom0str (entry->gr_passwd);
   ve[2] = scm_ulong2num ((unsigned long) entry->gr_gid);
   ve[3] = scm_makfromstrs (-1, entry->gr_mem);
-  SCM_ALLOW_INTS;
   return result;
 }
+#undef FUNC_NAME
 
 
 
-SCM_PROC (s_setgrent, "setgr", 0, 1, 0, scm_setgrent);
-
-SCM 
-scm_setgrent (arg)
-     SCM arg;
+SCM_DEFINE (scm_setgrent, "setgr", 0, 1, 0, 
+            (SCM arg),
+           "If called with a true argument, initialize or reset the group data\n"
+           "stream.  Otherwise, close the stream.  The @code{setgrent} and\n"
+           "@code{endgrent} procedures are implemented on top of this.")
+#define FUNC_NAME s_scm_setgrent
 {
   if (SCM_UNBNDP (arg) || SCM_FALSEP (arg))
     endgrent ();
@@ -364,65 +374,114 @@ scm_setgrent (arg)
     setgrent ();
   return SCM_UNSPECIFIED;
 }
-
-
-
-SCM_PROC (s_kill, "kill", 2, 0, 0, scm_kill);
-
-SCM 
-scm_kill (pid, sig)
-     SCM pid;
-     SCM sig;
+#undef FUNC_NAME
+
+
+
+SCM_DEFINE (scm_kill, "kill", 2, 0, 0,
+            (SCM pid, SCM sig),
+           "Sends a signal to the specified process or group of processes.\n\n"
+           "@var{pid} specifies the processes to which the signal is sent:\n\n"
+           "@table @r\n"
+           "@item @var{pid} greater than 0\n"
+           "The process whose identifier is @var{pid}.\n"
+           "@item @var{pid} equal to 0\n"
+           "All processes in the current process group.\n"
+           "@item @var{pid} less than -1\n"
+           "The process group whose identifier is -@var{pid}\n"
+           "@item @var{pid} equal to -1\n"
+           "If the process is privileged, all processes except for some special\n"
+           "system processes.  Otherwise, all processes with the current effective\n"
+           "user ID.\n"
+           "@end table\n\n"
+           "@var{sig} should be specified using a variable corresponding to\n"
+           "the Unix symbolic name, e.g.,\n\n"
+           "@defvar SIGHUP\n"
+           "Hang-up signal.\n"
+           "@end defvar\n\n"
+           "@defvar SIGINT\n"
+           "Interrupt signal.\n"
+           "@end defvar")
+#define FUNC_NAME s_scm_kill
 {
-  SCM_ASSERT (SCM_INUMP (pid), pid, SCM_ARG1, s_kill);
-  SCM_ASSERT (SCM_INUMP (sig), sig, SCM_ARG2, s_kill);
+  SCM_VALIDATE_INUM (1,pid);
+  SCM_VALIDATE_INUM (2,sig);
   /* Signal values are interned in scm_init_posix().  */
   if (kill ((int) SCM_INUM (pid), (int) SCM_INUM (sig)) != 0)
-    scm_syserror (s_kill);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
 
-
-
-SCM_PROC (s_waitpid, "waitpid", 1, 1, 0, scm_waitpid);
-
-SCM 
-scm_waitpid (pid, options)
-     SCM pid;
-     SCM options;
-{
 #ifdef HAVE_WAITPID
+SCM_DEFINE (scm_waitpid, "waitpid", 1, 1, 0,
+            (SCM pid, SCM options),
+           "This procedure collects status information from a child process which\n"
+           "has terminated or (optionally) stopped.  Normally it will\n"
+           "suspend the calling process until this can be done.  If more than one\n"
+           "child process is eligible then one will be chosen by the operating system.\n\n"
+           "The value of @var{pid} determines the behaviour:\n\n"
+           "@table @r\n"
+           "@item @var{pid} greater than 0\n"
+           "Request status information from the specified child process.\n"
+           "@item @var{pid} equal to -1 or WAIT_ANY\n"
+           "Request status information for any child process.\n"
+           "@item @var{pid} equal to 0 or WAIT_MYPGRP\n"
+           "Request status information for any child process in the current process\n"
+           "group.\n"
+           "@item @var{pid} less than -1\n"
+           "Request status information for any child process whose process group ID\n"
+           "is -@var{PID}.\n"
+           "@end table\n\n"
+           "The @var{options} argument, if supplied, should be the bitwise OR of the\n"
+           "values of zero or more of the following variables:\n\n"
+           "@defvar WNOHANG\n"
+           "Return immediately even if there are no child processes to be collected.\n"
+           "@end defvar\n\n"
+           "@defvar WUNTRACED\n"
+           "Report status information for stopped processes as well as terminated\n"
+           "processes.\n"
+           "@end defvar\n\n"
+           "The return value is a pair containing:\n\n"
+           "@enumerate\n"
+           "@item\n"
+           "The process ID of the child process, or 0 if @code{WNOHANG} was\n"
+           "specified and no process was collected.\n"
+           "@item\n"
+           "The integer status value.\n"
+           "@end enumerate")
+#define FUNC_NAME s_scm_waitpid
+{
   int i;
   int status;
   int ioptions;
-  SCM_ASSERT (SCM_INUMP (pid), pid, SCM_ARG1, s_waitpid);
+  SCM_VALIDATE_INUM (1,pid);
   if (SCM_UNBNDP (options))
     ioptions = 0;
   else
     {
-      SCM_ASSERT (SCM_INUMP (options), options, SCM_ARG2, s_waitpid);
+      SCM_VALIDATE_INUM (2,options);
       /* Flags are interned in scm_init_posix.  */
       ioptions = SCM_INUM (options);
     }
   SCM_SYSCALL (i = waitpid (SCM_INUM (pid), &status, ioptions));
   if (i == -1)
-    scm_syserror (s_waitpid);
+    SCM_SYSERROR;
   return scm_cons (SCM_MAKINUM (0L + i), SCM_MAKINUM (0L + status));
-#else
-  scm_sysmissing (s_waitpid);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
 }
-
-SCM_PROC (s_status_exit_val, "status:exit-val", 1, 0, 0, scm_status_exit_val);
-SCM
-scm_status_exit_val (status)
-     SCM status;
+#undef FUNC_NAME
+#endif /* HAVE_WAITPID */
+
+SCM_DEFINE (scm_status_exit_val, "status:exit-val", 1, 0, 0, 
+            (SCM status),
+           "Return the exit status value, as would be set if a process\n"
+           "ended normally through a call to @code{exit} or @code{_exit},\n"
+           "if any, otherwise @code{#f}.")
+#define FUNC_NAME s_scm_status_exit_val
 {
   int lstatus;
 
-  SCM_ASSERT (SCM_INUMP (status), status, SCM_ARG1,s_status_exit_val);
+  SCM_VALIDATE_INUM (1,status);
 
   /* On Ultrix, the WIF... macros assume their argument is an lvalue;
      go figure.  SCM_INUM does not yield an lvalue.  */
@@ -432,15 +491,17 @@ scm_status_exit_val (status)
   else
     return SCM_BOOL_F;
 }
+#undef FUNC_NAME
 
-SCM_PROC (s_status_term_sig, "status:term-sig", 1, 0, 0, scm_status_term_sig);
-SCM
-scm_status_term_sig (status)
-     SCM status;
+SCM_DEFINE (scm_status_term_sig, "status:term-sig", 1, 0, 0, 
+            (SCM status),
+           "Return the signal number which terminated the process, if any,\n"
+           "otherwise @code{#f}.")
+#define FUNC_NAME s_scm_status_term_sig
 {
   int lstatus;
 
-  SCM_ASSERT (SCM_INUMP (status), status, SCM_ARG1,s_status_term_sig);
+  SCM_VALIDATE_INUM (1,status);
 
   lstatus = SCM_INUM (status);
   if (WIFSIGNALED (lstatus))
@@ -448,15 +509,17 @@ scm_status_term_sig (status)
   else
     return SCM_BOOL_F;
 }
+#undef FUNC_NAME
 
-SCM_PROC (s_status_stop_sig, "status:stop-sig", 1, 0, 0, scm_status_stop_sig);
-SCM
-scm_status_stop_sig (status)
-     SCM status;
+SCM_DEFINE (scm_status_stop_sig, "status:stop-sig", 1, 0, 0, 
+            (SCM status),
+           "Return the signal number which stopped the process, if any,\n"
+           "otherwise @code{#f}.")
+#define FUNC_NAME s_scm_status_stop_sig
 {
   int lstatus;
 
-  SCM_ASSERT (SCM_INUMP (status), status, SCM_ARG1,s_status_stop_sig);
+  SCM_VALIDATE_INUM (1,status);
 
   lstatus = SCM_INUM (status);
   if (WIFSTOPPED (lstatus))
@@ -464,41 +527,49 @@ scm_status_stop_sig (status)
   else
     return SCM_BOOL_F;
 }
+#undef FUNC_NAME
 
-SCM_PROC (s_getppid, "getppid", 0, 0, 0, scm_getppid);
-
-SCM 
-scm_getppid ()
+SCM_DEFINE (scm_getppid, "getppid", 0, 0, 0,
+            (),
+           "Return an integer representing the process ID of the parent\n"
+           "process.")
+#define FUNC_NAME s_scm_getppid
 {
   return SCM_MAKINUM (0L + getppid ());
 }
+#undef FUNC_NAME
 
 
 
-SCM_PROC (s_getuid, "getuid", 0, 0, 0, scm_getuid);
-
-SCM 
-scm_getuid ()
+SCM_DEFINE (scm_getuid, "getuid", 0, 0, 0,
+            (),
+           "Return an integer representing the current real user ID.")
+#define FUNC_NAME s_scm_getuid
 {
   return SCM_MAKINUM (0L + getuid ());
 }
+#undef FUNC_NAME
 
 
 
-SCM_PROC (s_getgid, "getgid", 0, 0, 0, scm_getgid);
-
-SCM 
-scm_getgid ()
+SCM_DEFINE (scm_getgid, "getgid", 0, 0, 0,
+            (),
+           "Return an integer representing the current real group ID.")
+#define FUNC_NAME s_scm_getgid
 {
   return SCM_MAKINUM (0L + getgid ());
 }
+#undef FUNC_NAME
 
 
 
-SCM_PROC (s_geteuid, "geteuid", 0, 0, 0, scm_geteuid);
-
-SCM 
-scm_geteuid ()
+SCM_DEFINE (scm_geteuid, "geteuid", 0, 0, 0,
+            (),
+           "Return an integer representing the current effective user ID.\n"
+           "If the system does not support effective IDs, then the real ID\n"
+           "is returned.  @code{(feature? 'EIDs)} reports whether the\n"
+           "system supports effective IDs.")
+#define FUNC_NAME s_scm_geteuid
 {
 #ifdef HAVE_GETEUID
   return SCM_MAKINUM (0L + geteuid ());
@@ -506,13 +577,17 @@ scm_geteuid ()
   return SCM_MAKINUM (0L + getuid ());
 #endif
 }
+#undef FUNC_NAME
 
 
 
-SCM_PROC (s_getegid, "getegid", 0, 0, 0, scm_getegid);
-
-SCM 
-scm_getegid ()
+SCM_DEFINE (scm_getegid, "getegid", 0, 0, 0,
+            (),
+           "Return an integer representing the current effective group ID.\n"
+           "If the system does not support effective IDs, then the real ID\n"
+           "is returned.  @code{(feature? 'EIDs)} reports whether the\n"
+           "system supports effective IDs.")
+#define FUNC_NAME s_scm_getegid
 {
 #ifdef HAVE_GETEUID
   return SCM_MAKINUM (0L + getegid ());
@@ -520,356 +595,387 @@ scm_getegid ()
   return SCM_MAKINUM (0L + getgid ());
 #endif
 }
+#undef FUNC_NAME
 
 
-SCM_PROC (s_setuid, "setuid", 1, 0, 0, scm_setuid);
-
-SCM 
-scm_setuid (id)
-     SCM id;
+SCM_DEFINE (scm_setuid, "setuid", 1, 0, 0, 
+            (SCM id),
+           "Sets both the real and effective user IDs to the integer @var{id}, provided\n"
+           "the process has appropriate privileges.\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_setuid
 {
-  SCM_ASSERT (SCM_INUMP (id), id, SCM_ARG1, s_setuid);
+  SCM_VALIDATE_INUM (1,id);
   if (setuid (SCM_INUM (id)) != 0)
-    scm_syserror (s_setuid);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
 }
-
-SCM_PROC (s_setgid, "setgid", 1, 0, 0, scm_setgid);
-
-SCM 
-scm_setgid (id)
-     SCM id;
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_setgid, "setgid", 1, 0, 0, 
+            (SCM id),
+           "Sets both the real and effective group IDs to the integer @var{id}, provided\n"
+           "the process has appropriate privileges.\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_setgid
 {
-  SCM_ASSERT (SCM_INUMP (id), id, SCM_ARG1, s_setgid);
+  SCM_VALIDATE_INUM (1,id);
   if (setgid (SCM_INUM (id)) != 0)
-    scm_syserror (s_setgid);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
 }
-
-SCM_PROC (s_seteuid, "seteuid", 1, 0, 0, scm_seteuid);
-
-SCM 
-scm_seteuid (id)
-     SCM id;
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_seteuid, "seteuid", 1, 0, 0, 
+            (SCM id),
+           "Sets the effective user ID to the integer @var{id}, provided the process\n"
+           "has appropriate privileges.  If effective IDs are not supported, the\n"
+           "real ID is set instead -- @code{(feature? 'EIDs)} reports whether the\n"
+           "system supports effective IDs.\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_seteuid
 {
   int rv;
 
-  SCM_ASSERT (SCM_INUMP (id), id, SCM_ARG1, s_seteuid);
+  SCM_VALIDATE_INUM (1,id);
 #ifdef HAVE_SETEUID
   rv = seteuid (SCM_INUM (id));
 #else
   rv = setuid (SCM_INUM (id));
 #endif
   if (rv != 0)
-    scm_syserror (s_seteuid);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
 
 #ifdef HAVE_SETEGID
-SCM_PROC (s_setegid, "setegid", 1, 0, 0, scm_setegid);
-
-SCM 
-scm_setegid (id)
-     SCM id;
+SCM_DEFINE (scm_setegid, "setegid", 1, 0, 0, 
+            (SCM id),
+           "Sets the effective group ID to the integer @var{id}, provided the process\n"
+           "has appropriate privileges.  If effective IDs are not supported, the\n"
+           "real ID is set instead -- @code{(feature? 'EIDs)} reports whether the\n"
+           "system supports effective IDs.\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_setegid
 {
   int rv;
 
-  SCM_ASSERT (SCM_INUMP (id), id, SCM_ARG1, s_setegid);
+  SCM_VALIDATE_INUM (1,id);
 #ifdef HAVE_SETEUID
   rv = setegid (SCM_INUM (id));
 #else
   rv = setgid (SCM_INUM (id));
 #endif
   if (rv != 0)
-    scm_syserror (s_setegid);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
     
 }
+#undef FUNC_NAME
 #endif
 
-SCM_PROC (s_getpgrp, "getpgrp", 0, 0, 0, scm_getpgrp);
-SCM 
-scm_getpgrp ()
+SCM_DEFINE (scm_getpgrp, "getpgrp", 0, 0, 0,
+            (),
+           "Return an integer representing the current process group ID.\n"
+           "This is the POSIX definition, not BSD.")
+#define FUNC_NAME s_scm_getpgrp
 {
   int (*fn)();
   fn = (int (*) ()) getpgrp;
   return SCM_MAKINUM (fn (0));
 }
+#undef FUNC_NAME
 
-SCM_PROC (s_setpgid, "setpgid", 2, 0, 0, scm_setpgid);
-SCM 
-scm_setpgid (pid, pgid)
-     SCM pid, pgid;
-{
 #ifdef HAVE_SETPGID
-  SCM_ASSERT (SCM_INUMP (pid), pid, SCM_ARG1, s_setpgid);
-  SCM_ASSERT (SCM_INUMP (pgid), pgid, SCM_ARG2, s_setpgid);
+SCM_DEFINE (scm_setpgid, "setpgid", 2, 0, 0, 
+            (SCM pid, SCM pgid),
+           "Move the process @var{pid} into the process group @var{pgid}.  @var{pid} or\n"
+           "@var{pgid} must be integers: they can be zero to indicate the ID of the\n"
+           "current process.\n"
+           "Fails on systems that do not support job control.\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_setpgid
+{
+  SCM_VALIDATE_INUM (1,pid);
+  SCM_VALIDATE_INUM (2,pgid);
   /* FIXME(?): may be known as setpgrp.  */
   if (setpgid (SCM_INUM (pid), SCM_INUM (pgid)) != 0)
-    scm_syserror (s_setpgid);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
-#else
-  scm_sysmissing (s_setpgid);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
 }
+#undef FUNC_NAME
+#endif /* HAVE_SETPGID */
 
-SCM_PROC (s_setsid, "setsid", 0, 0, 0, scm_setsid);
-SCM 
-scm_setsid ()
-{
 #ifdef HAVE_SETSID
+SCM_DEFINE (scm_setsid, "setsid", 0, 0, 0,
+            (),
+           "Creates a new session.  The current process becomes the session leader\n"
+           "and is put in a new process group.  The process will be detached\n"
+           "from its controlling terminal if it has one.\n"
+           "The return value is an integer representing the new process group ID.")
+#define FUNC_NAME s_scm_setsid
+{
   pid_t sid = setsid ();
   if (sid == -1)
-    scm_syserror (s_setsid);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
-#else
-  scm_sysmissing (s_setsid);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
 }
-
-SCM_PROC (s_ttyname, "ttyname", 1, 0, 0, scm_ttyname);
-
-SCM 
-scm_ttyname (port)
-     SCM port;
+#undef FUNC_NAME
+#endif /* HAVE_SETSID */
+
+SCM_DEFINE (scm_ttyname, "ttyname", 1, 0, 0, 
+            (SCM port),
+           "Return a string with the name of the serial terminal device\n"
+           "underlying @var{port}.")
+#define FUNC_NAME s_scm_ttyname
 {
   char *ans;
   int fd;
 
   port = SCM_COERCE_OUTPORT (port);
-  SCM_ASSERT (SCM_NIMP (port) && SCM_OPPORTP (port), port, SCM_ARG1, s_ttyname);
-  if (scm_tc16_fport != SCM_TYP16 (port))
+  SCM_VALIDATE_OPPORT (1,port);
+  if (!SCM_FPORTP (port))
     return SCM_BOOL_F;
-  fd = fileno ((FILE *)SCM_STREAM (port));
-  if (fd == -1)
-    scm_syserror (s_ttyname);
+  fd = SCM_FPORT_FDES (port);
   SCM_SYSCALL (ans = ttyname (fd));
   if (!ans)
-    scm_syserror (s_ttyname);
+    SCM_SYSERROR;
   /* ans could be overwritten by another call to ttyname */
   return (scm_makfrom0str (ans));
 }
+#undef FUNC_NAME
 
-
-SCM_PROC (s_ctermid, "ctermid", 0, 0, 0, scm_ctermid);
-SCM 
-scm_ctermid ()
-{
 #ifdef HAVE_CTERMID
+SCM_DEFINE (scm_ctermid, "ctermid", 0, 0, 0,
+            (),
+           "Return a string containing the file name of the controlling\n"
+           "terminal for the current process.")
+#define FUNC_NAME s_scm_ctermid
+{
   char *result = ctermid (NULL);
   if (*result == '\0')
-    scm_syserror (s_ctermid);
+    SCM_SYSERROR;
   return scm_makfrom0str (result);
-#else
-  scm_sysmissing (s_ctermid);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
 }
+#undef FUNC_NAME
+#endif /* HAVE_CTERMID */
 
-SCM_PROC (s_tcgetpgrp, "tcgetpgrp", 1, 0, 0, scm_tcgetpgrp);
-SCM 
-scm_tcgetpgrp (port)
-     SCM port;
-{
 #ifdef HAVE_TCGETPGRP
+SCM_DEFINE (scm_tcgetpgrp, "tcgetpgrp", 1, 0, 0, 
+            (SCM port),
+           "Return the process group ID of the foreground process group\n"
+           "associated with the terminal open on the file descriptor\n"
+           "underlying @var{port}.\n"
+           "\n"
+           "If there is no foreground process group, the return value is a\n"
+           "number greater than 1 that does not match the process group ID\n"
+           "of any existing process group.  This can happen if all of the\n"
+           "processes in the job that was formerly the foreground job have\n"
+           "terminated, and no other job has yet been moved into the\n"
+           "foreground.")
+#define FUNC_NAME s_scm_tcgetpgrp
+{
   int fd;
   pid_t pgid;
 
   port = SCM_COERCE_OUTPORT (port);
 
-  SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_tcgetpgrp);
-  fd = fileno ((FILE *)SCM_STREAM (port));
-  if (fd == -1 || (pgid = tcgetpgrp (fd)) == -1)
-    scm_syserror (s_tcgetpgrp);
+  SCM_VALIDATE_OPFPORT (1,port);
+  fd = SCM_FPORT_FDES (port);
+  if ((pgid = tcgetpgrp (fd)) == -1)
+    SCM_SYSERROR;
   return SCM_MAKINUM (pgid);
-#else
-  scm_sysmissing (s_tcgetpgrp);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
-}    
+}
+#undef FUNC_NAME    
+#endif /* HAVE_TCGETPGRP */
 
-SCM_PROC (s_tcsetpgrp, "tcsetpgrp", 2, 0, 0, scm_tcsetpgrp);
-SCM 
-scm_tcsetpgrp (port, pgid)
-     SCM port, pgid;
-{
 #ifdef HAVE_TCSETPGRP
+SCM_DEFINE (scm_tcsetpgrp, "tcsetpgrp", 2, 0, 0,
+            (SCM port, SCM pgid),
+           "Set the foreground process group ID for the terminal used by the file\n"
+           "descriptor underlying @var{port} to the integer @var{pgid}.\n"
+           "The calling process\n"
+           "must be a member of the same session as @var{pgid} and must have the same\n"
+           "controlling terminal.  The return value is unspecified.")
+#define FUNC_NAME s_scm_tcsetpgrp
+{
   int fd;
 
   port = SCM_COERCE_OUTPORT (port);
 
-  SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_tcsetpgrp);
-  SCM_ASSERT (SCM_INUMP (pgid), pgid, SCM_ARG2, s_tcsetpgrp);
-  fd = fileno ((FILE *)SCM_STREAM (port));
-  if (fd == -1 || tcsetpgrp (fd, SCM_INUM (pgid)) == -1)
-    scm_syserror (s_tcsetpgrp);
+  SCM_VALIDATE_OPFPORT (1,port);
+  SCM_VALIDATE_INUM (2,pgid);
+  fd = SCM_FPORT_FDES (port);
+  if (tcsetpgrp (fd, SCM_INUM (pgid)) == -1)
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
-#else
-  scm_sysmissing (s_tcsetpgrp);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
-}    
+}
+#undef FUNC_NAME
+#endif /* HAVE_TCSETPGRP */
 
-/* Copy exec args from an SCM vector into a new C array.  */
+/* Create a new C argv array from a scheme list of strings. */
+/* Dirk:FIXME:: A quite similar function is implemented in dynl.c */
+/* Dirk:FIXME:: In case of assertion errors, we get memory leaks */
 
 static char **
-scm_convert_exec_args (SCM args, int pos, char *subr)
+scm_convert_exec_args (SCM args, int argn, const char *subr)
 {
-  char **execargv;
-  int num_args;
+  char **argv;
+  int argc;
   int i;
 
-  SCM_ASSERT (SCM_NULLP (args)
-             || (SCM_NIMP (args) && SCM_CONSP (args)),
-             args, pos, subr);
-  SCM_DEFER_INTS;
-  num_args = scm_ilength (args);
-  execargv = (char **) 
-    scm_must_malloc ((num_args + 1) * sizeof (char *), subr);
-  for (i = 0; SCM_NNULLP (args); args = SCM_CDR (args), ++i)
+  argc = scm_ilength (args);
+  SCM_ASSERT (argc >= 0, args, argn, subr);
+  argv = (char **) scm_must_malloc ((argc + 1) * sizeof (char *), subr);
+  for (i = 0; !SCM_NULLP (args); args = SCM_CDR (args), ++i)
     {
-      scm_sizet len;
+      SCM arg = SCM_CAR (args);
+      size_t len;
       char *dst;
       char *src;
-      SCM_ASSERT (SCM_NIMP (SCM_CAR (args)) && SCM_ROSTRINGP (SCM_CAR (args)),
-                 SCM_CAR (args), SCM_ARGn, subr);
-      len = 1 + SCM_ROLENGTH (SCM_CAR (args));
-      dst = (char *) scm_must_malloc ((long) len, subr);
-      src = SCM_ROCHARS (SCM_CAR (args));
-      while (len--) 
-       dst[len] = src[len];
-      execargv[i] = dst;
+
+      SCM_ASSERT (SCM_STRINGP (arg), args, argn, subr);
+      len = SCM_STRING_LENGTH (arg);
+      src = SCM_STRING_CHARS (arg);
+      dst = (char *) scm_must_malloc (len + 1, subr);
+      memcpy (dst, src, len);
+      dst[len] = 0;
+      argv[i] = dst;
     }
-  execargv[i] = 0;
-  SCM_ALLOW_INTS;
-  return execargv;
+  argv[i] = 0;
+  return argv;
 }
 
-SCM_PROC (s_execl, "execl", 1, 0, 1, scm_execl);
-
-SCM
-scm_execl (filename, args)
-     SCM filename, args;
+SCM_DEFINE (scm_execl, "execl", 1, 0, 1, 
+            (SCM filename, SCM args),
+           "Executes the file named by @var{path} as a new process image.\n"
+           "The remaining arguments are supplied to the process; from a C program\n"
+           "they are accessable as the @code{argv} argument to @code{main}.\n"
+           "Conventionally the first @var{arg} is the same as @var{path}.\n"
+           "All arguments must be strings.  \n\n"
+           "If @var{arg} is missing, @var{path} is executed with a null\n"
+           "argument list, which may have system-dependent side-effects.\n\n"
+           "This procedure is currently implemented using the @code{execv} system\n"
+           "call, but we call it @code{execl} because of its Scheme calling interface.")
+#define FUNC_NAME s_scm_execl
 {
   char **execargv;
-  SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename), filename,
-             SCM_ARG1, s_execl);
-  SCM_COERCE_SUBSTR (filename);
-  execargv = scm_convert_exec_args (args, SCM_ARG2, s_execl);
-  execv (SCM_ROCHARS (filename), execargv);
-  scm_syserror (s_execl);
+  SCM_VALIDATE_STRING (1, filename);
+  SCM_STRING_COERCE_0TERMINATION_X (filename);
+  execargv = scm_convert_exec_args (args, SCM_ARG2, FUNC_NAME);
+  execv (SCM_STRING_CHARS (filename), execargv);
+  SCM_SYSERROR;
   /* not reached.  */
   return SCM_BOOL_F;
 }
-
-SCM_PROC (s_execlp, "execlp", 1, 0, 1, scm_execlp);
-
-SCM
-scm_execlp (filename, args)
-     SCM filename, args;
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_execlp, "execlp", 1, 0, 1, 
+            (SCM filename, SCM args),
+           "Similar to @code{execl}, however if\n"
+           "@var{filename} does not contain a slash\n"
+           "then the file to execute will be located by searching the\n"
+           "directories listed in the @code{PATH} environment variable.\n\n"
+           "This procedure is currently implemented using the @code{execvp} system\n"
+           "call, but we call it @code{execlp} because of its Scheme calling interface.")
+#define FUNC_NAME s_scm_execlp
 {
   char **execargv;
-  SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename), filename,
-             SCM_ARG1, s_execlp);
-  SCM_COERCE_SUBSTR (filename);
-  execargv = scm_convert_exec_args (args, SCM_ARG2, s_execlp);
-  execvp (SCM_ROCHARS (filename), execargv);
-  scm_syserror (s_execlp);
+  SCM_VALIDATE_STRING (1, filename);
+  SCM_STRING_COERCE_0TERMINATION_X (filename);
+  execargv = scm_convert_exec_args (args, SCM_ARG2, FUNC_NAME);
+  execvp (SCM_STRING_CHARS (filename), execargv);
+  SCM_SYSERROR;
   /* not reached.  */
   return SCM_BOOL_F;
 }
+#undef FUNC_NAME
 
 static char **
-environ_list_to_c (SCM envlist, int arg, char *proc)
+environ_list_to_c (SCM envlist, int arg, const char *proc)
 {
   int num_strings;
   char **result;
-  int i = 0;
+  int i;
 
-  SCM_REDEFER_INTS;
-  SCM_ASSERT (SCM_NULLP (envlist)
-             || (SCM_NIMP (envlist) && SCM_CONSP (envlist)),
-             envlist, arg, proc);
   num_strings = scm_ilength (envlist);
+  SCM_ASSERT (num_strings >= 0, envlist, arg, proc);
   result = (char **) malloc ((num_strings + 1) * sizeof (char *));
   if (result == NULL)
     scm_memory_error (proc);
-  while (SCM_NNULLP (envlist))
+  for (i = 0; !SCM_NULLP (envlist); ++i, envlist = SCM_CDR (envlist))
     {
+      SCM str = SCM_CAR (envlist);
       int len;
       char *src;
 
-      SCM_ASSERT (SCM_NIMP (SCM_CAR (envlist))
-                 && SCM_ROSTRINGP (SCM_CAR (envlist)),
-                 envlist, arg, proc);
-      len = 1 + SCM_ROLENGTH (SCM_CAR (envlist));
-      result[i] = malloc ((long) len);
+      SCM_ASSERT (SCM_STRINGP (str), envlist, arg, proc);
+      len = SCM_STRING_LENGTH (str);
+      src = SCM_STRING_CHARS (str);
+      result[i] = malloc (len + 1);
       if (result[i] == NULL)
        scm_memory_error (proc);
-      src = SCM_ROCHARS (SCM_CAR (envlist));
-      while (len--) 
-       result[i][len] = src[len];
-      envlist = SCM_CDR (envlist);
-      i++;
+      memcpy (result[i], src, len);
+      result[i][len] = 0;
     }
   result[i] = 0;
-  SCM_REALLOW_INTS;
   return result;
 }
 
-SCM_PROC (s_execle, "execle", 2, 0, 1, scm_execle);
-
-SCM
-scm_execle (filename, env, args)
-     SCM filename, env, args;
+SCM_DEFINE (scm_execle, "execle", 2, 0, 1, 
+            (SCM filename, SCM env, SCM args),
+           "Similar to @code{execl}, but the environment of the new process is\n"
+           "specified by @var{env}, which must be a list of strings as returned by the\n"
+           "@code{environ} procedure.\n\n"
+           "This procedure is currently implemented using the @code{execve} system\n"
+           "call, but we call it @code{execle} because of its Scheme calling interface.")
+#define FUNC_NAME s_scm_execle
 {
   char **execargv;
   char **exec_env;
 
-  SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename), filename,
-             SCM_ARG1, s_execle);
-  SCM_COERCE_SUBSTR (filename);
+  SCM_VALIDATE_STRING (1, filename);
+  SCM_STRING_COERCE_0TERMINATION_X (filename);
   
-  execargv = scm_convert_exec_args (args, SCM_ARG1, s_execle);
-  exec_env = environ_list_to_c (env, SCM_ARG2, s_execle);
-  execve (SCM_ROCHARS (filename), execargv, exec_env);
-  scm_syserror (s_execle);
+  execargv = scm_convert_exec_args (args, SCM_ARG1, FUNC_NAME);
+  exec_env = environ_list_to_c (env, SCM_ARG2, FUNC_NAME);
+  execve (SCM_STRING_CHARS (filename), execargv, exec_env);
+  SCM_SYSERROR;
   /* not reached.  */
   return SCM_BOOL_F;
 }
-
-SCM_PROC (s_fork, "primitive-fork", 0, 0, 0, scm_fork);
-
-SCM
-scm_fork()
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0,
+            (),
+           "Creates a new \"child\" process by duplicating the current \"parent\" process.\n"
+           "In the child the return value is 0.  In the parent the return value is\n"
+           "the integer process ID of the child.\n\n"
+           "This procedure has been renamed from @code{fork} to avoid a naming conflict\n"
+           "with the scsh fork.")
+#define FUNC_NAME s_scm_fork
 {
   int pid;
   pid = fork ();
   if (pid == -1)
-    scm_syserror (s_fork);
+    SCM_SYSERROR;
   return SCM_MAKINUM (0L+pid);
 }
+#undef FUNC_NAME
 
-
-SCM_PROC (s_uname, "uname", 0, 0, 0, scm_uname);
-
-SCM 
-scm_uname ()
-{
 #ifdef HAVE_UNAME
+SCM_DEFINE (scm_uname, "uname", 0, 0, 0,
+            (),
+           "Return an object with some information about the computer\n"
+           "system the program is running on.")
+#define FUNC_NAME s_scm_uname
+{
   struct utsname buf;
-  SCM ans = scm_make_vector (SCM_MAKINUM(5), SCM_UNSPECIFIED);
+  SCM ans = scm_c_make_vector (5, SCM_UNSPECIFIED);
   SCM *ve = SCM_VELTS (ans);
-  SCM_DEFER_INTS;
   if (uname (&buf) < 0)
-    scm_syserror (s_uname);
+    SCM_SYSERROR;
   ve[0] = scm_makfrom0str (buf.sysname);
   ve[1] = scm_makfrom0str (buf.nodename);
   ve[2] = scm_makfrom0str (buf.release);
@@ -879,20 +985,21 @@ scm_uname ()
    a linux special?
   ve[5] = scm_makfrom0str (buf.domainname);
 */
-  SCM_ALLOW_INTS;
   return ans;
-#else
-  scm_sysmissing (s_uname);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
 }
-
-SCM_PROC (s_environ, "environ", 0, 1, 0, scm_environ);
-
-SCM
-scm_environ (env)
-     SCM env;
+#undef FUNC_NAME
+#endif /* HAVE_UNAME */
+
+SCM_DEFINE (scm_environ, "environ", 0, 1, 0, 
+            (SCM env),
+           "If @var{env} is omitted, return the current environment (in the\n"
+           "Unix sense) as a list of strings.  Otherwise set the current\n"
+           "environment, which is also the default environment for child\n"
+           "processes, to the supplied list of strings.  Each member of\n"
+           "@var{env} should be of the form @code{NAME=VALUE} and values of\n"
+           "@code{NAME} should not be duplicated.  If @var{env} is supplied\n"
+           "then the return value is unspecified.")
+#define FUNC_NAME s_scm_environ
 {
   if (SCM_UNBNDP (env))
     return scm_makfromstrs (-1, environ);
@@ -900,8 +1007,7 @@ scm_environ (env)
     {
       char **new_environ;
 
-      SCM_DEFER_INTS;
-      new_environ = environ_list_to_c (env, SCM_ARG1, s_environ);
+      new_environ = environ_list_to_c (env, SCM_ARG1, FUNC_NAME);
       /* Free the old environment, except when called for the first
        * time.
        */
@@ -917,212 +1023,234 @@ scm_environ (env)
        first = 0;
       }
       environ = new_environ;
-      SCM_ALLOW_INTS;
       return SCM_UNSPECIFIED;
     }
 }
+#undef FUNC_NAME
 
 #ifdef L_tmpnam
 
-SCM_PROC (s_tmpnam, "tmpnam", 0, 0, 0, scm_tmpnam);
-
-SCM scm_tmpnam()
+SCM_DEFINE (scm_tmpnam, "tmpnam", 0, 0, 0,
+            (),
+           "Return a name in the file system that does not match any\n"
+           "existing file.  However there is no guarantee that another\n"
+           "process will not create the file after @code{tmpnam} is called.\n"
+           "Care should be taken if opening the file, e.g., use the\n"
+           "@code{O_EXCL} open flag or use @code{mkstemp!} instead.")
+#define FUNC_NAME s_scm_tmpnam
 {
   char name[L_tmpnam];
-  SCM_SYSCALL (tmpnam (name););
-  return scm_makfrom0str (name);
-}
-#endif
-
-SCM_PROC (s_open_pipe, "open-pipe", 2, 0, 0, scm_open_pipe);
+  char *rv;
 
-SCM 
-scm_open_pipe (pipestr, modes)
-     SCM pipestr;
-     SCM modes;
-{
-  FILE *f;
-  register SCM z;
-  struct scm_port_table * pt;
-
-  SCM_ASSERT (SCM_NIMP (pipestr) && SCM_ROSTRINGP (pipestr), pipestr,
-             SCM_ARG1, s_open_pipe);
-  if (SCM_SUBSTRP (pipestr))
-    pipestr = scm_makfromstr (SCM_ROCHARS (pipestr),
-                             SCM_ROLENGTH (pipestr), 0);
-  SCM_ASSERT (SCM_NIMP (modes) && SCM_ROSTRINGP (modes), modes, SCM_ARG2,
-             s_open_pipe);
-  if (SCM_SUBSTRP (modes))
-    modes = scm_makfromstr (SCM_ROCHARS (modes), SCM_ROLENGTH (modes), 0);
-  SCM_NEWCELL (z);
-  SCM_DEFER_INTS;
-  SCM_SYSCALL (f = popen (SCM_ROCHARS (pipestr), SCM_ROCHARS (modes)));
-  if (!f)
-    scm_syserror (s_open_pipe);
-  pt = scm_add_to_port_table (z);
-  SCM_SETPTAB_ENTRY (z, pt);
-  SCM_SETCAR (z, scm_tc16_pipe | SCM_OPN 
-    | (strchr (SCM_ROCHARS (modes), 'r') ? SCM_RDNG : SCM_WRTNG));
-  SCM_SETSTREAM (z, (SCM)f);
-  SCM_ALLOW_INTS;
-  return z;
+  SCM_SYSCALL (rv = tmpnam (name));
+  if (rv == NULL)
+    /* not SCM_SYSERROR since errno probably not set.  */
+    SCM_MISC_ERROR ("tmpnam failed", SCM_EOL);
+  return scm_makfrom0str (name);
 }
+#undef FUNC_NAME
 
-SCM_PROC (s_close_pipe, "close-pipe", 1, 0, 0, scm_close_pipe);
+#endif
 
-SCM 
-scm_close_pipe (port)
-     SCM port;
+SCM_DEFINE (scm_mkstemp, "mkstemp!", 1, 0, 0,
+           (SCM tmpl),
+           "Create a new unique file in the file system and returns a new\n"
+           "buffered port open for reading and writing to the file.\n"
+           "@var{tmpl} is a string specifying where the file should be\n"
+           "created: it must end with @code{XXXXXX} and will be changed in\n"
+           "place to return the name of the temporary file.")
+#define FUNC_NAME s_scm_mkstemp
 {
+  char *c_tmpl;
   int rv;
-
-  SCM_ASSERT (SCM_NIMP (port) && SCM_TYP16(port) == scm_tc16_pipe 
-             && SCM_OPENP (port), port, SCM_ARG1, s_close_pipe);
-  SCM_DEFER_INTS;
-  rv = pclose ((FILE *) SCM_STREAM (port));
-  scm_remove_from_port_table (port);
-  SCM_SETAND_CAR (port, ~SCM_OPN);
+  
+  SCM_STRING_COERCE_0TERMINATION_X (tmpl);
+  SCM_VALIDATE_STRING_COPY (1, tmpl, c_tmpl);
+  SCM_SYSCALL (rv = mkstemp (c_tmpl));
   if (rv == -1)
-    scm_syserror (s_close_pipe);
-  SCM_ALLOW_INTS;
-  return SCM_MAKINUM (rv);
+    SCM_SYSERROR;
+  return scm_fdes_to_port (rv, "w+", tmpl);
 }
-
-SCM_PROC (s_utime, "utime", 1, 2, 0, scm_utime);
-
-SCM 
-scm_utime (pathname, actime, modtime)
-     SCM pathname;
-     SCM actime;
-     SCM modtime;
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_utime, "utime", 1, 2, 0,
+            (SCM pathname, SCM actime, SCM modtime),
+           "@code{utime} sets the access and modification times for the\n"
+           "file named by @var{path}.  If @var{actime} or @var{modtime} is\n"
+           "not supplied, then the current time is used.  @var{actime} and\n"
+           "@var{modtime} must be integer time values as returned by the\n"
+           "@code{current-time} procedure.\n"
+           "@lisp\n"
+           "(utime \"foo\" (- (current-time) 3600))\n"
+           "@end lisp\n"
+           "will set the access time to one hour in the past and the\n"
+           "modification time to the current time.")
+#define FUNC_NAME s_scm_utime
 {
   int rv;
   struct utimbuf utm_tmp;
 
-  SCM_ASSERT (SCM_NIMP (pathname) && SCM_ROSTRINGP (pathname), pathname,
-             SCM_ARG1, s_utime);
-
-  SCM_COERCE_SUBSTR (pathname);
+  SCM_VALIDATE_STRING (1, pathname);
+  SCM_STRING_COERCE_0TERMINATION_X (pathname);
   if (SCM_UNBNDP (actime))
     SCM_SYSCALL (time (&utm_tmp.actime));
   else
-    utm_tmp.actime = scm_num2ulong (actime, (char *) SCM_ARG2, s_utime);
+    utm_tmp.actime = SCM_NUM2ULONG (2, actime);
 
   if (SCM_UNBNDP (modtime))
     SCM_SYSCALL (time (&utm_tmp.modtime));
   else
-    utm_tmp.modtime = scm_num2ulong (modtime, (char *) SCM_ARG3, s_utime);
+    utm_tmp.modtime = SCM_NUM2ULONG (3, modtime);
 
-  SCM_SYSCALL (rv = utime (SCM_ROCHARS (pathname), &utm_tmp));
+  SCM_SYSCALL (rv = utime (SCM_STRING_CHARS (pathname), &utm_tmp));
   if (rv != 0)
-    scm_syserror (s_utime);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
 }
-
-SCM_PROC (s_access, "access?", 2, 0, 0, scm_access);
-
-SCM 
-scm_access (path, how)
-     SCM path;
-     SCM how;
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_access, "access?", 2, 0, 0,
+            (SCM path, SCM how),
+           "Return @code{#t} if @var{path} corresponds to an existing file\n"
+           "and the current process has the type of access specified by\n"
+           "@var{how}, otherwise @code{#f}.  @var{how} should be specified\n"
+           "using the values of the variables listed below.  Multiple\n"
+           "values can be combined using a bitwise or, in which case\n"
+           "@code{#t} will only be returned if all accesses are granted.\n"
+           "\n"
+           "Permissions are checked using the real id of the current\n"
+           "process, not the effective id, although it's the effective id\n"
+           "which determines whether the access would actually be granted.\n"
+           "\n"
+           "@defvar R_OK\n"
+           "test for read permission.\n"
+           "@end defvar\n"
+           "@defvar W_OK\n"
+           "test for write permission.\n"
+           "@end defvar\n"
+           "@defvar X_OK\n"
+           "test for execute permission.\n"
+           "@end defvar\n"
+           "@defvar F_OK\n"
+           "test for existence of the file.\n"
+           "@end defvar")
+#define FUNC_NAME s_scm_access
 {
   int rv;
 
-  SCM_ASSERT (SCM_NIMP (path) && SCM_ROSTRINGP (path), path, SCM_ARG1,
-             s_access);
-  if (SCM_SUBSTRP (path))
-    path = scm_makfromstr (SCM_ROCHARS (path), SCM_ROLENGTH (path), 0);
-  SCM_ASSERT (SCM_INUMP (how), how, SCM_ARG2, s_access);
-  rv = access (SCM_ROCHARS (path), SCM_INUM (how));
-  return rv ? SCM_BOOL_F : SCM_BOOL_T;
+  SCM_VALIDATE_STRING (1, path);
+  SCM_STRING_COERCE_0TERMINATION_X (path);
+  SCM_VALIDATE_INUM (2, how);
+  rv = access (SCM_STRING_CHARS (path), SCM_INUM (how));
+  return SCM_NEGATE_BOOL(rv);
 }
+#undef FUNC_NAME
 
-SCM_PROC (s_getpid, "getpid", 0, 0, 0, scm_getpid);
-
-SCM 
-scm_getpid ()
+SCM_DEFINE (scm_getpid, "getpid", 0, 0, 0,
+            (),
+           "Return an integer representing the current process ID.")
+#define FUNC_NAME s_scm_getpid
 {
   return SCM_MAKINUM ((unsigned long) getpid ());
 }
-
-SCM_PROC (s_putenv, "putenv", 1, 0, 0, scm_putenv);
-
-SCM
-scm_putenv (str)
-     SCM str;
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_putenv, "putenv", 1, 0, 0, 
+            (SCM str),
+           "Modifies the environment of the current process, which is\n"
+           "also the default environment inherited by child processes.\n\n"
+           "If @var{string} is of the form @code{NAME=VALUE} then it will be written\n"
+           "directly into the environment, replacing any existing environment string\n"
+           "with\n"
+           "name matching @code{NAME}.  If @var{string} does not contain an equal\n"
+           "sign, then any existing string with name matching @var{string} will\n"
+           "be removed.\n\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_putenv
 {
   int rv;
   char *ptr;
 
-  SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, SCM_ARG1, s_putenv);
+  SCM_VALIDATE_STRING (1, str);
   /* must make a new copy to be left in the environment, safe from gc.  */
-  ptr = malloc (SCM_LENGTH (str) + 1);
+  ptr = malloc (SCM_STRING_LENGTH (str) + 1);
   if (ptr == NULL)
-    scm_memory_error (s_putenv);
-  strncpy (ptr, SCM_ROCHARS (str), SCM_LENGTH (str));
-  ptr[SCM_LENGTH(str)] = 0;
+    SCM_MEMORY_ERROR;
+  strncpy (ptr, SCM_STRING_CHARS (str), SCM_STRING_LENGTH (str));
+  ptr[SCM_STRING_LENGTH (str)] = 0;
   rv = putenv (ptr);
   if (rv < 0)
-    scm_syserror (s_putenv);
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
 
-SCM_PROC (s_setlocale, "setlocale", 1, 1, 0, scm_setlocale);
-
-SCM
-scm_setlocale (category, locale)
-     SCM category;
-     SCM locale;
-{
 #ifdef HAVE_SETLOCALE
+SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
+            (SCM category, SCM locale),
+           "If @var{locale} is omitted, return the current value of the\n"
+           "specified locale category as a system-dependent string.\n"
+           "@var{category} should be specified using the values\n"
+           "@code{LC_COLLATE}, @code{LC_ALL} etc.\n"
+           "\n"
+           "Otherwise the specified locale category is set to the string\n"
+           "@var{locale} and the new value is returned as a\n"
+           "system-dependent string.  If @var{locale} is an empty string,\n"
+           "the locale will be set using envirionment variables.")
+#define FUNC_NAME s_scm_setlocale
+{
   char *clocale;
   char *rv;
 
-  SCM_ASSERT (SCM_INUMP (category), category, SCM_ARG1, s_setlocale);
+  SCM_VALIDATE_INUM (1,category);
   if (SCM_UNBNDP (locale))
     {
       clocale = NULL;
     }
   else
     {
-      SCM_ASSERT (SCM_NIMP (locale) && SCM_ROSTRINGP (locale), locale,
-                 SCM_ARG2, s_setlocale);
-      SCM_COERCE_SUBSTR (locale);
-      clocale = SCM_ROCHARS (locale);
+      SCM_VALIDATE_STRING (2, locale);
+      SCM_STRING_COERCE_0TERMINATION_X (locale);
+      clocale = SCM_STRING_CHARS (locale);
     }
 
   rv = setlocale (SCM_INUM (category), clocale);
   if (rv == NULL)
-    scm_syserror (s_setlocale);
+    SCM_SYSERROR;
   return scm_makfrom0str (rv);
-#else
-  scm_sysmissing (s_setlocale);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
 }
+#undef FUNC_NAME
+#endif /* HAVE_SETLOCALE */
 
-SCM_PROC (s_mknod, "mknod", 4, 0, 0, scm_mknod);
-
-SCM
-scm_mknod(path, type, perms, dev)
-     SCM path;
-     SCM type;
-     SCM perms;
-     SCM dev;
-{
 #ifdef HAVE_MKNOD
+SCM_DEFINE (scm_mknod, "mknod", 4, 0, 0,
+            (SCM path, SCM type, SCM perms, SCM dev),
+           "Creates a new special file, such as a file corresponding to a device.\n"
+           "@var{path} specifies the name of the file.  @var{type} should\n"
+           "be one of the following symbols:\n"
+           "regular, directory, symlink, block-special, char-special,\n"
+           "fifo, or socket.  @var{perms} (an integer) specifies the file permissions.\n"
+           "@var{dev} (an integer) specifies which device the special file refers\n"
+           "to.  Its exact interpretation depends on the kind of special file\n"
+           "being created.\n\n"
+           "E.g.,\n"
+           "@lisp\n"
+           "(mknod \"/dev/fd0\" 'block-special #o660 (+ (* 2 256) 2))\n"
+           "@end lisp\n\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_mknod
+{
   int val;
   char *p;
   int ctype = 0;
 
-  SCM_ASSERT (SCM_NIMP(path) && SCM_ROSTRINGP(path), path, SCM_ARG1, s_mknod);
-  SCM_ASSERT (SCM_NIMP(type) && SCM_SYMBOLP (type), type, SCM_ARG2, s_mknod);
-  SCM_ASSERT (SCM_INUMP (perms), perms, SCM_ARG3, s_mknod);
-  SCM_ASSERT (SCM_INUMP(dev), dev, SCM_ARG4, s_mknod);
-  SCM_COERCE_SUBSTR (path);
+  SCM_VALIDATE_STRING (1, path);
+  SCM_VALIDATE_SYMBOL (2,type);
+  SCM_VALIDATE_INUM (3,perms);
+  SCM_VALIDATE_INUM (4,dev);
+  SCM_STRING_COERCE_0TERMINATION_X (path);
 
-  p = SCM_CHARS (type);
+  p = SCM_SYMBOL_CHARS (type);
   if (strcmp (p, "regular") == 0)
     ctype = S_IFREG;
   else if (strcmp (p, "directory") == 0)
@@ -1135,58 +1263,306 @@ scm_mknod(path, type, perms, dev)
     ctype = S_IFCHR;
   else if (strcmp (p, "fifo") == 0)
     ctype = S_IFIFO;
+#ifdef S_IFSOCK
   else if (strcmp (p, "socket") == 0)
     ctype = S_IFSOCK;
+#endif
   else
-    scm_out_of_range (s_mknod, type);
+    SCM_OUT_OF_RANGE (2,type);
 
-  SCM_DEFER_INTS;
-  SCM_SYSCALL (val = mknod(SCM_ROCHARS(path), ctype | SCM_INUM (perms),
-                          SCM_INUM (dev)));
+  SCM_SYSCALL (val = mknod (SCM_STRING_CHARS (path), ctype | SCM_INUM (perms),
+                           SCM_INUM (dev)));
   if (val != 0)
-    scm_syserror (s_mknod);
-  SCM_ALLOW_INTS;
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
-#else
-  scm_sysmissing (s_mknod);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
 }
+#undef FUNC_NAME
+#endif /* HAVE_MKNOD */
 
+#ifdef HAVE_NICE
+SCM_DEFINE (scm_nice, "nice", 1, 0, 0, 
+            (SCM incr),
+           "Increment the priority of the current process by @var{incr}.  A higher\n"
+           "priority value means that the process runs less often.\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_nice
+{
+  SCM_VALIDATE_INUM (1,incr);
+  if (nice(SCM_INUM(incr)) != 0)
+    SCM_SYSERROR;
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+#endif /* HAVE_NICE */
 
-SCM_PROC (s_nice, "nice", 1, 0, 0, scm_nice);
+#ifdef HAVE_SYNC
+SCM_DEFINE (scm_sync, "sync", 0, 0, 0,
+            (),
+           "Flush the operating system disk buffers.\n"
+           "The return value is unspecified.")
+#define FUNC_NAME s_scm_sync
+{
+  sync();
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+#endif /* HAVE_SYNC */
+
+#if HAVE_LIBCRYPT && HAVE_CRYPT_H
+SCM_DEFINE (scm_crypt, "crypt", 2, 0, 0, 
+            (SCM key, SCM salt),
+           "Encrypt @var{key} using @var{salt} as the salt value to the\n"
+           "crypt(3) library call\n")
+#define FUNC_NAME s_scm_crypt
+{
+  char * p;
+
+  SCM_VALIDATE_STRING (1, key);
+  SCM_VALIDATE_STRING (2, salt);
+  SCM_STRING_COERCE_0TERMINATION_X (key);
+  SCM_STRING_COERCE_0TERMINATION_X (salt);
 
-SCM
-scm_nice(incr)
-     SCM incr;
+  p = crypt (SCM_STRING_CHARS (key), SCM_STRING_CHARS (salt));
+  return scm_makfrom0str (p);
+}
+#undef FUNC_NAME
+#endif /* HAVE_LIBCRYPT && HAVE_CRYPT_H */
+
+#if HAVE_CHROOT
+SCM_DEFINE (scm_chroot, "chroot", 1, 0, 0, 
+            (SCM path),
+           "Change the root directory to that specified in @var{path}.\n"
+           "This directory will be used for path names beginning with\n"
+           "@file{/}.  The root directory is inherited by all children\n"
+           "of the current process.  Only the superuser may change the\n"
+           "root directory.")
+#define FUNC_NAME s_scm_chroot
 {
-#ifdef HAVE_NICE
-  SCM_ASSERT(SCM_INUMP(incr), incr, SCM_ARG1, s_nice);
-  if (nice(SCM_INUM(incr)) != 0)
-    scm_syserror (s_nice);
+  SCM_VALIDATE_STRING (1, path);
+  SCM_STRING_COERCE_0TERMINATION_X (path);
+
+  if (chroot (SCM_STRING_CHARS (path)) == -1)
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
-#else
-  scm_sysmissing (s_nice);
-  /* not reached.  */
-  return SCM_BOOL_F;
-#endif
 }
+#undef FUNC_NAME
+#endif /* HAVE_CHROOT */
+
+#if HAVE_GETLOGIN
+SCM_DEFINE (scm_getlogin, "getlogin", 0, 0, 0, 
+            (void),
+           "Return a string containing the name of the user logged in on\n"
+           "the controlling terminal of the process, or @code{#f} if this\n"
+           "information cannot be obtained.")
+#define FUNC_NAME s_scm_getlogin
+{
+  char * p;
+
+  p = getlogin ();
+  if (!p || !*p)
+    return SCM_BOOL_F;
+  return scm_makfrom0str (p);
+}
+#undef FUNC_NAME
+#endif /* HAVE_GETLOGIN */
+
+#if HAVE_CUSERID
+SCM_DEFINE (scm_cuserid, "cuserid", 0, 0, 0, 
+            (void),
+           "Return a string containing a user name associated with the\n"
+           "effective user id of the process.  Return @code{#f} if this\n"
+           "information cannot be obtained.")
+#define FUNC_NAME s_scm_cuserid
+{
+  char * p;
 
+  p = cuserid (NULL);
+  if (!p || !*p)
+    return SCM_BOOL_F;
+  return scm_makfrom0str (p);
+}
+#undef FUNC_NAME
+#endif /* HAVE_CUSERID */
+
+#if HAVE_GETPRIORITY
+SCM_DEFINE (scm_getpriority, "getpriority", 2, 0, 0, 
+            (SCM which, SCM who),
+           "Return the scheduling priority of the process, process group\n"
+           "or user, as indicated by @var{which} and @var{who}. @var{which}\n"
+           "is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP}\n"
+           "or @code{PRIO_USER}, and @var{who} is interpreted relative to\n"
+           "@var{which} (a process identifier for @code{PRIO_PROCESS},\n"
+           "process group identifier for @code{PRIO_PGRP}, and a user\n"
+           "identifier for @code{PRIO_USER}.  A zero value of @var{who}\n"
+           "denotes the current process, process group, or user.  Return\n"
+           "the highest priority (lowest numerical value) of any of the\n"
+           "specified processes.")
+#define FUNC_NAME s_scm_getpriority
+{
+  int cwhich, cwho, ret;
+
+  SCM_VALIDATE_INUM_COPY (1, which, cwhich);
+  SCM_VALIDATE_INUM_COPY (2, who, cwho);
+
+  /* We have to clear errno and examine it later, because -1 is a
+     legal return value for getpriority().  */
+  errno = 0;
+  ret = getpriority (cwhich, cwho);
+  if (errno != 0)
+    SCM_SYSERROR;
+  return SCM_MAKINUM (ret);
+}
+#undef FUNC_NAME
+#endif /* HAVE_GETPRIORITY */
+
+#if HAVE_SETPRIORITY
+SCM_DEFINE (scm_setpriority, "setpriority", 3, 0, 0, 
+            (SCM which, SCM who, SCM prio),
+           "Set the scheduling priority of the process, process group\n"
+           "or user, as indicated by @var{which} and @var{who}. @var{which}\n"
+           "is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP}\n"
+           "or @code{PRIO_USER}, and @var{who} is interpreted relative to\n"
+           "@var{which} (a process identifier for @code{PRIO_PROCESS},\n"
+           "process group identifier for @code{PRIO_PGRP}, and a user\n"
+           "identifier for @code{PRIO_USER}.  A zero value of @var{who}\n"
+           "denotes the current process, process group, or user.\n"
+           "@var{prio} is a value in the range -20 and 20, the default\n"
+           "priority is 0; lower priorities cause more favorable\n"
+           "scheduling.  Sets the priority of all of the specified\n"
+           "processes.  Only the super-user may lower priorities.\n"
+           "The return value is not specified.")
+#define FUNC_NAME s_scm_setpriority
+{
+  int cwhich, cwho, cprio;
 
-SCM_PROC (s_sync, "sync", 0, 0, 0, scm_sync);
+  SCM_VALIDATE_INUM_COPY (1, which, cwhich);
+  SCM_VALIDATE_INUM_COPY (2, who, cwho);
+  SCM_VALIDATE_INUM_COPY (3, prio, cprio);
 
-SCM
-scm_sync()
+  if (setpriority (cwhich, cwho, cprio) == -1)
+    SCM_SYSERROR;
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+#endif /* HAVE_SETPRIORITY */
+
+#if HAVE_GETPASS
+SCM_DEFINE (scm_getpass, "getpass", 1, 0, 0, 
+            (SCM prompt),
+           "Display @var{prompt} to the standard error output and read\n"
+           "a password from @file{/dev/tty}.  If this file is not\n"
+           "accessible, it reads from standard input.  The password may be\n"
+           "up to 127 characters in length.  Additional characters and the\n"
+           "terminating newline character are discarded.  While reading\n"
+           "the password, echoing and the generation of signals by special\n"
+           "characters is disabled.")
+#define FUNC_NAME s_scm_getpass
 {
-#ifdef HAVE_SYNC
-  sync();
-#else
-  scm_sysmissing (s_sync);
-  /* not reached.  */
-#endif
+  char * p;
+  SCM passwd;
+
+  SCM_VALIDATE_STRING (1, prompt);
+  SCM_STRING_COERCE_0TERMINATION_X (prompt);
+
+  p = getpass(SCM_STRING_CHARS (prompt));
+  passwd = scm_makfrom0str (p);
+
+  /* Clear out the password in the static buffer.  */
+  memset (p, 0, strlen (p));
+
+  return passwd;
+}
+#undef FUNC_NAME
+#endif /* HAVE_GETPASS */
+
+#if HAVE_FLOCK
+SCM_DEFINE (scm_flock, "flock", 2, 0, 0, 
+            (SCM file, SCM operation),
+           "Apply or remove an advisory lock on an open file.\n"
+           "@var{operation} specifies the action to be done:\n"
+           "@table @code\n"
+           "@item LOCK_SH\n"
+           "Shared lock.  More than one process may hold a shared lock\n"
+           "for a given file at a given time.\n"
+           "@item LOCK_EX\n"
+           "Exclusive lock.  Only one process may hold an exclusive lock\n"
+           "for a given file at a given time.\n"
+           "@item LOCK_UN\n"
+           "Unlock the file.\n"
+           "@item LOCK_NB\n"
+           "Don't block when locking.  May be specified by bitwise OR'ing\n"
+           "it to one of the other operations.\n"
+           "@end table\n"
+           "The return value is not specified. @var{file} may be an open\n"
+           "file descriptor or an open file descriptior port.")
+#define FUNC_NAME s_scm_flock
+{
+  int coperation, fdes;
+
+  if (SCM_INUMP (file))
+    fdes = SCM_INUM (file);
+  else
+    {
+      SCM_VALIDATE_OPFPORT (2, file);
+
+      fdes = SCM_FPORT_FDES (file);
+    }
+  SCM_VALIDATE_INUM_COPY (2, operation, coperation);
+  if (flock (fdes, coperation) == -1)
+    SCM_SYSERROR;
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+#endif /* HAVE_FLOCK */
+
+#if HAVE_SETHOSTNAME
+SCM_DEFINE (scm_sethostname, "sethostname", 1, 0, 0, 
+            (SCM name),
+           "Set the host name of the current processor to @var{name}. May\n"
+           "only be used by the superuser.  The return value is not\n"
+           "specified.")
+#define FUNC_NAME s_scm_sethostname
+{
+  SCM_VALIDATE_STRING (1, name);
+  SCM_STRING_COERCE_0TERMINATION_X (name);
+
+  if (sethostname (SCM_STRING_CHARS (name), SCM_STRING_LENGTH (name)) == -1)
+    SCM_SYSERROR;
   return SCM_UNSPECIFIED;
 }
+#undef FUNC_NAME
+#endif /* HAVE_SETHOSTNAME */
+
+#if HAVE_GETHOSTNAME
+SCM_DEFINE (scm_gethostname, "gethostname", 0, 0, 0, 
+            (void),
+           "Return the host name of the current processor.")
+#define FUNC_NAME s_scm_gethostname
+{
+  /* 256 is for Solaris, under Linux ENAMETOOLONG is returned if not
+     large enough.  */
+  int len = 256, res;
+  char *p = scm_must_malloc (len, "gethostname");
+  SCM name;
+
+  res = gethostname (p, len);
+  while (res == -1 && errno == ENAMETOOLONG)
+    {
+      p = scm_must_realloc (p, len, len * 2, "gethostname");
+      len *= 2;
+      res = gethostname (p, len);
+    }
+  if (res == -1)
+    {
+      scm_must_free (p);
+      SCM_SYSERROR;
+    }
+  name = scm_makfrom0str (p);
+  scm_must_free (p);
+  return name;
+}
+#undef FUNC_NAME
+#endif /* HAVE_GETHOSTNAME */
 
 void 
 scm_init_posix ()
@@ -1196,45 +1572,80 @@ scm_init_posix ()
   scm_add_feature ("EIDs");
 #endif
 #ifdef WAIT_ANY
-  scm_sysintern ("WAIT_ANY", SCM_MAKINUM (WAIT_ANY));
+  scm_c_define ("WAIT_ANY", SCM_MAKINUM (WAIT_ANY));
 #endif
 #ifdef WAIT_MYPGRP
-  scm_sysintern ("WAIT_MYPGRP", SCM_MAKINUM (WAIT_MYPGRP));
+  scm_c_define ("WAIT_MYPGRP", SCM_MAKINUM (WAIT_MYPGRP));
 #endif
 #ifdef WNOHANG
-  scm_sysintern ("WNOHANG", SCM_MAKINUM (WNOHANG));
+  scm_c_define ("WNOHANG", SCM_MAKINUM (WNOHANG));
 #endif
 #ifdef WUNTRACED
-  scm_sysintern ("WUNTRACED", SCM_MAKINUM (WUNTRACED));
+  scm_c_define ("WUNTRACED", SCM_MAKINUM (WUNTRACED));
 #endif
 
   /* access() symbols.  */
-  scm_sysintern ("R_OK", SCM_MAKINUM (R_OK));
-  scm_sysintern ("W_OK", SCM_MAKINUM (W_OK));
-  scm_sysintern ("X_OK", SCM_MAKINUM (X_OK));
-  scm_sysintern ("F_OK", SCM_MAKINUM (F_OK));
+  scm_c_define ("R_OK", SCM_MAKINUM (R_OK));
+  scm_c_define ("W_OK", SCM_MAKINUM (W_OK));
+  scm_c_define ("X_OK", SCM_MAKINUM (X_OK));
+  scm_c_define ("F_OK", SCM_MAKINUM (F_OK));
 
 #ifdef LC_COLLATE
-  scm_sysintern ("LC_COLLATE", SCM_MAKINUM (LC_COLLATE));
+  scm_c_define ("LC_COLLATE", SCM_MAKINUM (LC_COLLATE));
 #endif
 #ifdef LC_CTYPE
-  scm_sysintern ("LC_CTYPE", SCM_MAKINUM (LC_CTYPE));
+  scm_c_define ("LC_CTYPE", SCM_MAKINUM (LC_CTYPE));
 #endif
 #ifdef LC_MONETARY
-  scm_sysintern ("LC_MONETARY", SCM_MAKINUM (LC_MONETARY));
+  scm_c_define ("LC_MONETARY", SCM_MAKINUM (LC_MONETARY));
 #endif
 #ifdef LC_NUMERIC
-  scm_sysintern ("LC_NUMERIC", SCM_MAKINUM (LC_NUMERIC));
+  scm_c_define ("LC_NUMERIC", SCM_MAKINUM (LC_NUMERIC));
 #endif
 #ifdef LC_TIME
-  scm_sysintern ("LC_TIME", SCM_MAKINUM (LC_TIME));
+  scm_c_define ("LC_TIME", SCM_MAKINUM (LC_TIME));
 #endif
 #ifdef LC_MESSAGES
-  scm_sysintern ("LC_MESSAGES", SCM_MAKINUM (LC_MESSAGES));
+  scm_c_define ("LC_MESSAGES", SCM_MAKINUM (LC_MESSAGES));
 #endif
 #ifdef LC_ALL
-  scm_sysintern ("LC_ALL", SCM_MAKINUM (LC_ALL));
+  scm_c_define ("LC_ALL", SCM_MAKINUM (LC_ALL));
+#endif
+#ifdef PIPE_BUF
+  scm_c_define ("PIPE_BUF", scm_long2num (PIPE_BUF));
+#endif
+
+#ifdef PRIO_PROCESS
+  scm_c_define ("PRIO_PROCESS", SCM_MAKINUM (PRIO_PROCESS));
+#endif
+#ifdef PRIO_PGRP
+  scm_c_define ("PRIO_PGRP", SCM_MAKINUM (PRIO_PGRP));
+#endif
+#ifdef PRIO_USER
+  scm_c_define ("PRIO_USER", SCM_MAKINUM (PRIO_USER));
+#endif
+
+#ifdef LOCK_SH
+  scm_c_define ("LOCK_SH", SCM_MAKINUM (LOCK_SH));
+#endif
+#ifdef LOCK_EX
+  scm_c_define ("LOCK_EX", SCM_MAKINUM (LOCK_EX));
+#endif
+#ifdef LOCK_UN
+  scm_c_define ("LOCK_UN", SCM_MAKINUM (LOCK_UN));
+#endif
+#ifdef LOCK_NB
+  scm_c_define ("LOCK_NB", SCM_MAKINUM (LOCK_NB));
+#endif
+
+#include "libguile/cpp_sig_symbols.c"
+#ifndef SCM_MAGIC_SNARFER
+#include "libguile/posix.x"
 #endif
-#include "cpp_sig_symbols.c"
-#include "posix.x"
 }
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/