changeset 2937:9d26524e2869

[project @ 1997-05-06 05:49:53 by jwe]
author jwe
date Tue, 06 May 1997 05:55:13 +0000
parents 87cb7614257d
children 2e1757f57ce6
files liboctave/file-ops.cc liboctave/file-ops.h liboctave/oct-env.cc liboctave/oct-group.cc liboctave/oct-group.h liboctave/oct-passwd.cc liboctave/oct-passwd.h liboctave/str-vec.cc liboctave/str-vec.h src/ChangeLog src/DLD-FUNCTIONS/getgrent.cc src/DLD-FUNCTIONS/getpwent.cc src/syscalls.cc
diffstat 13 files changed, 699 insertions(+), 281 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/file-ops.cc
+++ b/liboctave/file-ops.cc
@@ -29,8 +29,6 @@
 #include <cstdlib>
 #include <cstring>
 
-#include <iostream.h>
-
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
@@ -40,18 +38,21 @@
 #endif
 
 #include "file-ops.h"
-#include "lo-error.h"
 #include "oct-env.h"
 #include "oct-passwd.h"
 #include "statdefs.h"
 #include "str-vec.h"
 
+#define NOT_SUPPORTED(nm) \
+  nm ## ": not supported on this system"
+
 // We provide a replacement for mkdir().
 
 int
 file_ops::mkdir (const string& name, mode_t mode)
 {
-  return ::mkdir (name.c_str (), mode);
+  string msg;
+  return mkdir (name, mode, msg);
 }
 
 int
@@ -59,10 +60,16 @@
 {
   msg = string ();
 
-  int status = ::mkdir (name.c_str (), mode);
+  int status = -1;
+
+#if defined (HAVE_MKDIR)
+  status = ::mkdir (name.c_str (), mode);
 
   if (status < 0)
     msg = ::strerror (errno);
+#else
+  msg = NOT_SUPPORTED ("mkdir");
+#endif
 
   return status;
 }
@@ -72,13 +79,8 @@
 int
 file_ops::mkfifo (const string& name, mode_t mode)
 {
-#if defined (HAVE_MKFIFO)
-  return ::mkfifo (name.c_str (), mode);
-#else
-  (*current_liboctave_error_handler)
-    ("mkfifo: not implemented on this system");
-  return -1;
-#endif
+  string msg;
+  return mkfifo (name, mode, msg);
 }
 
 int
@@ -86,18 +88,18 @@
 {
   msg = string ();
 
+  int status = -1;
+
 #if defined (HAVE_MKFIFO)
-  int status = ::mkfifo (name.c_str (), mode);
+  status = ::mkfifo (name.c_str (), mode);
 
   if (status < 0)
     msg = ::strerror (errno);
+#else
+  msg = NOT_SUPPORTED ("mkfifo");
+#endif
 
   return status;
-#else
-  (*current_liboctave_error_handler)
-    ("mkfifo: not implemented on this system");
-  return -1;
-#endif
 }
 
 // We provide a replacement for rename().
@@ -105,18 +107,25 @@
 int
 file_ops::rename (const string& from, const string& to)
 {
-  return ::rename (from.c_str (), to.c_str ());
+  string msg;
+  return rename (from, to, msg);
 }
 
 int
 file_ops::rename (const string& from, const string& to, string& msg)
 {
+  int status = -1;
+
   msg = string ();
 
-  int status = ::rename (from.c_str (), to.c_str ());
+#if defined (HAVE_RENAME)
+  status = ::rename (from.c_str (), to.c_str ());
 
   if (status < 0)
     msg = ::strerror (errno);
+#else
+  msg = NOT_SUPPORTED ("rename");
+#endif
 
   return status;
 }
@@ -126,7 +135,8 @@
 int
 file_ops::rmdir (const string& name)
 {
-  return ::rmdir (name.c_str ());
+  string msg;
+  return rmdir (name, msg);
 }
 
 int
@@ -134,10 +144,16 @@
 {
   msg = string ();
 
-  int status = ::rmdir (name.c_str ());
+  int status = -1;
+
+#if defined (HAVE_RMDIR)
+  status = ::rmdir (name.c_str ());
 
   if (status < 0)
     msg = ::strerror (errno);
+#else
+  msg = NOT_SUPPORTED ("rmdir");
+#endif
 
   return status;
 }
@@ -145,20 +161,33 @@
 // We provide a replacement for tempnam().
 
 string
-file_ops::tempnam (void)
+file_ops::tempnam (const string& dir, const string& pfx)
 {
+  string msg;
+  return tempnam (dir, pfx, msg);
+}
+
+string
+file_ops::tempnam (const string& dir, const string& pfx, string& msg)
+{
+  msg = string ();
+
   string retval;
+  
+  const char *pdir = dir.empty () ? 0 : dir.c_str ();
 
-  char *tmp = ::tempnam (0, "oct-");
+  const char *ppfx = pfx.empty () ? 0 : pfx.c_str ();
+
+  char *tmp = ::tempnam (pdir, ppfx);
 
   if (tmp)
     {
       retval = tmp;
 
-      free (tmp);
+      ::free (tmp);
     }
   else
-    (*current_liboctave_error_handler) ("can't open temporary file!");
+    msg = ::strerror (errno);
 
   return retval;
 }
@@ -217,7 +246,7 @@
 
 	  // If no such user, just use `.'.
 
-	  string home = pw.empty () ? : string (".") : pw.dir ();
+	  string home = pw ? string (".") : pw.dir ();
       
 	  expansion = string (" ", beg) + home;
 
@@ -259,18 +288,25 @@
 int
 file_ops::unlink (const string& name)
 {
-  return ::unlink (name.c_str ());
+  string msg;
+  return unlink (name, msg);
 }
 
 int
-file_ops::unlink (const string& name, string& errmsg)
+file_ops::unlink (const string& name, string& msg)
 {
-  errmsg = string ();
+  msg = string ();
 
-  int status = ::unlink (name.c_str ());
+  int status = -1;
+
+#if defined (HAVE_UNLINK)
+  status = ::unlink (name.c_str ());
 
   if (status < 0)
-    errmsg = ::strerror (errno);
+    msg = ::strerror (errno);
+#else
+  msg = NOT_SUPPORTED ("unlink");
+#endif
 
   return status;
 }
--- a/liboctave/file-ops.h
+++ b/liboctave/file-ops.h
@@ -46,7 +46,8 @@
   static int rmdir (const string&);
   static int rmdir (const string&, string&);
 
-  static string tempnam (void);
+  static string tempnam (const string&, const string&);
+  static string tempnam (const string&, const string&, string&);
 
   static string tilde_expand (const string&);
   static string_vector tilde_expand (const string_vector&);
--- a/liboctave/oct-env.cc
+++ b/liboctave/oct-env.cc
@@ -373,7 +373,7 @@
     {
       octave_passwd pw = octave_passwd::getpwuid (getuid ());
 
-      user_name = pw.empty () ? string ("I have no name!") : pw.name ();
+      user_name = pw ? string ("I have no name!") : pw.name ();
     }
 
   return user_name;
new file mode 100644
--- /dev/null
+++ b/liboctave/oct-group.cc
@@ -0,0 +1,228 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
+#include "lo-error.h"
+#include "oct-group.h"
+#include "str-vec.h"
+
+#define NOT_SUPPORTED(nm) \
+  nm ## ": not supported on this system"
+
+string
+octave_group::name (void) const
+{
+  if (! ok ())
+    gripe_invalid ();
+
+  return gr_name;
+}
+
+string
+octave_group::passwd (void) const
+{
+  if (! ok ())
+    gripe_invalid ();
+
+  return gr_passwd;
+}
+
+gid_t
+octave_group::gid (void) const
+{
+  if (! ok ())
+    gripe_invalid ();
+
+  return gr_gid;
+}
+
+string_vector
+octave_group::mem (void) const
+{
+  if (! ok ())
+    gripe_invalid ();
+
+  return gr_mem;
+}
+
+octave_group
+octave_group::getgrent (void)
+{
+  string msg;
+  return getgrent (msg);
+}
+
+octave_group
+octave_group::getgrent (string& msg)
+{
+#if defined (HAVE_GETGRENT)
+  msg = string ();
+  return octave_group (::getgrent (), msg);
+#else
+  msg = NOT_SUPPORTED ("getgrent");
+  return octave_group ();
+#endif
+}
+
+octave_group
+octave_group::getgrgid (gid_t gid)
+{
+  string msg;
+  return getgrgid (gid, msg);
+}
+
+octave_group
+octave_group::getgrgid (gid_t gid, string& msg)
+{
+#if defined (HAVE_GETGRGID)
+  msg = string ();
+  return octave_group (::getgrgid (gid), msg);
+#else
+  msg = NOT_SUPPORTED ("getgruid");
+  return octave_group ();
+#endif
+}
+
+octave_group
+octave_group::getgrnam (const string& nm)
+{
+  string msg;
+  return getgrnam (msg);
+}
+
+octave_group
+octave_group::getgrnam (const string& nm, string& msg)
+{
+#if defined (HAVE_GETGRNAM)
+  msg = string ();
+  return octave_group (::getgrnam (nm.c_str ()), msg);
+#else
+  msg = NOT_SUPPORTED ("getgrnam");
+  return octave_group ();
+#endif
+}
+
+int
+octave_group::setgrent (void)
+{
+  string msg;
+  return setgrent (msg);
+}
+
+int
+octave_group::setgrent (string& msg)
+{
+#if defined (HAVE_SETGRENT)
+  msg = string ();
+  ::setgrent ();
+  return 0;
+#else
+  msg = NOT_SUPPORTED ("setgrent");
+  return -1;
+#endif
+}
+
+int
+octave_group::endgrent (void)
+{
+  string msg;
+  return endgrent (msg);
+}
+
+int
+octave_group::endgrent (string& msg)
+{
+#if defined (HAVE_ENDGRENT)
+  msg = string ();
+  ::endgrent ();
+  return 0;
+#else
+  msg = NOT_SUPPORTED ("endgrent");
+  return -1;
+#endif
+}
+
+octave_group::octave_group (void *p, string& msg)
+  : gr_name (), gr_passwd (), gr_gid (0), gr_mem (), valid (false)
+{
+#if defined (HAVE_GRP_H)
+  msg = string ();
+
+  if (p)
+    {
+      struct group *gr = static_cast<struct group *> (p);
+
+      gr_name = gr->gr_name;
+
+#if defined (HAVE_GR_PASSWD)
+      gr_passwd = gr->gr_passwd;
+#endif
+
+      // XXX FIXME XXX -- maybe there should be a string_vector
+      // constructor that takes a NULL terminated list of C
+      // strings.
+
+      const char * const *tmp = gr->gr_mem;
+
+      int k = 0;
+      while (*tmp++)
+	k++;
+
+      if (k > 0)
+	{
+	  tmp = gr->gr_mem;
+
+	  gr_mem.resize (k);
+
+	  for (int i = 0; i < k; i++)
+	    gr_mem[i] = tmp[i];
+	}
+
+      valid = true;
+    }
+#else
+  msg = NOT_SUPPORTED ("group functions");
+#endif
+}
+
+void
+octave_group::gripe_invalid (void) const
+{
+  (*current_liboctave_error_handler) ("invalid group object");
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
new file mode 100644
--- /dev/null
+++ b/liboctave/oct-group.h
@@ -0,0 +1,121 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#if !defined (octave_group_h)
+#define octave_group_h 1
+
+#include <string>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "str-vec.h"
+
+class
+octave_group
+{
+public:
+
+  octave_group (void)
+    : gr_name (), gr_passwd (), gr_gid (0), gr_mem (), valid (false)
+  { }
+
+  octave_group (const octave_group& gr)
+    : gr_name (gr.gr_name), gr_passwd (gr.gr_passwd),
+      gr_gid (gr.gr_gid), gr_mem (gr.gr_mem), valid (gr.valid) 
+  { }
+
+  octave_group& operator = (const octave_group& gr)
+  {
+    if (this != &gr)
+      {
+	gr_name  = gr.gr_name;
+	gr_passwd = gr.gr_passwd;
+	gr_gid = gr.gr_gid;
+	gr_mem = gr.gr_mem;
+	valid = gr.valid;
+      }
+
+    return *this;
+  }
+
+  string name (void) const;
+
+  string passwd (void) const;
+
+  gid_t gid (void) const;
+
+  string_vector mem (void) const;
+
+  bool ok (void) const { return valid; }
+
+  operator void* () const
+    { return ok ()
+	? static_cast<void *> (-1) : static_cast<void *> (0); }
+
+  static octave_group getgrent (void);
+  static octave_group getgrent (string& msg);
+
+  static octave_group getgrgid (gid_t gid);
+  static octave_group getgrgid (gid_t gid, string& msg);
+
+  static octave_group getgrnam (const string& nm);
+  static octave_group getgrnam (const string& nm, string& msg);
+
+  static int setgrent (void);
+  static int setgrent (string& msg);
+
+  static int endgrent (void);
+  static int endgrent (string& msg);
+
+private:
+
+  // The group name.
+  string gr_name;
+
+  // The group password.
+  string gr_passwd;
+
+  // The numeric group id.
+  gid_t gr_gid;
+
+  // The members of the group;
+  string_vector gr_mem;
+
+  // Flag that says whether we have been properly initialized.
+  bool valid;
+
+  // This is how we will create an octave_group object from a pointer
+  // to a struct group.
+  octave_group (void *p, string& msg);
+
+  void gripe_invalid (void) const;
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/liboctave/oct-passwd.cc
+++ b/liboctave/oct-passwd.cc
@@ -24,6 +24,10 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #endif
@@ -31,6 +35,9 @@
 #include "lo-error.h"
 #include "oct-passwd.h"
 
+#define NOT_SUPPORTED(nm) \
+  nm ## ": not supported on this system"
+
 string
 octave_passwd::name (void) const
 {
@@ -97,11 +104,18 @@
 octave_passwd
 octave_passwd::getpwent (void)
 {
-#ifdef HAVE_GETPWENT
-  return octave_passwd (::getpwent ());
+  string msg;
+  return getpwent (msg);
+}
+
+octave_passwd
+octave_passwd::getpwent (string& msg)
+{
+#if defined HAVE_GETPWENT
+  msg = string ();
+  return octave_passwd (::getpwent (), msg);
 #else
-  gripe_not_implemented ("getpwent");
-
+  msg = NOT_SUPPORTED ("getpwent");
   return octave_passwd ();
 #endif
 }
@@ -109,11 +123,18 @@
 octave_passwd
 octave_passwd::getpwuid (uid_t uid)
 {
-#ifdef HAVE_GETPWUID
-  return octave_passwd (::getpwuid (uid));
+  string msg;
+  return getpwuid (uid, msg);
+}
+
+octave_passwd
+octave_passwd::getpwuid (uid_t uid, string& msg)
+{
+#if defined (HAVE_GETPWUID)
+  msg = string ();
+  return octave_passwd (::getpwuid (uid), msg);
 #else
-  gripe_not_implemented ("getpwuid");
-
+  msg = NOT_SUPPORTED ("getpwuid");
   return octave_passwd ();
 #endif
 }
@@ -121,40 +142,69 @@
 octave_passwd
 octave_passwd::getpwnam (const string& nm)
 {
-#ifdef HAVE_GETPWNAM
-  return octave_passwd (::getpwnam (nm.c_str ()));
+  string msg;
+  return getpwnam (nm, msg);
+}
+
+octave_passwd
+octave_passwd::getpwnam (const string& nm, string& msg)
+{
+#if defined (HAVE_GETPWNAM)
+  msg = string ();
+  return octave_passwd (::getpwnam (nm.c_str ()), msg);
 #else
-  gripe_not_implemented ("getpwnam");
-
+  msg = NOT_SUPPORTED ("getpwnam");
   return octave_passwd ();
 #endif
 }
 
-void
+int
 octave_passwd::setpwent (void)
 {
-#ifdef HAVE_SETPWENT
+  string msg;
+  return setpwent (msg);
+}
+
+int
+octave_passwd::setpwent (string& msg)
+{
+#if defined (HAVE_SETPWENT)
+  msg = string ();
   ::setpwent ();
+  return 0;
 #else
-  gripe_not_implemented ("setpwent");
+  msg = NOT_SUPPORTED ("setpwent");
+  return -1;
 #endif
 }
 
-void
+int
 octave_passwd::endpwent (void)
 {
-#ifdef HAVE_ENDPWENT
+  string msg;
+  return endpwent (msg);
+}
+
+int
+octave_passwd::endpwent (string& msg)
+{
+#if defined (HAVE_ENDPWENT)
+  msg = string ();
   ::endpwent ();
+  return 0;
 #else
-  gripe_not_implemented ("endpwent");
+  msg = NOT_SUPPORTED ("endpwent");
+  return -1;
 #endif
 }
 
-octave_passwd::octave_passwd (void *p)
+octave_passwd::octave_passwd (void *p, string& msg)
   : pw_name (), pw_passwd (), pw_uid (0), pw_gid (0), pw_gecos (),
     pw_dir (), pw_shell (), valid (false)
 {
-#ifdef HAVE_PWD_H
+#if defined (HAVE_PWD_H)
+  msg = string ();
+
   if (p)
     {
       struct passwd *pw = static_cast<struct passwd *> (p);
@@ -169,6 +219,8 @@
 
       valid = true;
     }
+#else
+  msg = NOT_SUPPORTED ("password functions");
 #endif
 }
 
@@ -178,13 +230,6 @@
   (*current_liboctave_error_handler) ("invalid password object");
 }
 
-void
-octave_passwd::gripe_not_supported (const string& fcn) const
-{
-  (*current_liboctave_error_handler)
-    ("%s: not supported on this system", fcn.c_str ());
-}
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/oct-passwd.h
+++ b/liboctave/oct-passwd.h
@@ -46,21 +46,21 @@
   { }
 
   octave_passwd& operator = (const octave_passwd& pw)
-    {
-      if (this != &pw)
-	{
-	  pw_name = pw.pw_name;
-	  pw_passwd = pw.pw_passwd;
-	  pw_uid = pw.pw_uid;
-	  pw_gid = pw.pw_gid;
-	  pw_gecos = pw.pw_gecos;
-	  pw_dir = pw.pw_dir;
-	  pw_shell = pw.pw_shell;
-	  valid = pw.valid;
-	}
+  {
+    if (this != &pw)
+      {
+	pw_name = pw.pw_name;
+	pw_passwd = pw.pw_passwd;
+	pw_uid = pw.pw_uid;
+	pw_gid = pw.pw_gid;
+	pw_gecos = pw.pw_gecos;
+	pw_dir = pw.pw_dir;
+	pw_shell = pw.pw_shell;
+	valid = pw.valid;
+      }
 
-      return *this;
-    }
+    return *this;
+  }
 
   ~octave_passwd (void) { }
 
@@ -85,14 +85,19 @@
 	? static_cast<void *> (-1) : static_cast<void *> (0); }
 
   static octave_passwd getpwent (void);
+  static octave_passwd getpwent (string& msg);
 
   static octave_passwd getpwuid (uid_t uid);
+  static octave_passwd getpwuid (uid_t uid, string& msg);
 
   static octave_passwd getpwnam (const string& nm);
+  static octave_passwd getpwnam (const string& nm, string& msg);
 
-  static void setpwent (void);
+  static int setpwent (void);
+  static int setpwent (string& msg);
 
-  static void endpwent (void);
+  static int endpwent (void);
+  static int endpwent (string& msg);
 
 private:
 
@@ -122,11 +127,9 @@
 
   // This is how we will create an octave_passwd object from a pointer
   // to a struct passwd.
-  octave_passwd (void *);
+  octave_passwd (void *p, string& msg);
 
   void gripe_invalid (void) const;
-
-  void gripe_not_supported (const string& fcn) const;
 };
 
 #endif
--- a/liboctave/str-vec.cc
+++ b/liboctave/str-vec.cc
@@ -29,6 +29,7 @@
 #include <iostream.h>
 
 #include "cmd-edit.h"
+#include "lo-utils.h"
 #include "str-vec.h"
 
 // Create a string vector from a NULL terminated list of C strings.
@@ -57,6 +58,30 @@
     elem (i) = s[i];
 }
 
+char **
+string_vector::c_str_vec (void) const
+{
+  int len = length ();
+
+  char **retval = new char * [len + 1];
+
+  retval [len] = 0;
+
+  for (int i = 0; i < len; i++)
+    retval[i] = strsave (elem(i).c_str ());
+
+  return retval;
+}
+
+void
+string_vector::delete_c_str_vec (const char * const *v)
+{
+  while (*v)
+    delete [] *v;
+
+  delete [] v;
+}
+
 // Format a list in neat columns.  Mostly stolen from GNU ls.
 
 ostream&
--- a/liboctave/str-vec.h
+++ b/liboctave/str-vec.h
@@ -95,6 +95,10 @@
       return *this;
     }
 
+  char **c_str_vec (void) const;
+
+  static void delete_c_str_vec (const char * const*);
+
   ostream& list_in_columns (ostream&) const;
 };
 
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,7 +1,15 @@
+Tue May  6 00:48:59 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* DLD-FUNCTIONS/getgrent.cc: Use new octave_group class.
+	* DLD-FUNCTIONS/getpwent.cc: Use new octave_passwd class.
+
+	* syscalls.cc: Simplify by using new functions defined in
+	liboctave/oct-syscalls.cc.
+
+	* file-io.cc (Ftmpnam): Accept DIR and PREFIX args.
+
 Mon May  5 00:54:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
-	* DLD-FUNCTIONS/getpwent.cc: Use new octave_passwd class.
-
 	* ov-str-mat.cc (octave_char_matrix_str::print_name_tag): Print
 	empty strings on one line.
 
--- a/src/DLD-FUNCTIONS/getgrent.cc
+++ b/src/DLD-FUNCTIONS/getgrent.cc
@@ -30,9 +30,7 @@
 #include <sys/types.h>
 #endif
 
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
+#include "oct-group.h"
 
 #include "defun-dld.h"
 #include "error.h"
@@ -46,7 +44,7 @@
 // Group file functions.  (Why not?)
 
 static octave_value
-mk_gr_map (struct group *gr)
+mk_gr_map (const octave_group& gr)
 {
   octave_value retval;
 
@@ -54,40 +52,10 @@
     {
       Octave_map m;
 
-      m ["name"] = gr->gr_name;
-#if defined (HAVE_GR_PASSWD)
-      m ["passwd"] = gr->gr_passwd;
-#else
-      m ["passwd"] = "";
-#endif
-      m ["gid"] = static_cast<double> (gr->gr_gid);
-
-      if (gr->gr_mem)
-	{
-	  // XXX FIXME XXX -- maybe there should be a string_vector
-	  // constructor that takes a NULL terminated list of C
-	  // strings.
-
-	  char **tmp = gr->gr_mem;
-
-	  int k = 0;
-	  while (*tmp++)
-	    k++;
-
-	  if (k > 0)
-	    {
-	      tmp = gr->gr_mem;
-
-	      string_vector members (k);
-
-	      for (int i = 0; i < k; i++)
-		members[i] = tmp[i];
-
-	      m ["mem"] = members;
-	    }
-	  else
-	    m ["mem"] = "";
-	}
+      m ["name"] = gr.name ();
+      m ["passwd"] = gr.passwd ();
+      m ["gid"] = static_cast<double> (gr.gid ());
+      m ["mem"] = gr.mem ();
 
       retval = m;
     }
@@ -102,17 +70,19 @@
 \n\
 Read an entry from the group-file stream, opening it if necessary.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = 0.0;
 
   int nargin = args.length ();
 
   if (nargin == 0)
     {
-#ifdef HAVE_GETGRENT
-      retval = mk_gr_map (getgrent ());
-#else
-      gripe_not_supported ("getgrent");
-#endif
+      string msg;
+
+      retval(0) = mk_gr_map (octave_group::getgrent (msg));
+      retval(1) = msg;
     }
   else
     print_usage ("getgrent");
@@ -125,13 +95,15 @@
 \n\
 Search for a group entry with a matching group ID.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = 0.0;
 
   int nargin = args.length ();
 
   if (nargin == 1)
     {
-#ifdef HAVE_GETGRGID
       double dval = args(0).double_value ();
 
       if (! error_state)
@@ -140,14 +112,14 @@
 	    {
 	      gid_t gid = static_cast<gid_t> (dval);
 
-	      retval = mk_gr_map (getgrgid (gid));
+	      string msg;
+
+	      retval(0) = mk_gr_map (octave_group::getgrgid (gid, msg));
+	      retval(1) = msg;
 	    }
 	  else
 	    error ("getgrgid: argument must be an integer");
 	}
-#else
-      gripe_not_supported ("getgrgid");
-#endif
     }
   else
     print_usage ("getgrgid");
@@ -160,20 +132,24 @@
 \n\
 Search for group entry with a matching group name.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = 0.0;
 
   int nargin = args.length ();
 
   if (nargin == 1)
     {
-#ifdef HAVE_GETGRNAM
       string s = args(0).string_value ();
 
       if (! error_state)
-	retval = mk_gr_map (getgrnam (s.c_str ()));
-#else
-      gripe_not_supported ("getgrnam");
-#endif
+	{
+	  string msg;
+
+	  retval(0) = mk_gr_map (octave_group::getgrnam (s.c_str (), msg));
+	  retval(1) = msg;
+	}
     }
   else
     print_usage ("getgrnam");
@@ -186,17 +162,19 @@
 \n\
 Rewind the group-file stream.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = -1.0;
 
   int nargin = args.length ();
 
   if (nargin == 0)
     {
-#ifdef HAVE_SETGRENT
-      setgrent ();
-#else
-      gripe_not_supported ("setgrent");
-#endif
+      string msg;
+
+      retval(0) = static_cast<double> (octave_group::setgrent (msg));
+      retval(1) = msg;
     }
   else
     print_usage ("setgrent");
@@ -209,17 +187,19 @@
 \n\
 Close the group-file stream.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = -1.0;
 
   int nargin = args.length ();
 
   if (nargin == 0)
     {
-#ifdef HAVE_ENDGRENT
-      endgrent ();
-#else
-      gripe_not_supported ("endgrent");
-#endif
+      string msg;
+
+      retval(0) = static_cast<double> (octave_group::endgrent (msg));
+      retval(1) = msg;
     }
   else
     print_usage ("endgrent");
--- a/src/DLD-FUNCTIONS/getpwent.cc
+++ b/src/DLD-FUNCTIONS/getpwent.cc
@@ -73,12 +73,20 @@
 \n\
 Read an entry from the password-file stream, opening it if necessary.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = 0.0;
 
   int nargin = args.length ();
 
   if (nargin == 0)
-    retval = mk_pw_map (octave_passwd::getpwent ());
+    {
+      string msg;
+
+      retval(0) = mk_pw_map (octave_passwd::getpwent (msg));
+      retval(1) = msg;
+    }
   else
     print_usage ("getpwent");
 
@@ -90,7 +98,10 @@
 \n\
 Search for a password entry with a matching user ID.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = 0.0;
 
   int nargin = args.length ();
 
@@ -104,7 +115,10 @@
 	    {
 	      uid_t uid = static_cast<uid_t> (dval);
 
-	      retval = mk_pw_map (octave_passwd::getpwuid (uid));
+	      string msg;
+
+	      retval(0) = mk_pw_map (octave_passwd::getpwuid (uid, msg));
+	      retval(1) = msg;
 	    }
 	  else
 	    error ("getpwuid: argument must be an integer");
@@ -121,7 +135,10 @@
 \n\
 Search for password entry with a matching username.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = 0.0;
 
   int nargin = args.length ();
 
@@ -130,7 +147,12 @@
       string s = args(0).string_value ();
 
       if (! error_state)
-	retval = mk_pw_map (octave_passwd::getpwnam (s.c_str ()));
+	{
+	  string msg;
+
+	  retval(0) = mk_pw_map (octave_passwd::getpwnam (s.c_str (), msg));
+	  retval(1) = msg;
+	}
     }
   else
     print_usage ("getpwnam");
@@ -143,12 +165,20 @@
 \n\
 Rewind the password-file stream.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = -1.0;
 
   int nargin = args.length ();
 
   if (nargin == 0)
-    octave_passwd::setpwent ();
+    {
+      string msg;
+
+      retval(0) = static_cast<double> (octave_passwd::setpwent (msg));
+      retval(1) = msg;
+    }
   else
     print_usage ("setpwent");
 
@@ -160,12 +190,20 @@
 \n\
 Close the password-file stream.")
 {
-  octave_value retval;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = -1.0;
 
   int nargin = args.length ();
 
   if (nargin == 0)
-    octave_passwd::endpwent ();
+    {
+      string msg;
+
+      retval(0) = static_cast<double> (octave_passwd::endpwent (msg));
+      retval(1) = msg;
+    }
   else
     print_usage ("endpwent");
 
--- a/src/syscalls.cc
+++ b/src/syscalls.cc
@@ -46,6 +46,7 @@
 
 #include "file-ops.h"
 #include "file-stat.h"
+#include "oct-syscalls.h"
 
 #include "defun.h"
 #include "error.h"
@@ -106,7 +107,6 @@
 
   if (nargin == 2)
     {
-#if defined (HAVE_DUP2)
       double d_old = args(0).double_value ();
       double d_new = args(1).double_value ();
 
@@ -120,12 +120,12 @@
 	      // XXX FIXME XXX -- are these checks sufficient?
 	      if (i_old >= 0 && i_new >= 0)
 		{
-		  int status = dup2 (i_old, i_new);
+		  string msg;
+
+		  int status = octave_syscalls::dup2 (i_old, i_new, msg);
 
 		  retval(0) = static_cast<double> (status);
-
-		  if (status < 0)
-		    retval(1) = strerror (errno);
+		  retval(1) = msg;
 		}
 	      else
 		error ("dup2: invalid file id");
@@ -133,9 +133,6 @@
 	  else
 	    error ("dup2: arguments must be integer values");
 	}
-#else
-      gripe_not_supported ("dup2");
-#endif
     }
   else
     print_usage ("dup2");
@@ -160,65 +157,49 @@
 
   if (nargin == 1 || nargin == 2)
     {
-#if defined (HAVE_EXECVP)
       string exec_file = args(0).string_value ();
 
       if (! error_state)
 	{
-	  char **exec_args = 0;
+	  string_vector exec_args;
 
 	  if (nargin == 2)
 	    {
-	      charMatrix chm = args(1).all_strings ();
+	      string_vector tmp = args(1).all_strings ();
 
 	      if (! error_state)
 		{
-		  int nr = chm.rows ();
-		  int nc = chm.cols ();
-
-		  exec_args = new char * [nr+2];
+		  int len = tmp.length ();
 
-		  // XXX FIXME XXX -- potential leak?
-
-		  exec_args[0] = strsave (exec_file.c_str ());
-		  exec_args[nr+1] = 0;
+		  exec_args.resize (len + 1);
 
-		  for (int i = 0; i < nr; i++)
-		    {
-		      exec_args[i+1] = new char [nc+1];
+		  exec_args[0] = exec_file;
 
-		      for (int j = 0; j < nc; j++)
-			exec_args[i+1][j] = chm (i, j);
-
-		      exec_args[i+1][nc] = '\0';
-		    }
+		  for (int i = 0; i < len; i++)
+		    exec_args[i+1] = tmp[i];
 		}
 	      else
 		error ("exec: arguments must be strings");
 	    }
 	  else
 	    {
-	      exec_args = new char * [2];
+	      exec_args.resize (1);
 
-	      exec_args[0] = strsave (exec_file.c_str ());
-	      exec_args[1] = 0;
+	      exec_args[0] = exec_file;
 	    }
 
 	  if (! error_state)
 	    {
-	      int status = execvp (exec_file.c_str (), exec_args);
+	      string msg;
+
+	      int status = octave_syscalls::execvp (exec_file, exec_args, msg);
 
 	      retval(0) = static_cast<double> (status);
-
-	      if (status < 0)
-		retval(1) = strerror (errno);
+	      retval(1) = msg;
 	    }
 	}
       else
 	error ("exec: first argument must be a string");
-#else
-      gripe_not_supported ("exec");
-#endif
     }
   else
     print_usage ("exec");
@@ -243,7 +224,6 @@
 
   if (nargin == 3)
     {
-#if defined (HAVE_FCNTL)
       double d_fid = args(0).double_value ();
       double d_req = args(1).double_value ();
       double d_arg = args(2).double_value ();
@@ -262,19 +242,16 @@
 	    error ("fcntl: invalid file id");
 	  else
 	    {
-	      int status = fcntl (fid, req, arg);
+	      string msg;
+
+	      int status = octave_syscalls::fcntl (fid, req, arg, msg);
 
 	      retval(0) = static_cast<double> (status);
-
-	      if (status < 0)
-		retval(1) = strerror (errno);
+	      retval(1) = msg;
 	    }
 	}
       else
 	error ("fcntl: file id must be an integer");
-#else
-      gripe_not_supported ("fcntl");
-#endif
     }
   else
     print_usage ("fcntl");
@@ -300,16 +277,12 @@
 
   if (nargin == 0)
     {
-#if defined (HAVE_FORK)
-      pid_t pid = fork ();
+      string msg;
+
+      pid_t pid = octave_syscalls::fork (msg);
 
       retval(0) = static_cast<double> (pid);
-
-      if (pid < 0)
-	retval(1) = strerror (errno);
-#else
-      gripe_not_supported ("fork");
-#endif
+      retval(1) = msg;
     }
   else
     print_usage ("fork");
@@ -320,17 +293,19 @@
 DEFUN (getpgrp, args, ,
   "pgid = getpgrp (): return the process group id of the current process")
 {
-  double retval = -1.0;
+  octave_value_list retval;
+
+  retval(1) = string ();
+  retval(0) = -1.0;
 
   int nargin = args.length ();
 
   if (nargin == 0)
     {
-#if defined (HAVE_GETPGRP)
-      retval = getpgrp ();
-#else
-      gripe_not_supported ("getpgrp");
-#endif
+      string msg;
+
+      retval(0) = static_cast<double> (octave_syscalls::getpgrp (msg));
+      retval(1) = msg;
     }
   else
     print_usage ("getpgrp");
@@ -346,13 +321,7 @@
   int nargin = args.length ();
 
   if (nargin == 0)
-    {
-#if defined (HAVE_GETPID)
-      retval = getpid ();
-#else
-      gripe_not_supported ("getpid");
-#endif
-    }
+    retval = octave_syscalls::getpid ();
   else
     print_usage ("getpid");
 
@@ -367,13 +336,7 @@
   int nargin = args.length ();
 
   if (nargin == 0)
-    {
-#if defined (HAVE_GETPPID)
-      retval = getppid ();
-#else
-      gripe_not_supported ("getppid");
-#endif
-    }
+    retval = octave_syscalls::getppid ();
   else
     print_usage ("getppid");
 
@@ -388,13 +351,7 @@
   int nargin = args.length ();
 
   if (nargin == 0)
-    {
-#if defined (HAVE_GETEGID)
-      retval = getegid ();
-#else
-      gripe_not_supported ("getegid");
-#endif
-    }
+    retval = octave_syscalls::getegid ();
   else
     print_usage ("getegid");
 
@@ -409,13 +366,7 @@
   int nargin = args.length ();
 
   if (nargin == 0)
-    {
-#if defined (HAVE_GETGID)
-      retval = getgid ();
-#else
-      gripe_not_supported ("getgid");
-#endif
-    }
+    retval = octave_syscalls::getgid ();
   else
     print_usage ("getgid");
 
@@ -430,13 +381,7 @@
   int nargin = args.length ();
 
   if (nargin == 0)
-    {
-#if defined (HAVE_GETEUID)
-      retval = geteuid ();
-#else
-      gripe_not_supported ("geteuid");
-#endif
-    }
+    retval = octave_syscalls::geteuid ();
   else
     print_usage ("geteuid");
 
@@ -451,13 +396,7 @@
   int nargin = args.length ();
 
   if (nargin == 0)
-    {
-#if defined (HAVE_GETUID)
-      retval = getuid ();
-#else
-      gripe_not_supported ("getuid");
-#endif
-    }
+    retval = octave_syscalls::getuid ();
   else
     print_usage ("getuid");
 
@@ -540,7 +479,6 @@
 	}
       else
 	error ("mkfifo: file name must be a string");
-
     }
   else
     print_usage ("mkfifo");
@@ -567,15 +505,14 @@
 
   if (nargin == 0)
     {
-#if defined (HAVE_PIPE)
       int fid[2];
 
-      int status = pipe (fid);
+      string msg;
+
+      int status = octave_syscalls::pipe (fid, msg);
 
       if (status < 0)
-	{
-	  retval(2) = strerror (errno);
-	}
+	retval(2) = msg;
       else
 	{
 	  FILE *in_file = fdopen (fid[0], "r");
@@ -595,9 +532,6 @@
 	  retval(1) = static_cast<double> (status);
           retval(0) = octave_value (file_ids);
 	}
-#else
-      gripe_not_supported ("pipe");
-#endif
     }
   else
     print_usage ("pipe");
@@ -687,9 +621,7 @@
 	  int status = file_ops::unlink (name, msg);
 
 	  retval(0) = static_cast<double> (status);
-
-	  if (status < 0)
-	    retval(1) = msg;	    
+	  retval(1) = msg;	    
 	}
       else
 	error ("unlink: file name must be a string");
@@ -736,7 +668,6 @@
 
   if (nargin == 1 || nargin == 2)
     {
-#if defined (HAVE_WAITPID)
       double pid_num = args(0).double_value ();
   
       if (! error_state)
@@ -768,18 +699,16 @@
 
 	      if (! error_state)
 		{
-		  pid_t status = waitpid (pid, 0, options);
+		  string msg;
+
+		  pid_t status
+		    = octave_syscalls::waitpid (pid, options, msg);
 
 		  retval(0) = static_cast<double> (status);
-
-		  if (status < 0)
-		    retval(1) = strerror (errno);
+		  retval(1) = msg;
 		}
 	    }
 	}
-#else
-      gripe_not_supported ("waitpid");
-#endif
     }
   else
     print_usage ("waitpid");