From dfa0b672ab9bb64c57c3815fcf3004891bd33e5f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Tue, 21 Jan 1997 21:15:28 -0800
Subject: [PATCH] gethostbyname fixed, socket->query_address() added,
 module_support added

Rev: src/Makefile.in:1.6
Rev: src/module_support.c:1.1
Rev: src/module_support.h:1.1
Rev: src/modules/files/configure.in:1.10
Rev: src/modules/files/efuns.c:1.6
Rev: src/modules/files/file.c:1.22
Rev: src/modules/files/file.h:1.2
Rev: src/modules/files/file_machine.h.in:1.5
Rev: src/modules/files/socket.c:1.5
Rev: src/modules/system/configure.in:1.3
Rev: src/modules/system/system.c:1.4
Rev: src/modules/system/system_machine.h.in:1.3
---
 src/Makefile.in                        |   1 +
 src/module_support.c                   | 136 ++++++++
 src/module_support.h                   |  22 ++
 src/modules/files/configure.in         |  71 +---
 src/modules/files/efuns.c              |  61 +++-
 src/modules/files/file.c               |  75 +---
 src/modules/files/file.h               |   4 +-
 src/modules/files/file_machine.h.in    |  12 +-
 src/modules/files/socket.c             |  29 ++
 src/modules/system/configure.in        |  49 +++
 src/modules/system/system.c            | 458 +++++++++++--------------
 src/modules/system/system_machine.h.in |   8 +-
 12 files changed, 506 insertions(+), 420 deletions(-)
 create mode 100644 src/module_support.c
 create mode 100644 src/module_support.h

diff --git a/src/Makefile.in b/src/Makefile.in
index 0fd84dd713..27379f4372 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -88,6 +88,7 @@ OBJ= \
  mapping.o \
  memory.o \
  module.o \
+ module_support.o \
  object.o \
  opcodes.o \
  operators.o \
diff --git a/src/module_support.c b/src/module_support.c
new file mode 100644
index 0000000000..87650116a1
--- /dev/null
+++ b/src/module_support.c
@@ -0,0 +1,136 @@
+#include "global.h"
+#include "module_support.h"
+#include "interpret.h"
+#include "svalue.h"
+#include "stralloc.h"
+
+void check_args(const char *fnname, int args, int minargs, ... )
+{
+  va_list arglist;
+  int argno;
+  
+  if (args < minargs) {
+    error("Too few arguments to %s()\n", fnname);
+  }
+
+  va_start(arglist, minargs);
+
+  for (argno=0; argno < minargs; argno++)
+  {
+    int type_mask = va_arg(arglist, unsigned INT32);
+
+    if (!((1UL << sp[argno-args].type) & type_mask))
+    {
+      va_end(arglist);
+      error("Bad argument %d to %s()\n", argno+1, fnname);
+    }
+  }
+
+  va_end(arglist);
+}
+
+/* This function does NOT generate errors, it simply returns how
+ * many arguments were actually matched.
+ * usage: get_args(sp-args, args, "%i",&an_int)
+ * format specifiers:
+ *   %i: INT32
+ *   %s: char *
+ *   %S: struct pike_string *
+ *   %a: struct array *
+ *   %f: float
+ *   %m: struct mapping *
+ *   %M: struct multiset *
+ *   %o: struct object *
+ *   %p: struct program *
+ *   %*: struct svalue *
+ */
+
+int va_get_args(struct svalue *s,
+		INT32 num_args,
+		char *fmt,
+		va_list ap)
+{
+  int ret=0;
+  while(*fmt)
+  {
+    if(*fmt != '%')
+      fatal("Error in format for get_args.\n");
+
+    if(ret == num_args) return ret;
+
+    switch(*++fmt)
+    {
+    case 'd':
+      if(s->type != T_INT) return ret;
+      *va_arg(ap, int *)=s->u.integer;
+      break;
+    case 'i':
+      if(s->type != T_INT) return ret;
+      *va_arg(ap, INT32 *)=s->u.integer; break;
+    case 's':
+      if(s->type != T_STRING) return ret;
+      *va_arg(ap, char **)=s->u.string->str;
+      break;
+    case 'S':
+      if(s->type != T_STRING) return ret;
+      *va_arg(ap, struct pike_string **)=s->u.string;
+      break;
+    case 'a':
+      if(s->type != T_ARRAY) return ret;
+      *va_arg(ap, struct array **)=s->u.array;
+      break;
+    case 'f':
+      if(s->type != T_ARRAY) return ret;
+      *va_arg(ap, float *)=s->u.float_number;
+      break;
+    case 'm':
+      if(s->type != T_MAPPING) return ret;
+      *va_arg(ap, struct mapping **)=s->u.mapping;
+      break;
+    case 'M':
+      if(s->type != T_MULTISET) return ret;
+      *va_arg(ap, struct multiset **)=s->u.multiset;
+      break;
+    case 'o':
+      if(s->type != T_OBJECT) return ret;
+      *va_arg(ap, struct object **)=s->u.object;
+      break;
+    case 'p':
+      if(s->type != T_PROGRAM) return ret;
+      *va_arg(ap, struct program **)=s->u.program;
+      break;
+    case '*':
+      *va_arg(ap, struct svalue **)=s;
+      break;
+      
+    default:
+      fatal("Unknown format character in get_args.\n");
+    }
+    ret++;
+    s++;
+    fmt++;
+  }
+  return ret;
+}
+
+int get_args(struct svalue *s,
+	     INT32 num_args,
+	     char *fmt, ...)
+{
+  va_list ptr;
+  int ret;
+  va_start(ptr, fmt);
+  ret=va_get_args(s, num_args, fmt, ptr);
+  va_end(fmt);
+}
+
+void get_all_args(char *fname, INT32 args, char *format,  ... )
+{
+  va_list ptr;
+  int ret;
+  va_start(ptr, format);
+  ret=va_get_args(sp-args, args, format, ptr);
+  va_end(ptr);
+  if((long)ret != (long)strlen(format) / 2)
+    error("Bad argument %d to %s()\n", ret+1, fname);
+}
diff --git a/src/module_support.h b/src/module_support.h
new file mode 100644
index 0000000000..791535e129
--- /dev/null
+++ b/src/module_support.h
@@ -0,0 +1,22 @@
+/*\
+||| This file a part of Pike, and is copyright by Fredrik Hubinette
+||| Pike is distributed as GPL (General Public License)
+||| See the files COPYING and DISCLAIMER for more information.
+\*/
+
+#ifndef MODULE_SUPPORT_H
+#include <stdarg.h>
+
+/* Prototypes begin here */
+void check_args(const char *fnname, int args, int minargs, ... );
+int va_get_args(struct svalue *s,
+		INT32 num_args,
+		char *fmt,
+		va_list ptr);
+int get_args(struct svalue *s,
+	     INT32 num_args,
+	     char *fmt, ...);
+void get_all_args(char *fname, INT32 args, char *format,  ... );
+/* Prototypes end here */
+
+#endif
diff --git a/src/modules/files/configure.in b/src/modules/files/configure.in
index d3d96f6fb4..74c57f96c1 100644
--- a/src/modules/files/configure.in
+++ b/src/modules/files/configure.in
@@ -14,77 +14,8 @@ AC_HAVE_HEADERS(arpa/inet.h sys/socketvar.h netinet/in.h \
  sys/stream.h sys/protosw.h netdb.h)
 AC_HEADER_DIRENT
 AC_CHECK_LIB(socket, socket)
-AC_CHECK_LIB(nsl, gethostbyname)
-
-AC_HAVE_FUNCS(socketpair getwd perror fork1)
-
-AC_MSG_CHECKING(for solaris style gethostbyname_r)
-
-AC_CACHE_VAL(pike_cv_have_solaris_gethostbyname_r,
-[
-AC_TRY_LINK([
-#define _REENTRANT
-#include <netdb.h>
-],[
-  char data[2000];
-  int h_errno;
-  struct hostent result,*bar;
-  gethostbyname_r("foo",&result, data, sizeof(data), h_errno)->h_name;
-],pike_cv_have_solaris_gethostbyname_r=yes,
-pike_cv_have_solaris_gethostbyname_r=no)
-])
-
-AC_MSG_RESULT($pike_cv_have_solaris_gethostbyname_r)
-
-if test $pike_cv_have_solaris_gethostbyname_r = yes; then
-  AC_DEFINE(HAVE_SOLARIS_GETHOSTBYNAME_R)
-fi
-
-
-AC_MSG_CHECKING(for OSF1 style gethostbyname_r)
-
-AC_CACHE_VAL(pike_cv_have_osf1_gethostbyname_r,
-[
-AC_TRY_LINK([
-#define _THREAD_SAFE
-#include <netdb.h>
-],[
-  int bar;
-  struct hostent result;
-  struct hostent_data data;
-  bar=gethostbyname_r("foo",&result, &data);
-],pike_cv_have_osf1_gethostbyname_r=yes,
-pike_cv_have_osf1_gethostbyname_r=no)
-])
-
-AC_MSG_RESULT($pike_cv_have_osf1_gethostbyname_r)
-
-if test $pike_cv_have_osf1_gethostbyname_r = yes; then
-  AC_DEFINE(HAVE_OSF1_GETHOSTBYNAME_R)
-fi
-
-AC_MSG_CHECKING(for h_addr_list)
-AC_CACHE_VAL(pike_cv_struct_has_h_addr_list,
-[
-AC_TRY_LINK([
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-],[
-struct hostent foo;
-foo.h_addr_list[0];
-],pike_cv_struct_has_h_addr_list=yes,pike_cv_struct_has_h_addr_list=no)
-])
-
-if test "$pike_cv_struct_has_h_addr_list" = yes; then
-  AC_MSG_RESULT(yes)
-  AC_DEFINE(HAVE_H_ADDR_LIST)
-else
-  AC_MSG_RESULT(no)
-fi
 
+AC_HAVE_FUNCS(socketpair getwd perror fork1 readdir_r)
 
 AC_MSG_CHECKING(for working (and failsafe) strerror)
 AC_CACHE_VAL(pike_cv_func_failsafe_strerror,
diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c
index dc94929498..9ef8ce799f 100644
--- a/src/modules/files/efuns.c
+++ b/src/modules/files/efuns.c
@@ -13,6 +13,7 @@
 #include "macros.h"
 #include "fd_control.h"
 #include "threads.h"
+#include "module_support.h"
 
 #include "file_machine.h"
 
@@ -167,14 +168,61 @@ void f_get_dir(INT32 args)
   DIR *dir;
   struct dirent *d;
   struct array *a=0;
+  char *path;
 
-  if(!args)
-    error("Too few arguments to get_dir()\n");
-
-  if(sp[-args].type != T_STRING)
-    error("Bad argument 1 to get_dir()\n");
+  get_all_args("get_dir",args,"%s",&path);
 
-  dir=opendir(sp[-args].u.string->str);
+#if defined(_REENTRANT) && defined(HAVE_READDIR_R)
+  THREADS_ALLOW();
+  dir=opendir(path);
+  THREADS_DISALLOW();
+  if(dir)
+  {
+#define FPR 1024
+    char buffer[MAXPATHLEN * 4];
+    char ptrs[FPR];
+    int lens[FPR];
+    
+    while(1)
+    {
+      int e;
+      struct dirent tmp;
+      int num_files=0;
+      char *bufptr=buffer;
+      THREADS_ALLOW();
+      while(1)
+      {
+	d=readdir_r(dir, &tmp);
+	if(d->d_name[0]=='.')
+	{
+	  if(!d->d_name[1]) continue;
+	  if(d->d_name[1]=='.' && !d->d_name[2]) continue;
+	}
+	if(num_files >= FPR) break;
+	lens[num_files]=NAMLEN(d);
+	if(ptr+lens[num_files] >= buffer+sizeof(buffer)) break;
+	MEMCPY(ptr, d->d_name, lens[num_files]);
+	ptrs[num_files]=ptr;
+	ptr+=len;
+	num_files++;
+      }
+      THREADS_DISALLOW();
+      for(e=0;e<num_files;e++)
+      {
+	push_string(make_shared_string(ptrs[e],lens[e]));
+      }
+      if(d)
+	push_string(make_shared_binary_string(d->d_name,NAMLEN(d)));
+      else
+	break;
+    }
+    THREADS_ALLOW();
+    closedir(dir);
+    THREADS_DISALLOW();
+    a=aggregate_array(sp-save_sp);
+  }
+#else
+  dir=opendir(path);
   if(dir)
   {
     for(d=readdir(dir); d; d=readdir(dir))
@@ -189,6 +237,7 @@ void f_get_dir(INT32 args)
     closedir(dir);
     a=aggregate_array(sp-save_sp);
   }
+#endif
 
   pop_n_elems(args);
   if(a)
diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index 79435279ef..5d142256e4 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -6,7 +6,7 @@
 #define READ_BUFFER 16384
 
 #include "global.h"
-RCSID("$Id: file.c,v 1.21 1997/01/18 22:00:10 hubbe Exp $");
+RCSID("$Id: file.c,v 1.22 1997/01/22 05:14:59 hubbe Exp $");
 #include "types.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -1244,78 +1244,6 @@ static int isipnr(char *s)
   return 1;
 }
 
-void get_inet_addr(struct sockaddr_in *addr,char *name)
-{
-  MEMSET((char *)addr,0,sizeof(struct sockaddr_in));
-
-  addr->sin_family = AF_INET;
-  if(!strcmp(name,"*"))
-  {
-    addr->sin_addr.s_addr=htonl(INADDR_ANY);
-  }
-  else if(isipnr(name))
-  {
-    if ((long)inet_addr(name) == (long)-1)
-      error("Malformed ip number.\n");
-
-    addr->sin_addr.s_addr = inet_addr(name);
-  }
-  else
-  {
-    struct hostent *ret;
-#ifdef _REENTRANT
-#ifdef HAVE_SOLARIS_GETHOSTBYNAME_R
-    struct hostent result;
-    char data[2048];
-    int h_errno;
-
-    THREADS_ALLOW();
-    ret=gethostbyname_r(name, &result, data, sizeof(data), &h_errno);
-    THREADS_DISALLOW();
-#else
-#ifdef HAVE_OSF1_GETHOSTBYNAME_R
-    struct hostent result;
-    struct hostent_data data;
-
-    THREADS_ALLOW();
-    MEMSET((char *)&data,0,sizeof(data));
-    if(gethostbyname_r(name, &result, &data) < 0)
-    {
-      ret=0;
-    }else{
-      ret=&result;
-    }
-    THREADS_DISALLOW();
-#else
-    static MUTEX_T l;
-
-    THREADS_ALLOW();
-
-    mt_lock(&l);
-    ret=gethostbyname(name);
-    mt_unlock(&l);
-
-    THREADS_DISALLOW();
-#endif
-#endif
-#else
-    ret=gethostbyname(name);
-#endif
-    if(!ret)
-      error("Invalid address '%s'\n",name);
-
-#ifdef HAVE_H_ADDR_LIST
-    MEMCPY((char *)&(addr->sin_addr),
-	   (char *)ret->h_addr_list[0],
-	   ret->h_length);
-#else
-    MEMCPY((char *)&(addr->sin_addr),
-	   (char *)ret->h_addr,
-	   ret->h_length);
-#endif
-  }
-}
-
 static void file_query_address(INT32 args)
 {
   struct sockaddr_in addr;
@@ -1337,6 +1265,7 @@ static void file_query_address(INT32 args)
   {
     ERRNO=errno;
     push_int(0);
+    return;
   }
 
   q=inet_ntoa(addr.sin_addr);
diff --git a/src/modules/files/file.h b/src/modules/files/file.h
index c82375cff4..4b871147b8 100644
--- a/src/modules/files/file.h
+++ b/src/modules/files/file.h
@@ -34,10 +34,12 @@ struct my_file
   struct svalue close_callback;
 };
 
+extern void get_inet_addr(struct sockaddr_in *addr,char *name);
+
 /* Prototypes begin here */
+struct file_struct;
 struct object *file_make_object_from_fd(int fd, int mode);
 int socketpair(int family, int type, int protocol, int sv[2]);
-void get_inet_addr(struct sockaddr_in *addr,char *name);
 void exit_files();
 void init_files_programs();
 /* Prototypes end here */
diff --git a/src/modules/files/file_machine.h.in b/src/modules/files/file_machine.h.in
index 75fe80ac77..ed7b4a9838 100644
--- a/src/modules/files/file_machine.h.in
+++ b/src/modules/files/file_machine.h.in
@@ -40,15 +40,12 @@
 /* Define if you have getwd.  */
 #undef HAVE_GETWD
 
-/* Define if you have solaris stype gethostbyname_r.  */
-#undef HAVE_SOLARIS_GETHOSTBYNAME_R
-
-/* Define if you have OSF1 stype gethostbyname_r.  */
-#undef HAVE_OSF1_GETHOSTBYNAME_R
-
 /* Define if you have fork1.  */
 #undef HAVE_FORK1
 
+/* Define if you have a solaris compatible readdir_r.  */
+#undef HAVE_READDIR_R
+
 /* Define if you have strerror.  */
 #undef HAVE_STRERROR
 
@@ -58,8 +55,5 @@
 /* Define this if you have perror() */
 #undef HAVE_PERROR
 
-/* Define this if your struct hostent has h_addr_list */
-#undef HAVE_H_ADDR_LIST
-
 #endif
 
diff --git a/src/modules/files/socket.c b/src/modules/files/socket.c
index ad8fe91869..3ebf4a9b1a 100644
--- a/src/modules/files/socket.c
+++ b/src/modules/files/socket.c
@@ -308,6 +308,34 @@ static void port_accept(INT32 args)
   push_object(o);
 }
 
+static void socket_query_address(INT32 args)
+{
+  struct sockaddr_in addr;
+  int i,len;
+  char buffer[496],*q;
+
+  if(THIS->fd <0)
+    error("socket->query_address(): Socket not bound yet.\n");
+
+  len=sizeof(addr);
+  i=getsockname(THIS->fd,(struct sockaddr *)&addr,&len);
+  pop_n_elems(args);
+  if(i < 0 || len < (int)sizeof(addr))
+  {
+    THIS->my_errno=errno;
+    push_int(0);
+    return;
+  }
+
+  q=inet_ntoa(addr.sin_addr);
+  strncpy(buffer,q,sizeof(buffer)-20);
+  buffer[sizeof(buffer)-20]=0;
+  sprintf(buffer+strlen(buffer)," %d",(int)(ntohs(addr.sin_port)));
+
+  push_string(make_shared_string(buffer));
+}
+
+
 static void init_port_struct(struct object *o)
 {
   THIS->fd=-1;
@@ -338,6 +366,7 @@ void port_setup_program()
   add_function("listen_fd",port_listen_fd,"function(int,void|mixed:int)",0);
   add_function("set_id",port_set_id,"function(mixed:mixed)",0);
   add_function("query_id",port_query_id,"function(:mixed)",0);
+  add_function("query_address",socket_query_address,"function(:string)",0);
   add_function("errno",port_errno,"function(:int)",0);
   add_function("accept",port_accept,"function(:object)",0);
   add_function("create",port_create,"function(void|string,void|mixed:void)",0);
diff --git a/src/modules/system/configure.in b/src/modules/system/configure.in
index 0f6cd9d90d..1abb41da7d 100644
--- a/src/modules/system/configure.in
+++ b/src/modules/system/configure.in
@@ -17,6 +17,55 @@ AC_HAVE_HEADERS(sys/types.h errno.h unistd.h pwd.h sys/conf.h sys/socket.h netin
 
 AC_HAVE_FUNCS(link symlink readlink initgroups seteuid setresuid geteuid getpgrp getpgid getppid fchroot uname gethostname gethostbyname)
 
+
+AC_CHECK_LIB(nsl, gethostbyname)
+
+AC_MSG_CHECKING(for solaris style gethostbyname_r)
+
+AC_CACHE_VAL(pike_cv_have_solaris_gethostbyname_r,
+[
+AC_TRY_LINK([
+#define _REENTRANT
+#include <netdb.h>
+],[
+  char data[2000];
+  int h_errno;
+  struct hostent result,*bar;
+  gethostbyname_r("foo",&result, data, sizeof(data), h_errno)->h_name;
+],pike_cv_have_solaris_gethostbyname_r=yes,
+pike_cv_have_solaris_gethostbyname_r=no)
+])
+
+AC_MSG_RESULT($pike_cv_have_solaris_gethostbyname_r)
+
+if test $pike_cv_have_solaris_gethostbyname_r = yes; then
+  AC_DEFINE(HAVE_SOLARIS_GETHOSTBYNAME_R)
+fi
+
+
+AC_MSG_CHECKING(for OSF1 style gethostbyname_r)
+
+AC_CACHE_VAL(pike_cv_have_osf1_gethostbyname_r,
+[
+AC_TRY_LINK([
+#define _THREAD_SAFE
+#include <netdb.h>
+],[
+  int bar;
+  struct hostent result;
+  struct hostent_data data;
+  bar=gethostbyname_r("foo",&result, &data);
+],pike_cv_have_osf1_gethostbyname_r=yes,
+pike_cv_have_osf1_gethostbyname_r=no)
+])
+
+AC_MSG_RESULT($pike_cv_have_osf1_gethostbyname_r)
+
+if test $pike_cv_have_osf1_gethostbyname_r = yes; then
+  AC_DEFINE(HAVE_OSF1_GETHOSTBYNAME_R)
+fi
+
+
 AC_MSG_CHECKING(for h_addr_list)
 AC_CACHE_VAL(pike_cv_struct_has_h_addr_list,
 [
diff --git a/src/modules/system/system.c b/src/modules/system/system.c
index 7bce31eef0..03757c9bd3 100644
--- a/src/modules/system/system.c
+++ b/src/modules/system/system.c
@@ -1,5 +1,5 @@
 /*
- * $Id: system.c,v 1.3 1997/01/22 02:55:12 grubba Exp $
+ * $Id: system.c,v 1.4 1997/01/22 05:15:27 hubbe Exp $
  *
  * System-call module for Pike
  *
@@ -13,7 +13,8 @@
 #include "system_machine.h"
 
 #include <global.h>
-RCSID("$Id: system.c,v 1.3 1997/01/22 02:55:12 grubba Exp $");
+RCSID("$Id: system.c,v 1.4 1997/01/22 05:15:27 hubbe Exp $");
+#include <module_support.h>
 #include <las.h>
 #include <interpret.h>
 #include <stralloc.h>
@@ -127,86 +128,6 @@ static volatile void report_error(const char *function_name)
   error("%s(): Failed:%s\n", function_name, error_msg);
 }
 
-#if defined(HAVE_STDARG_H) || !defined(HAVE_VARARGS_H)
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#else
-/* Fallback to this if we have neither <stdarg.h> nor <varargs.h>.
- *
- * Should work on anything that passes all arguments on the stack,
- * and the stack grows downwards.
- *
- * /grubba 1997-01-21
- */
-#define va_list			void *
-#define va_start(var, last_var)	(var = (va_list)(&(last_var)+1))
-/* Could be a NOP as well */
-#define va_end(var)		(var = 0)
-/* Is the following line legal C? */
-#define va_arg(var, type)	(*(((type *)var)++))
-#endif /* HAVE_STDARG_H */
-
-static void check_args(const char *fnname, int args, int minargs, ... )
-{
-  va_list arglist;
-  int argno;
-  
-  if (args < minargs) {
-    error("Too few arguments to %s()\n", fnname);
-  }
-
-  va_start(arglist, minargs);
-
-  for (argno=0; argno < minargs; argno++) {
-    int type_mask = va_arg(arglist, unsigned INT32);
-
-    if (!((1UL << sp[argno-args].type) & type_mask)) {
-      va_end(arglist);
-      error("Bad argument %d to %s()\n", argno+1, fnname);
-    }
-  }
-
-  va_end(arglist);
-}
-
-#else /* Only HAVE_VARARGS_H */
-
-#include <varargs.h>
-
-static void check_args(va_alist)
-va_dcl
-{
-  const char *fnname;
-  int args;
-  int minargs;
-  va_list arglist;
-  int argno;
-
-  va_start(arglist);
-
-  fnname = va_arg(arglist, const char *);
-  args = va_arg(arglist, int);
-  minargs = va_arg(arglist, int);
-  
-  if (args < minargs) {
-    error("Too few arguments to %s()\n", fnname);
-  }
-
-  va_start(arglist, minargs);
-
-  for (argno=0; argno < minargs; argno++) {
-    int type_mask = va_arg(arglist, unsigned INT32);
-
-    if (!((1UL << sp[argno-args].type) & type_mask)) {
-      va_end(arglist);
-      error("Bad argument %d to %s()\n", argno+1, fnname);
-    }
-  }
-
-  va_end(arglist);
-}
-
-#endif /* HAVE_STDARG_H || !HAVE_VARARGS_H */
 
 /*
  * efuns
@@ -220,20 +141,7 @@ void f_hardlink(INT32 args)
   char *to;
   int err;
 
-  check_args("hardlink", args, 2, BIT_STRING, BIT_STRING);
-#if 0
-  if (args < 2) {
-    error("Too few arguments to hardlink()\n");
-  }
-  if (sp[-args].type != T_STRING) {
-    error("Bad argument 1 to hardlink()\n");
-  }
-  if (sp[1-args].type != T_STRING) {
-    error("Bad argument 2 to hardlink()\n");
-  }
-#endif /* 0 */
-  from = sp[-args].u.string->str;
-  to = sp[1-args].u.string->str;
+  get_all_args("hardlink",args, "%s%s", &from, &to);
 
   do {
     THREADS_ALLOW();
@@ -258,20 +166,7 @@ void f_symlink(INT32 args)
   char *to;
   int err;
 
-  check_args("symlink", args, 2, BIT_STRING, BIT_STRING);
-#if 0
-  if (args < 2) {
-    error("Too few arguments to symlink()\n");
-  }
-  if (sp[-args].type != T_STRING) {
-    error("Bad argument 1 to symlink()\n");
-  }
-  if (sp[1-args].type != T_STRING) {
-    error("Bad argument 2 to symlink()\n");
-  }
-#endif /* 0 */
-  from = sp[-args].u.string->str;
-  to = sp[1-args].u.string->str;
+  get_all_args("symlink",args, "%s%s", &from, &to);
 
   do {
     THREADS_ALLOW();
@@ -297,17 +192,7 @@ void f_readlink(INT32 args)
   char *buf;
   int err;
 
-  check_args("readlink", args, 1, BIT_STRING);
-#if 0
-  if (!args) {
-    error("Too few arguments to readlink()\n");
-  }
-  if (sp[-args].type != T_STRING) {
-    error("Bad argument 1 to readlink()\n");
-  }
-#endif /* 0 */
-
-  path = sp[-args].u.string->str;
+  get_all_args("readlink",args, "%s", &path);
 
   buflen = 100;
 
@@ -338,42 +223,21 @@ void f_readlink(INT32 args)
 /* void initgroups(string name, int gid) */
 void f_initgroups(INT32 args)
 {
-  check_args("initgroups", args, 2, BIT_STRING, BIT_INT);
-#if 0
-  if(args < 2) {
-    error("Too few arguments to initgroups()\n");
-  }
- 
-  if(sp[-args].type != T_STRING) {
-    error("Bad argument 1 to initgroups()\n");
-  }
-  if (sp[1-args].type != T_INT) {
-    error("Bad argument 2 to initgroups()\n");
-  }
-#endif /* 0 */
- 
-  initgroups(sp[-args].u.string->str, sp[1-args].u.integer);
-    
+  char *user;
+  INT32 group;
+  get_all_args("initgroups", args, "%s%i", &user, &group);
+  initgroups(user, group);
   pop_n_elems(args);
 }
 #endif /* HAVE_INITGROUPS */
  
 void f_setuid(INT32 args)
 {
-  int id;
+  INT32 id;
 
-  check_args("setuid", args, 1, BIT_INT);
-#if 0
-  if (!args) {
-    error("Too few arguments to setuid()\n");
-  }
+  get_all_args("setuid", args, "%i", &id);
  
-  if (sp[-args].type != T_INT) {
-    error("Bad argument 1 to setuid()\n");
-  }
-#endif /* 0 */
- 
-  if(sp[-args].u.integer == -1) {
+  if(id == -1) {
     struct passwd *pw = getpwnam("nobody");
     id = pw->pw_uid;
   } else {
@@ -388,18 +252,9 @@ void f_setgid(INT32 args)
 {
   int id;
 
-  check_args("setgid", args, 1, BIT_INT);
-#if 0
-  if (!args) {
-    error("Too few arguments to setgid()\n");
-  }
+  get_all_args("setgid", args, "%i", &id);
  
-  if(sp[-args].type != T_INT) {
-    error("Bad argumnet 1 to setgid()\n");
-  }
-#endif /* 0 */
- 
-  if(sp[-args].u.integer == -1) {
+  if(id == -1) {
     struct passwd *pw = getpwnam("nobody");
     id = pw->pw_gid;
   } else {
@@ -415,18 +270,9 @@ void f_seteuid(INT32 args)
 {
   int id;
 
-  check_args("seteuid", args, 1, BIT_INT);
-#if 0
-  if (!args) {
-    error("Too few arguments to seteuid()\n");
-  }
- 
-  if (sp[-args].type != T_INT) {
-    error("Bad argument 1 to seteuid()\n");
-  }
-#endif /* 0 */
+  get_all_args("seteuid", args, "%i", &id);
  
-  if(sp[-args].u.integer == -1) {
+  if(id == -1) {
     struct passwd *pw = getpwnam("nobody");
     id = pw->pw_uid;
   } else {
@@ -445,18 +291,9 @@ void f_setegid(INT32 args)
 {
   int id;
 
-  check_args("setegid", args, 1, BIT_INT);
-#if 0
-  if (!args) {
-    error("Too few arguments to setegid()\n");
-  }
- 
-  if(sp[-args].type != T_INT) {
-    error("Bad argument 1 to setegid()\n");
-  }
-#endif /* 0 */
+  get_all_args("setegid", args, "%i", &id);
 
-  if(sp[-args].u.integer == -1)
+  if(id == -1)
   {
     struct passwd *pw = getpwnam("nobody");
     id = pw->pw_gid;
@@ -541,11 +378,6 @@ void f_chroot(INT32 args)
   check_args("chroot", args, 1, BIT_STRING);
 #endif /* HAVE_FCHROOT */
 
-#if 0
-  if(args < 1) {
-    error("Too few arguments to chroot()\n");
-  }
-#endif /* 0 */
 
 #ifdef HAVE_FCHROOT
   if(sp[-args].type == T_STRING)
@@ -627,42 +459,157 @@ void f_gethostname(INT32 args)
 }
 #endif /* HAVE_UNAME || HAVE_GETHOSTNAME */
 
+int my_isipnr(char *s)
+{
+  int e,i;
+  for(e=0;e<3;e++)
+  {
+    i=0;
+    while(*s==' ') s++;
+    while(*s>='0' && *s<='9') s++,i++;
+    if(!i) return 0;
+    if(*s!='.') return 0;
+    s++;
+  }
+  i=0;
+  while(*s==' ') s++;
+  while(*s>='0' && *s<='9') s++,i++;
+  if(!i) return 0;
+  while(*s==' ') s++;
+  if(*s) return 0;
+  return 1;
+}
+
+#ifdef _REENTRANT
+#ifdef HAVE_SOLARIS_GETHOSTBYNAME_R
+
+#define GETHOST_DECLARE() \
+    struct hostent *ret; \
+    struct hostent result; \
+    char data[2048]; \
+    int h_errno
+
+#define CALL_GETHOSTBYNAME(X) \
+    THREADS_ALLOW(); \
+    ret=gethostbyname_r((X), &result, data, sizeof(data), &h_errno); \
+    THREADS_DISALLOW()
+
+#define CALL_GETHOSTBYADDR(X,Y,Z) \
+    THREADS_ALLOW(); \
+    ret=gethostbyaddr_r((X),(Y),(Z), &result, data, sizeof(data), &h_errno); \
+    THREADS_DISALLOW()
+
+#else /* HAVE_SOLARIS_GETHOSTBYNAME_R */
+#ifdef HAVE_OSF1_GETHOSTBYNAME_R
+
+#define GETHOST_DECLARE() \
+    struct hostent *ret; \
+    struct hostent result; \
+    struct hostent_data data
+
+#define CALL_GETHOSTBYNAME(X) \
+    THREADS_ALLOW(); \
+    MEMSET((char *)&data,0,sizeof(data)); \
+    if(gethostbyname_r((X), &result, &data) < 0) { \
+      ret=0; \
+    }else{ \
+      ret=&result; \
+    } \
+    THREADS_DISALLOW()
+
+#define CALL_GETHOSTBYADDR(X,Y,Z) \
+    THREADS_ALLOW(); \
+    MEMSET((char *)&data,0,sizeof(data)); \
+    if(gethostbyaddr_r((X),(Y),(Z), &result, &data) < 0) { \
+      ret=0; \
+    }else{ \
+      ret=&result; \
+    } \
+    THREADS_DISALLOW()
+
+#else /* HAVE_OSF1_GETHOSTBYNAME_R */
+static MUTEX_T gethostbyname_mutex;
+
+#define GETHOST_DECLARE() struct hostent *ret
+
+#defne CALL_GETHOSTBYNAME(X) \
+    THREADS_ALLOW(); \
+    mt_lock(&gethostbyname_mutex); \
+    ret=gethostbyname(X); \
+    mt_unlock(&gethostbyname_mutex); \
+    THREADS_DISALLOW()
+
+
+#defne CALL_GETHOSTBYADDR(X,Y,Z) \
+    THREADS_ALLOW(); \
+    mt_lock(&gethostbyname_mutex); \
+    ret=gethostbyaddr((X),(Y),(Z)); \
+    mt_unlock(&gethostbyname_mutex); \
+    THREADS_DISALLOW()
+
+#endif /* HAVE_OSF1_GETHOSTBYNAME_R */
+#endif /* HAVE_SOLARIS_GETHOSTBYNAME_R */
+#else /* _REENTRANT */
+
 #ifdef HAVE_GETHOSTBYNAME
-/* array(string|array(string)) gethostbyaddr(string addr) */
-void f_gethostbyaddr(INT32 args)
+
+#define GETHOST_DECLARE() struct hostent *ret; 
+#define CALL_GETHOSTBYNAME(X) ret=gethostbyname(X)
+#define CALL_GETHOSTBYADDR(X,Y,Z) ret=gethostbyaddr((X),(Y),(Z))
+#endif
+
+#endif /* REENTRANT */
+
+/* this is used from modules/file/file.c ! */
+void get_inet_addr(struct sockaddr_in *addr,char *name)
 {
-  u_long addr;
-  struct hostent *hp;
-  char **p, **q;
-  int nelem;
-
-  check_args("gethostbyaddr", args, 1, BIT_STRING);
-#if 0
-  if (!args) {
-    error("Too few arguments to gethostbyaddr()\n");
+  MEMSET((char *)addr,0,sizeof(struct sockaddr_in));
+
+  addr->sin_family = AF_INET;
+  if(!strcmp(name,"*"))
+  {
+    addr->sin_addr.s_addr=htonl(INADDR_ANY);
   }
-  if (sp[-args].type != T_STRING) {
-    error("Bad argument 1 to gethostbyaddr()\n");
+  else if(my_isipnr(name)) /* I do not entirely trust inet_addr */
+  {
+    if ((long)inet_addr(name) == (long)-1)
+      error("Malformed ip number.\n");
+
+    addr->sin_addr.s_addr = inet_addr(name);
   }
-#endif /* 0 */ 
+  else
+  {
+#ifdef GETHOST_DECLARE
+    GETHOST_DECLARE();
+    CALL_GETHOSTBYNAME(name);
 
-  if ((int)(addr = inet_addr(sp[-args].u.string->str)) == -1) {
-    error("gethostbyaddr(): IP-address must be of the form a.b.c.d\n");
+    if(!ret)
+      error("Invalid address '%s'\n",name);
+
+#ifdef HAVE_H_ADDR_LIST
+    MEMCPY((char *)&(addr->sin_addr),
+	   (char *)ret->h_addr_list[0],
+	   ret->h_length);
+#else
+    MEMCPY((char *)&(addr->sin_addr),
+	   (char *)ret->h_addr,
+	   ret->h_length);
+#endif
+#else
+    error("Invalid address '%s'\n",name);
+#endif
   }
- 
-  pop_n_elems(args);
+}
 
-  THREADS_ALLOW();
 
-  hp = gethostbyaddr((char *)&addr, sizeof (addr), AF_INET);
+#ifdef GETHOST_DECLARE
+/* array(string|array(string)) gethostbyaddr(string addr) */
 
-  THREADS_DISALLOW();
+static void describe_hostent(struct hostent *hp)
+{
+  char **p;
+  INT32 nelem;
 
-  if(!hp) {
-    push_int(0);
-    return;
-  }
- 
   push_text(hp->h_name);
   
 #ifdef HAVE_H_ADDR_LIST
@@ -677,74 +624,65 @@ void f_gethostbyaddr(INT32 args)
   f_aggregate(nelem);
  
   nelem=0;
-  for (q = hp->h_aliases; *q != 0; q++) {
-    push_text(*q);
+  for (p = hp->h_aliases; *p != 0; p++) {
+    push_text(*p);
     nelem++;
   }
   f_aggregate(nelem);
 #else
-  f_aggregate(0);
+  {
+    struct in_addr in;
+    memcpy(&in.s_addr, ret->h_addr, sizeof (in.s_addr));
+    push_text(inet_ntoa(in));
+  }
+
+  f_aggregate(1);
   f_aggregate(0);
 #endif /* HAVE_H_ADDR_LIST */
   f_aggregate(3);
-}  
+}
 
-/* array(array(string)) gethostbyname(string hostname) */ 
-void f_gethostbyname(INT32 args)
+void f_gethostbyaddr(INT32 args)
 {
-  struct hostent *hp;
-  char **p, **q;
-  struct svalue *old_sp;
+  u_long addr;
   char *name;
-  int nelem;
+  GETHOST_DECLARE();
+
+  get_all_args("gethostbyaddr", args, "%s", &name);
 
-  check_args("gethostbyname", args, 1, BIT_STRING);
-#if 0
-  if (!args) {
-    error("Too few arguments to gethostbyname()\n");
+  if ((int)(addr = inet_addr(name)) == -1) {
+    error("gethostbyaddr(): IP-address must be of the form a.b.c.d\n");
   }
-  if (sp[-args].type != T_STRING) {
-    error("Bad argument 1 to gethostbyname()\n");
+ 
+  pop_n_elems(args);
+
+  CALL_GETHOSTBYADDR((char *)&addr, sizeof (addr), AF_INET);
+
+  if(!ret) {
+    push_int(0);
+    return;
   }
-#endif /* 0 */
  
-  name = sp[-args].u.string->str;
+  describe_hostent(ret);
+}  
 
-  THREADS_ALLOW();
+/* array(array(string)) gethostbyname(string hostname) */ 
+void f_gethostbyname(INT32 args)
+{
+  char *name;
+  GETHOST_DECLARE();
 
-  hp = gethostbyname(name);
+  get_all_args("gethostbyname", args, "%s", &name);
 
-  THREADS_DISALLOW();
+  CALL_GETHOSTBYNAME(name);
  
   pop_n_elems(args);
   
-  if(!hp) {
+  if(!ret) {
     push_int(0);
     return;
   }
-  
-#ifdef HAVE_H_ADDR_LIST
-  nelem=0;
-  for (p = hp->h_addr_list; *p != 0; p++) {
-    struct in_addr in;
- 
-    memcpy(&in.s_addr, *p, sizeof (in.s_addr));
-    push_text(inet_ntoa(in));
-    nelem++;
-  }
-  f_aggregate(nelem);
- 
-  nelem=0;
-  for (q = hp->h_aliases; *q != 0; q++) {
-    push_text(*q);
-    nelem++;
-  }
-  f_aggregate(nelem);
-#else
-  f_aggregate(0);
-  f_aggregate(0);
-#endif /* HAVE_H_ADDR_LIST */
-  f_aggregate(3);
+  describe_hostent(ret);
 }  
 #endif /* HAVE_GETHOSTBYNAME */
 
@@ -770,7 +708,7 @@ void init_system_efuns(void)
   add_efun("setgid", f_setgid, "function(int:void)", OPT_SIDE_EFFECT);
 #if defined(HAVE_SETEUID) || defined(HAVE_SETRESUID)
   add_efun("seteuid", f_seteuid, "function(int:void)", OPT_SIDE_EFFECT);
-  add_efun("setegid", f_do_setegid, "function(int:void)", OPT_SIDE_EFFECT);
+  add_efun("setegid", f_setegid, "function(int:void)", OPT_SIDE_EFFECT);
 #endif /* HAVE_SETEUID || HAVE_SETRESUID */
 
   add_efun("getuid", f_getuid, "function(:int)", OPT_EXTERNAL_DEPEND);
@@ -801,7 +739,7 @@ void init_system_efuns(void)
   add_efun("gethostname", f_gethostname, "function(:string)",OPT_TRY_OPTIMIZE);
 #endif /* HAVE_GETHOSTNAME || HAVE_UNAME */
 
-#ifdef HAVE_GETHOSTBYNAME
+#ifdef GETHOST_DECLARE
   add_efun("gethostbyname", f_gethostbyname, "function(string:array)",
            OPT_TRY_OPTIMIZE);
   add_efun("gethostbyaddr", f_gethostbyaddr, "function(string:array)",
diff --git a/src/modules/system/system_machine.h.in b/src/modules/system/system_machine.h.in
index bacdb76079..07467f211d 100644
--- a/src/modules/system/system_machine.h.in
+++ b/src/modules/system/system_machine.h.in
@@ -1,5 +1,5 @@
 /*
- * $Id: system_machine.h.in,v 1.2 1997/01/22 02:55:41 grubba Exp $
+ * $Id: system_machine.h.in,v 1.3 1997/01/22 05:15:28 hubbe Exp $
  *
  * System dependant definitions for the system module for Pike
  *
@@ -89,6 +89,12 @@
 /* Define if you have uname() */
 #undef HAVE_UNAME
 
+/* Define if you have solaris stype gethostbyname_r.  */
+#undef HAVE_SOLARIS_GETHOSTBYNAME_R
+
+/* Define if you have OSF1 stype gethostbyname_r.  */
+#undef HAVE_OSF1_GETHOSTBYNAME_R
+
 /* Define if you have gethostname() */
 #undef HAVE_GETHOSTNAME
 
-- 
GitLab