chiark / gitweb /
+ * Add pre-generated versions of m4-generated files in regress/.
authorian <ian>
Sat, 16 Sep 2000 22:12:31 +0000 (22:12 +0000)
committerian <ian>
Sat, 16 Sep 2000 22:12:31 +0000 (22:12 +0000)
@@ -22,6 +22,7 @@
+  * Add pre-generated versions of m4-generated files in regress/.

INSTALL
changelog
regress/.cvsignore
regress/harness.h [new file with mode: 0644]
regress/hcommon.c [new file with mode: 0644]
regress/hplayback.c [new file with mode: 0644]
regress/hrecord.c [new file with mode: 0644]
regress/hredirect.h [new file with mode: 0644]
regress/hsyscalls.h [new file with mode: 0644]

diff --git a/INSTALL b/INSTALL
index b3680fe..2d64e61 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -29,8 +29,8 @@ Notes/known problems:
     [1] IRIX 6.5 inet_ntoa seems to break with GCC.
 
 The following platforms are known to be deficient and will not work:
-    Solaris 2.5                        Lacks vsnprintf
-    TruUnix64 (DEC UNIX 4.0f)  Lacks vsnprintf
+    Solaris 2.5                        Lacks vsnprintf - install glibc ?
+    TruUnix64 (DEC UNIX 4.0f)  Lacks vsnprintf - install glibc ?
 Please don't report these problems unless you have a nice,
 straightforward solution or workaround for them.
 
index 828aa32..fe27c64 100644 (file)
--- a/changelog
+++ b/changelog
@@ -22,6 +22,7 @@ adns (0.10) unstable; urgency=low
   * Cast a sizeof(...) in src/event.c to unsigned long before printing.
   * #include <sys/select.h> if it exists.
   * Regression tests work better if some syscalls are already macros.
+  * Add pre-generated versions of m4-generated files in regress/.
 
   Portability cleanups:
   * Add list of tested platforms in INSTALL file.
index d2b132d..21dc051 100644 (file)
@@ -1,12 +1,6 @@
 Makefile
-harness.h
-hsyscalls.h
-hredirect.h
-hcommon.c
 *_record
 *_playback
-hrecord.c
-hplayback.c
 output-*.*
 pipe.out
 pipe.err
diff --git a/regress/harness.h b/regress/harness.h
new file mode 100644 (file)
index 0000000..2708e66
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef HARNESS_H_INCLUDED
+#define HARNESS_H_INCLUDED
+#include "internal.h"
+#include "hsyscalls.h"
+/* There is a Q function (Q for Question) for each such syscall;
+ * it constructs a string representing the call, and calls Q_str
+ * on it, or constructs it in vb and calls Q_vb;
+ */
+void Qselect(  int max , const fd_set *rfds , const fd_set *wfds , const fd_set *efds , struct timeval *to     );
+#ifdef HAVE_POLL
+void Qpoll(    const struct pollfd *fds , int nfds , int timeout       );
+#endif
+void Qsocket(   int type       );
+void Qfcntl(   int fd , int cmd , long arg     );
+void Qconnect( int fd , const struct sockaddr *addr , int addrlen      );
+void Qclose(   int fd  );
+void Qsendto(  int fd , const void *msg , int msglen , const struct sockaddr *addr , int addrlen       );
+void Qrecvfrom(        int fd , int buflen , int addrlen       );
+void Qread(    int fd , size_t buflen  );
+void Qwrite(   int fd , const void *buf , size_t len   );
+void Q_vb(void);
+extern void Tshutdown(void);
+/* General help functions */
+void Tfailed(const char *why);
+void Toutputerr(void);
+void Tnomem(void);
+void Tfsyscallr(const char *fmt, ...) PRINTFFORMAT(1,2);
+void Tensureoutputfile(void);
+void Tmust(const char *call, const char *arg, int cond);
+void Tvbf(const char *fmt, ...) PRINTFFORMAT(1,2);
+void Tvbvf(const char *fmt, va_list al);
+void Tvbfdset(int max, const fd_set *set);
+void Tvbpollfds(const struct pollfd *fds, int nfds);
+void Tvbaddr(const struct sockaddr *addr, int addrlen);
+void Tvbbytes(const void *buf, int len);
+void Tvberrno(int e);
+void Tvba(const char *str);
+/* Shared globals */
+extern vbuf vb;
+extern struct timeval currenttime;
+extern const struct Terrno { const char *n; int v; } Terrnos[];
+#endif
diff --git a/regress/hcommon.c b/regress/hcommon.c
new file mode 100644 (file)
index 0000000..cd35309
--- /dev/null
@@ -0,0 +1,280 @@
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "harness.h"
+#include "internal.h"
+vbuf vb;
+FILE *Toutputfile= 0;
+struct timeval currenttime;
+const struct Terrno Terrnos[]= {
+  { "EBADF",                     EBADF                        },
+  { "EAGAIN",                    EAGAIN                       },
+  { "EINPROGRESS",               EINPROGRESS                  },
+  { "EINTR",                     EINTR                        },
+  { "EINVAL",                    EINVAL                       },
+  { "EMSGSIZE",                  EMSGSIZE                     },
+  { "ENOBUFS",                   ENOBUFS                      },
+  { "ENOENT",                    ENOENT                       },
+  { "ENOPROTOOPT",               ENOPROTOOPT                  },
+  { "ENOSPC",                    ENOSPC                       },
+  { "EWOULDBLOCK",               EWOULDBLOCK                  },
+  { "EHOSTUNREACH",              EHOSTUNREACH                 },
+  { "ECONNRESET",                ECONNRESET                   },
+  { "ECONNREFUSED",              ECONNREFUSED                 },
+  { "EPIPE",                     EPIPE                        },
+  {  0,                          0                            }
+};
+static vbuf vbw;
+int Hgettimeofday(struct timeval *tv, struct timezone *tz) {
+  Tmust("gettimeofday","tz",!tz);
+  *tv= currenttime;
+  return 0;
+}
+int Hwritev(int fd, const struct iovec *vector, size_t count) {
+  size_t i;
+  vbw.used= 0;
+  for (i=0; i<count; i++, vector++) {
+    if (!adns__vbuf_append(&vbw,vector->iov_base,vector->iov_len)) Tnomem();
+  }
+  return Hwrite(fd,vbw.buf,vbw.used);
+}
+void Qselect(  int max , const fd_set *rfds , const fd_set *wfds , const fd_set *efds , struct timeval *to     ) {
+ vb.used= 0;
+ Tvba("select");
+       Tvbf(" max=%d",max); 
+       Tvbf(" rfds="); Tvbfdset(max,rfds); 
+       Tvbf(" wfds="); Tvbfdset(max,wfds); 
+       Tvbf(" efds="); Tvbfdset(max,efds); 
+  if (to) Tvbf(" to=%ld.%06ld",(long)to->tv_sec,(long)to->tv_usec);
+  else Tvba(" to=null"); 
+  Q_vb();
+}
+#ifdef HAVE_POLL
+void Qpoll(    const struct pollfd *fds , int nfds , int timeout       ) {
+ vb.used= 0;
+ Tvba("poll");
+        Tvbf(" fds="); Tvbpollfds(fds,nfds); 
+       Tvbf(" timeout=%d",timeout); 
+  Q_vb();
+}
+#endif
+void Qsocket(   int type       ) {
+ vb.used= 0;
+ Tvba("socket");
+  Tvbf(type==SOCK_STREAM ? " type=SOCK_STREAM" : " type=SOCK_DGRAM"); 
+  Q_vb();
+}
+void Qfcntl(   int fd , int cmd , long arg     ) {
+ vb.used= 0;
+ Tvba("fcntl");
+       Tvbf(" fd=%d",fd); 
+  if (cmd == F_SETFL) {
+   Tvbf(" cmd=F_SETFL %s",arg & O_NONBLOCK ? "O_NONBLOCK|..." : "~O_NONBLOCK&...");
+  } else if (cmd == F_GETFL) {
+   Tvba(" cmd=F_GETFL");
+  } else {
+   Tmust("cmd","F_GETFL/F_SETFL",0);
+  } 
+  Q_vb();
+}
+void Qconnect( int fd , const struct sockaddr *addr , int addrlen      ) {
+ vb.used= 0;
+ Tvba("connect");
+       Tvbf(" fd=%d",fd); 
+       Tvba(" addr="); Tvbaddr(addr,addrlen); 
+  Q_vb();
+}
+void Qclose(   int fd  ) {
+ vb.used= 0;
+ Tvba("close");
+       Tvbf(" fd=%d",fd); 
+  Q_vb();
+}
+void Qsendto(  int fd , const void *msg , int msglen , const struct sockaddr *addr , int addrlen       ) {
+ vb.used= 0;
+ Tvba("sendto");
+       Tvbf(" fd=%d",fd); 
+       Tvba(" addr="); Tvbaddr(addr,addrlen); 
+       Tvbbytes(msg,msglen); 
+  Q_vb();
+}
+void Qrecvfrom(        int fd , int buflen , int addrlen       ) {
+ vb.used= 0;
+ Tvba("recvfrom");
+       Tvbf(" fd=%d",fd); 
+       Tvbf(" buflen=%lu",(unsigned long)buflen); 
+       Tvbf(" *addrlen=%d",addrlen); 
+  Q_vb();
+}
+void Qread(    int fd , size_t buflen  ) {
+ vb.used= 0;
+ Tvba("read");
+       Tvbf(" fd=%d",fd); 
+       Tvbf(" buflen=%lu",(unsigned long)buflen); 
+  Q_vb();
+}
+void Qwrite(   int fd , const void *buf , size_t len   ) {
+ vb.used= 0;
+ Tvba("write");
+       Tvbf(" fd=%d",fd); 
+       Tvbbytes(buf,len); 
+  Q_vb();
+}
+void Tvbaddr(const struct sockaddr *addr, int len) {
+  const struct sockaddr_in *ai= (const struct sockaddr_in*)addr;
+  assert(len==sizeof(struct sockaddr_in));
+  assert(ai->sin_family==AF_INET);
+  Tvbf("%s:%u",inet_ntoa(ai->sin_addr),htons(ai->sin_port));
+}
+void Tvbbytes(const void *buf, int len) {
+  const byte *bp;
+  int i;
+  if (!len) { Tvba("\n     ."); return; }
+  for (i=0, bp=buf; i<len; i++, bp++) {
+    if (!(i&31)) Tvba("\n     ");
+    else if (!(i&3)) Tvba(" ");
+    Tvbf("%02x",*bp);
+  }
+  Tvba(".");
+}
+void Tvbfdset(int max, const fd_set *fds) {
+  int i;
+  const char *comma= "";
+  Tvba("[");
+  for (i=0; i<max; i++) {
+    if (!FD_ISSET(i,fds)) continue;
+    Tvba(comma);
+    Tvbf("%d",i);
+    comma= ",";
+  }
+  Tvba("]");
+}
+static void Tvbpollevents(int events) {
+  const char *delim= "";
+  events &= (POLLIN|POLLOUT|POLLPRI);
+  if (!events) { Tvba("0"); return; }
+  if (events & POLLIN) { Tvba("POLLIN"); delim= "|"; }
+  if (events & POLLOUT) { Tvba(delim); Tvba("POLLOUT"); delim= "|"; }
+  if (events & POLLPRI) { Tvba(delim); Tvba("POLLPRI"); }
+}
+void Tvbpollfds(const struct pollfd *fds, int nfds) {
+  const char *comma= "";
+  Tvba("[");
+  while (nfds>0) {
+    Tvba(comma);
+    Tvbf("{fd=%d, events=",fds->fd);
+    Tvbpollevents(fds->events);
+    Tvba(", revents=");
+    Tvbpollevents(fds->revents);
+    Tvba("}");
+    comma= ", ";
+    nfds--; fds++;
+  }
+  Tvba("]");
+}
+void Tvberrno(int e) {
+  const struct Terrno *te;
+  for (te= Terrnos; te->n && te->v != e; te++);
+  assert(te->n);
+  Tvba(te->n);
+}
+void Tvba(const char *str) {
+  if (!adns__vbuf_appendstr(&vb,str)) Tnomem();
+}
+void Tvbvf(const char *fmt, va_list al) {
+  char buf[1000];
+  buf[sizeof(buf)-2]= '\t';
+  vsnprintf(buf,sizeof(buf),fmt,al);
+  assert(buf[sizeof(buf)-2] == '\t');
+  Tvba(buf);
+}
+void Tvbf(const char *fmt, ...) {
+  va_list al;
+  va_start(al,fmt);
+  Tvbvf(fmt,al);
+  va_end(al);
+}
+void Tmust(const char *call, const char *arg, int cond) {
+  if (cond) return;
+  fprintf(stderr,"adns test harness: case not handled: system call %s, arg %s",call,arg);
+  exit(-1);
+}
+void Tfailed(const char *why) {
+  fprintf(stderr,"adns test harness: failure: %s: %s\n",why,strerror(errno));
+  exit(-1);
+}
+void Tnomem(void) {
+  Tfailed("unable to malloc/realloc");
+}
+void Toutputerr(void) {
+  Tfailed("write error on test harness output");
+}
+struct malloced {
+  struct malloced *next, *back;
+  size_t sz;
+  unsigned long count;
+  struct { double d; long ul; void *p; void (*fp)(void); } data;
+};
+static unsigned long malloccount, mallocfailat;
+static struct { struct malloced *head, *tail; } mallocedlist;
+#define MALLOCHSZ ((char*)&mallocedlist.head->data - (char*)mallocedlist.head)
+void *Hmalloc(size_t sz) {
+  struct malloced *newnode;
+  const char *mfavar;
+  char *ep;
+  assert(sz);
+  newnode= malloc(MALLOCHSZ + sz);  if (!newnode) Tnomem();
+  LIST_LINK_TAIL(mallocedlist,newnode);
+  newnode->sz= sz;
+  newnode->count= ++malloccount;
+  if (!mallocfailat) {
+    mfavar= getenv("ADNS_REGRESS_MALLOCFAILAT");
+    if (mfavar) {
+      mallocfailat= strtoul(mfavar,&ep,10);
+      if (!mallocfailat || *ep) Tfailed("ADNS_REGRESS_MALLOCFAILAT bad value");
+    } else {
+      mallocfailat= ~0UL;
+    }
+  }
+  assert(newnode->count != mallocfailat);
+  memset(&newnode->data,0xc7,sz);
+  return &newnode->data;
+}
+void Hfree(void *ptr) {
+  struct malloced *oldnode;
+  if (!ptr) return;
+  oldnode= (void*)((char*)ptr - MALLOCHSZ);
+  LIST_UNLINK(mallocedlist,oldnode);
+  memset(&oldnode->data,0x38,oldnode->sz);
+  free(oldnode);
+}
+void *Hrealloc(void *op, size_t nsz) {
+  struct malloced *oldnode;
+  void *np;
+  size_t osz;
+  if (op) { oldnode= (void*)((char*)op - MALLOCHSZ); osz= oldnode->sz; } else { osz= 0; }
+  np= Hmalloc(nsz);
+  memcpy(np,op, osz>nsz ? nsz : osz);
+  Hfree(op);
+  return np;
+}
+void Hexit(int rv) {
+  struct malloced *loopnode;
+  Tshutdown();
+  adns__vbuf_free(&vb);
+  adns__vbuf_free(&vbw);
+  if (mallocedlist.head) {
+    fprintf(stderr,"adns test harness: memory leaked:");
+    for (loopnode=mallocedlist.head; loopnode; loopnode=loopnode->next)
+      fprintf(stderr," %lu(%lu)",loopnode->count,(unsigned long)loopnode->sz);
+    putc('\n',stderr);
+    if (ferror(stderr)) exit(-1);
+  }
+  exit(rv);
+}
diff --git a/regress/hplayback.c b/regress/hplayback.c
new file mode 100644 (file)
index 0000000..92570ff
--- /dev/null
@@ -0,0 +1,529 @@
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "harness.h"
+static FILE *Tinputfile, *Treportfile;
+static vbuf vb2;
+extern void Tshutdown(void) {
+  adns__vbuf_free(&vb2);
+}
+static void Tensurereportfile(void) {
+  const char *fdstr;
+  int fd;
+  if (Treportfile) return;
+  Treportfile= stderr;
+  fdstr= getenv("ADNS_TEST_REPORT_FD"); if (!fdstr) return;
+  fd= atoi(fdstr);
+  Treportfile= fdopen(fd,"a"); if (!Treportfile) Tfailed("fdopen ADNS_TEST_REPORT_FD");
+}
+static void Psyntax(const char *where) {
+  fprintf(stderr,"adns test harness: syntax error in test log input file: %s\n",where);
+  exit(-1);
+}
+static void Pcheckinput(void) {
+  if (ferror(Tinputfile)) Tfailed("read test log input file");
+  if (feof(Tinputfile)) Psyntax("eof at syscall reply");
+}
+static void Tensureinputfile(void) {
+  const char *fdstr;
+  int fd;
+  int chars;
+  unsigned long sec, usec;
+  if (Tinputfile) return;
+  Tinputfile= stdin;
+  fdstr= getenv("ADNS_TEST_IN_FD");
+  if (fdstr) {
+    fd= atoi(fdstr);
+    Tinputfile= fdopen(fd,"r"); if (!Tinputfile) Tfailed("fdopen ADNS_TEST_IN_FD");
+  }
+  setvbuf(Tinputfile,0,_IONBF,0);
+  if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+  fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+  chars= -1;
+  sscanf(vb2.buf," start %lu.%lu%n",&sec,&usec,&chars);
+  if (chars==-1) Psyntax("start time invalid");
+  currenttime.tv_sec= sec;
+  currenttime.tv_usec= usec;
+  if (vb2.buf[chars] != '\n') Psyntax("not newline after start time");
+}
+static void Parg(const char *argname) {
+  int l;
+  if (vb2.buf[vb2.used++] != ' ') Psyntax("not a space before argument");
+  l= strlen(argname);
+  if (memcmp(vb2.buf+vb2.used,argname,l)) Psyntax("argument name wrong");
+  vb2.used+= l;
+  if (vb2.buf[vb2.used++] != '=') Psyntax("not = after argument name");
+}
+static int Pstring_maybe(const char *string) {
+  int l;
+  l= strlen(string);
+  if (memcmp(vb2.buf+vb2.used,string,l)) return 0;
+  vb2.used+= l;
+  return 1;
+}
+static void Pstring(const char *string, const char *emsg) {
+  if (Pstring_maybe(string)) return;
+  Psyntax(emsg);
+}
+static int Perrno(const char *stuff) {
+  const struct Terrno *te;
+  int r;
+  char *ep;
+  for (te= Terrnos; te->n && strcmp(te->n,stuff); te++);
+  if (te->n) return te->v;
+  r= strtoul(stuff+2,&ep,10);
+  if (*ep) Psyntax("errno value not recognised, not numeric");
+  return r;
+}
+static void P_updatetime(void) {
+  int chars;
+  unsigned long sec, usec;
+  if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+  fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+  chars= -1;
+  sscanf(vb2.buf," +%lu.%lu%n",&sec,&usec,&chars);
+  if (chars==-1) Psyntax("update time invalid");
+  currenttime.tv_sec+= sec;
+  currenttime.tv_usec+= usec;
+  if (currenttime.tv_usec > 1000000) {
+    currenttime.tv_sec++;
+    currenttime.tv_usec -= 1000000;
+  }
+  if (vb2.buf[chars] != '\n') Psyntax("not newline after update time");
+}
+static void Pfdset(fd_set *set, int max) {
+  int r, c;
+  char *ep;
+  if (vb2.buf[vb2.used++] != '[') Psyntax("fd set start not [");
+  FD_ZERO(set);
+  if (vb2.buf[vb2.used] == ']') { vb2.used++; return; }
+  for (;;) {
+    r= strtoul(vb2.buf+vb2.used,&ep,10);
+    if (r>=max) Psyntax("fd set member > max");
+    if (ep == (char*)vb2.buf+vb2.used) Psyntax("empty entry in fd set");
+    FD_SET(r,set);
+    vb2.used= ep - (char*)vb2.buf;
+    c= vb2.buf[vb2.used++];
+    if (c == ']') break;
+    if (c != ',') Psyntax("fd set separator not ,");
+  }
+}
+#ifdef HAVE_POLL
+static int Ppollfdevents(void) {
+  int events;
+  if (Pstring_maybe("0")) return 0;
+  events= 0;
+  if (Pstring_maybe("POLLIN")) {
+    events |= POLLIN;
+    if (!Pstring_maybe("|")) return events;
+  }
+  if (Pstring_maybe("POLLOUT")) {
+    events |= POLLOUT;
+    if (!Pstring_maybe("|")) return events;
+  }
+  Pstring("POLLPRI","pollfdevents PRI?");
+  return events;
+}
+static void Ppollfds(struct pollfd *fds, int nfds) {
+  int i;
+  char *ep;
+  const char *comma= "";
+  if (vb2.buf[vb2.used++] != '[') Psyntax("pollfds start not [");
+  for (i=0; i<nfds; i++) {
+    Pstring("{fd=","{fd= in pollfds");
+    fds->fd= strtoul(vb2.buf+vb2.used,&ep,10);
+    vb2.used= ep - (char*)vb2.buf;    
+    Pstring(", events=",", events= in pollfds");
+    fds->events= Ppollfdevents();
+    Pstring(", revents=",", revents= in pollfds");
+    fds->revents= Ppollfdevents();
+    Pstring("}","} in pollfds");
+    Pstring(comma,"separator in pollfds");
+    comma= ", ";
+  }
+  if (vb2.buf[vb2.used++] != ']') Psyntax("pollfds end not ]");
+}
+#endif
+static void Paddr(struct sockaddr *addr, int *lenr) {
+  struct sockaddr_in *sa= (struct sockaddr_in*)addr;
+  char *p, *ep;
+  long ul;
+  assert(*lenr >= sizeof(*sa));
+  p= strchr(vb2.buf+vb2.used,':');
+  if (!p) Psyntax("no port on address");
+  *p++= 0;
+  memset(sa,0,sizeof(*sa));
+  sa->sin_family= AF_INET;
+  if (!inet_aton(vb2.buf+vb2.used,&sa->sin_addr)) Psyntax("invalid address");
+  ul= strtoul(p,&ep,10);
+  if (*ep && *ep != ' ') Psyntax("invalid port (bad syntax)");
+  if (ul >= 65536) Psyntax("port too large");
+  sa->sin_port= htons(ul);
+  *lenr= sizeof(*sa);
+  vb2.used= ep - (char*)vb2.buf;
+}
+static int Pbytes(byte *buf, int maxlen) {
+  static const char hexdigits[]= "0123456789abcdef";
+  int c, v, done;
+  const char *pf;
+  done= 0;
+  for (;;) {
+    c= getc(Tinputfile); Pcheckinput();
+    if (c=='\n' || c==' ' || c=='\t') continue;
+    if (c=='.') break;
+    pf= strchr(hexdigits,c); if (!pf) Psyntax("invalid first hex digit");
+    v= (pf-hexdigits)<<4;
+    c= getc(Tinputfile); Pcheckinput();
+    pf= strchr(hexdigits,c); if (!pf) Psyntax("invalid second hex digit");
+    v |= (pf-hexdigits);
+    if (maxlen<=0) Psyntax("buffer overflow in bytes");
+    *buf++= v;
+    maxlen--; done++;
+  }
+  for (;;) {
+    c= getc(Tinputfile); Pcheckinput();
+    if (c=='\n') return done;
+  }
+}
+void Q_vb(void) {
+  int r;
+  const char *nl;
+  Tensureinputfile();
+  if (!adns__vbuf_ensure(&vb2,vb.used+2)) Tnomem();
+  r= fread(vb2.buf,1,vb.used+2,Tinputfile);
+  if (feof(Tinputfile)) {
+    fprintf(stderr,"adns test harness: input ends prematurely; program did:\n %.*s\n",
+           vb.used,vb.buf);
+    exit(-1);
+  }
+  Pcheckinput();
+  if (vb2.buf[0] != ' ') Psyntax("not space before call");
+  if (memcmp(vb.buf,vb2.buf+1,vb.used) ||
+      vb2.buf[vb.used+1] != '\n') {
+    fprintf(stderr,
+            "adns test harness: program did unexpected:\n %.*s\n"
+            "was expecting:\n %.*s\n",
+            vb.used,vb.buf, vb.used,vb2.buf+1);
+    exit(1);
+  }
+  Tensurereportfile();
+  nl= memchr(vb.buf,'\n',vb.used);
+  fprintf(Treportfile," %.*s\n", (int)(nl ? nl - (const char*)vb.buf : vb.used), vb.buf);
+}
+int Hselect(   int max , fd_set *rfds , fd_set *wfds , fd_set *efds , struct timeval *to       ) {
+ int r, amtread;
+ char *ep;
+ Qselect(      max , rfds , wfds , efds , to   );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," select=",8)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[8] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+8);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  r= strtoul(vb2.buf+8,&ep,10);
+  if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
+  vb2.used= ep - (char*)vb2.buf;
+       Parg("rfds"); Pfdset(rfds,max); 
+       Parg("wfds"); Pfdset(wfds,max); 
+       Parg("efds"); Pfdset(efds,max); 
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+ P_updatetime();
+ return r;
+}
+#ifdef HAVE_POLL
+int Hpoll(     struct pollfd *fds , int nfds , int timeout     ) {
+ int r, amtread;
+ char *ep;
+ Qpoll(        fds , nfds , timeout    );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," poll=",6)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[6] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+6);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  r= strtoul(vb2.buf+6,&ep,10);
+  if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
+  vb2.used= ep - (char*)vb2.buf;
+        Parg("fds"); Ppollfds(fds,nfds); 
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+ P_updatetime();
+ return r;
+}
+#endif
+int Hsocket(   int domain , int type , int protocol    ) {
+ int r, amtread;
+ char *ep;
+       Tmust("socket","domain",domain==AF_INET); 
+  Tmust("socket","type",type==SOCK_STREAM || type==SOCK_DGRAM); 
+ Qsocket(       type   );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," socket=",8)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[8] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+8);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  r= strtoul(vb2.buf+8,&ep,10);
+  if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
+  vb2.used= ep - (char*)vb2.buf;
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+ P_updatetime();
+ return r;
+}
+int Hfcntl(    int fd , int cmd , ...  ) {
+ int r, amtread;
+       va_list al; long arg; 
+  Tmust("fcntl","cmd",cmd==F_SETFL || cmd==F_GETFL);
+  if (cmd == F_SETFL) {
+    va_start(al,cmd); arg= va_arg(al,long); va_end(al);
+  } else {
+    arg= 0;
+  } 
+ Qfcntl(       fd , cmd , arg  );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," fcntl=",7)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[7] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+7);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  r= 0;
+  if (cmd == F_GETFL) {
+    if (!memcmp(vb2.buf+7,"O_NONBLOCK|...",14)) {
+      r= O_NONBLOCK;
+      vb2.used= 7+14;
+    } else if (!memcmp(vb2.buf+7,"~O_NONBLOCK&...",15)) {
+      vb2.used= 7+15;
+    } else {
+      Psyntax("fcntl flags not O_NONBLOCK|... or ~O_NONBLOCK&...");
+    }
+  } else if (cmd == F_SETFL) {
+  if (memcmp(vb2.buf+7,"OK",2)) Psyntax("success/fail not E* or OK");
+  vb2.used= 7+2;
+  r= 0;
+  } else {
+    Psyntax("fcntl not F_GETFL or F_SETFL");
+  }
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+ P_updatetime();
+ return r;
+}
+int Hconnect(  int fd , const struct sockaddr *addr , int addrlen      ) {
+ int r, amtread;
+ Qconnect(     fd , addr , addrlen     );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," connect=",9)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[9] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+9);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  if (memcmp(vb2.buf+9,"OK",2)) Psyntax("success/fail not E* or OK");
+  vb2.used= 9+2;
+  r= 0;
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+ P_updatetime();
+ return r;
+}
+int Hclose(    int fd  ) {
+ int r, amtread;
+ Qclose(       fd      );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," close=",7)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[7] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+7);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  if (memcmp(vb2.buf+7,"OK",2)) Psyntax("success/fail not E* or OK");
+  vb2.used= 7+2;
+  r= 0;
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+ P_updatetime();
+ return r;
+}
+int Hsendto(   int fd , const void *msg , int msglen , unsigned int flags , const struct sockaddr *addr , int addrlen  ) {
+ int r, amtread;
+ char *ep;
+       Tmust("sendto","flags",flags==0); 
+ Qsendto(      fd , msg , msglen , addr , addrlen      );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," sendto=",8)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[8] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+8);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  r= strtoul(vb2.buf+8,&ep,10);
+  if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
+  vb2.used= ep - (char*)vb2.buf;
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+ P_updatetime();
+ return r;
+}
+int Hrecvfrom( int fd , void *buf , int buflen , unsigned int flags , struct sockaddr *addr , int *addrlen     ) {
+ int r, amtread;
+       Tmust("recvfrom","flags",flags==0); 
+       Tmust("recvfrom","*addrlen",*addrlen>=sizeof(struct sockaddr_in)); 
+ Qrecvfrom(    fd , buflen , *addrlen  );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," recvfrom=",10)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[10] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+10);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  if (memcmp(vb2.buf+10,"OK",2)) Psyntax("success/fail not E* or OK");
+  vb2.used= 10+2;
+  r= 0;
+       Parg("addr"); Paddr(addr,addrlen); 
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+       r= Pbytes(buf,buflen); 
+ P_updatetime();
+ return r;
+}
+int Hread(     int fd , void *buf , size_t buflen      ) {
+ int r, amtread;
+ Qread(        fd , buflen     );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," read=",6)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[6] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+6);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  if (memcmp(vb2.buf+6,"OK",2)) Psyntax("success/fail not E* or OK");
+  vb2.used= 6+2;
+  r= 0;
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+       r= Pbytes(buf,buflen); 
+ P_updatetime();
+ return r;
+}
+int Hwrite(    int fd , const void *buf , size_t len   ) {
+ int r, amtread;
+ char *ep;
+ Qwrite(       fd , buf , len  );
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+ Tensurereportfile();
+ fprintf(Treportfile,"%s",vb2.buf);
+ amtread= strlen(vb2.buf);
+ if (amtread<=0 || vb2.buf[--amtread]!='\n')
+  Psyntax("badly formed line");
+ vb2.buf[amtread]= 0;
+ if (memcmp(vb2.buf," write=",7)) Psyntax("syscall reply mismatch");
+ if (vb2.buf[7] == 'E') {
+  int e;
+  e= Perrno(vb2.buf+7);
+  P_updatetime();
+  errno= e;
+  return -1;
+ }
+  r= strtoul(vb2.buf+7,&ep,10);
+  if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
+  vb2.used= ep - (char*)vb2.buf;
+ assert(vb2.used <= amtread);
+ if (vb2.used != amtread) Psyntax("junk at end of line");
+ P_updatetime();
+ return r;
+}
diff --git a/regress/hrecord.c b/regress/hrecord.c
new file mode 100644 (file)
index 0000000..c60f93c
--- /dev/null
@@ -0,0 +1,227 @@
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "harness.h"
+static FILE *Toutputfile;
+void Tshutdown(void) {
+}
+static void R_recordtime(void) {
+  int r;
+  struct timeval tv, tvrel;
+  Tensureoutputfile();
+  r= gettimeofday(&tv,0); if (r) Tfailed("gettimeofday syscallbegin");
+  tvrel.tv_sec= tv.tv_sec - currenttime.tv_sec;
+  tvrel.tv_usec= tv.tv_usec - currenttime.tv_usec;
+  if (tv.tv_usec < 0) { tvrel.tv_usec += 1000000; tvrel.tv_sec--; }
+  Tvbf("\n +%ld.%06ld",(long)tvrel.tv_sec,(long)tvrel.tv_usec);
+  currenttime= tv;
+}
+void Tensureoutputfile(void) {
+  const char *fdstr;
+  int fd, r;
+  if (Toutputfile) return;
+  Toutputfile= stdout;
+  fdstr= getenv("ADNS_TEST_OUT_FD");
+  if (fdstr) {
+    fd= atoi(fdstr);
+    Toutputfile= fdopen(fd,"a"); if (!Toutputfile) Tfailed("fdopen ADNS_TEST_OUT_FD");
+  }
+  r= gettimeofday(&currenttime,0); if (r) Tfailed("gettimeofday syscallbegin");
+  if (fprintf(Toutputfile," start %ld.%06ld\n",
+             (long)currenttime.tv_sec,(long)currenttime.tv_usec) == EOF) Toutputerr();
+}
+void Q_vb(void) {
+  if (!adns__vbuf_append(&vb,"",1)) Tnomem();
+  Tensureoutputfile();
+  if (fprintf(Toutputfile," %s\n",vb.buf) == EOF) Toutputerr();
+  if (fflush(Toutputfile)) Toutputerr();
+}
+static void R_vb(void) {
+  Q_vb();
+}
+int Hselect(   int max , fd_set *rfds , fd_set *wfds , fd_set *efds , struct timeval *to       ) {
+ int r, e;
+ Qselect(      max , rfds , wfds , efds , to   );
+ r= select(    max , rfds , wfds , efds , to   );
+ e= errno;
+ vb.used= 0;
+ Tvba("select=");
+  if (r==-1) { Tvberrno(e); goto x_error; }
+  Tvbf("%d",r);
+       Tvba(" rfds="); Tvbfdset(max,rfds); 
+       Tvba(" wfds="); Tvbfdset(max,wfds); 
+       Tvba(" efds="); Tvbfdset(max,efds); 
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+#ifdef HAVE_POLL
+int Hpoll(     struct pollfd *fds , int nfds , int timeout     ) {
+ int r, e;
+ Qpoll(        fds , nfds , timeout    );
+ r= poll(      fds , nfds , timeout    );
+ e= errno;
+ vb.used= 0;
+ Tvba("poll=");
+  if (r==-1) { Tvberrno(e); goto x_error; }
+  Tvbf("%d",r);
+        Tvba(" fds="); Tvbpollfds(fds,nfds); 
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+#endif
+int Hsocket(   int domain , int type , int protocol    ) {
+ int r, e;
+       Tmust("socket","domain",domain==AF_INET); 
+  Tmust("socket","type",type==SOCK_STREAM || type==SOCK_DGRAM); 
+ Qsocket(       type   );
+ r= socket(    domain , type , protocol        );
+ e= errno;
+ vb.used= 0;
+ Tvba("socket=");
+  if (r==-1) { Tvberrno(e); goto x_error; }
+  Tvbf("%d",r);
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+int Hfcntl(    int fd , int cmd , ...  ) {
+ int r, e;
+       va_list al; long arg; 
+  Tmust("fcntl","cmd",cmd==F_SETFL || cmd==F_GETFL);
+  if (cmd == F_SETFL) {
+    va_start(al,cmd); arg= va_arg(al,long); va_end(al);
+  } else {
+    arg= 0;
+  } 
+ Qfcntl(       fd , cmd , arg  );
+ r= fcntl(     fd , cmd , arg  );
+ e= errno;
+ vb.used= 0;
+ Tvba("fcntl=");
+  if (r==-1) { Tvberrno(e); goto x_error; }
+  if (cmd == F_GETFL) {
+    Tvbf(r & O_NONBLOCK ? "O_NONBLOCK|..." : "~O_NONBLOCK&...");
+  } else {
+    if (cmd == F_SETFL) {
+      Tmust("fcntl","return",!r);
+    } else {
+      Tmust("cmd","F_GETFL/F_SETFL",0);
+    }
+    Tvba("OK");
+  }
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+int Hconnect(  int fd , const struct sockaddr *addr , int addrlen      ) {
+ int r, e;
+ Qconnect(     fd , addr , addrlen     );
+ r= connect(   fd , addr , addrlen     );
+ e= errno;
+ vb.used= 0;
+ Tvba("connect=");
+  if (r) { Tvberrno(e); goto x_error; }
+  Tvba("OK");
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+int Hclose(    int fd  ) {
+ int r, e;
+ Qclose(       fd      );
+ r= close(     fd      );
+ e= errno;
+ vb.used= 0;
+ Tvba("close=");
+  if (r) { Tvberrno(e); goto x_error; }
+  Tvba("OK");
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+int Hsendto(   int fd , const void *msg , int msglen , unsigned int flags , const struct sockaddr *addr , int addrlen  ) {
+ int r, e;
+       Tmust("sendto","flags",flags==0); 
+ Qsendto(      fd , msg , msglen , addr , addrlen      );
+ r= sendto(    fd , msg , msglen , flags , addr , addrlen      );
+ e= errno;
+ vb.used= 0;
+ Tvba("sendto=");
+  if (r==-1) { Tvberrno(e); goto x_error; }
+  Tvbf("%d",r);
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+int Hrecvfrom( int fd , void *buf , int buflen , unsigned int flags , struct sockaddr *addr , int *addrlen     ) {
+ int r, e;
+       Tmust("recvfrom","flags",flags==0); 
+       Tmust("recvfrom","*addrlen",*addrlen>=sizeof(struct sockaddr_in)); 
+ Qrecvfrom(    fd , buflen , *addrlen  );
+ r= recvfrom(  fd , buf , buflen , flags , addr , addrlen      );
+ e= errno;
+ vb.used= 0;
+ Tvba("recvfrom=");
+  if (r==-1) { Tvberrno(e); goto x_error; }
+  Tmust("recvfrom","return",r<=buflen);
+  Tvba("OK");
+       Tvba(" addr="); Tvbaddr(addr,*addrlen); 
+       Tvbbytes(buf,r); 
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+int Hread(     int fd , void *buf , size_t buflen      ) {
+ int r, e;
+ Qread(        fd , buflen     );
+ r= read(      fd , buf , buflen       );
+ e= errno;
+ vb.used= 0;
+ Tvba("read=");
+  if (r==-1) { Tvberrno(e); goto x_error; }
+  Tmust("read","return",r<=buflen);
+  Tvba("OK");
+       Tvbbytes(buf,r); 
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
+int Hwrite(    int fd , const void *buf , size_t len   ) {
+ int r, e;
+ Qwrite(       fd , buf , len  );
+ r= write(     fd , buf , len  );
+ e= errno;
+ vb.used= 0;
+ Tvba("write=");
+  if (r==-1) { Tvberrno(e); goto x_error; }
+  Tvbf("%d",r);
+ x_error:
+ R_recordtime();
+ R_vb();
+ errno= e;
+ return r;
+}
diff --git a/regress/hredirect.h b/regress/hredirect.h
new file mode 100644 (file)
index 0000000..d49da69
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef HREDIRECT_H_INCLUDED
+#define HREDIRECT_H_INCLUDED
+#include "hsyscalls.h"
+#undef select
+#define select Hselect
+#ifdef HAVE_POLL
+#undef poll
+#define poll Hpoll
+#endif
+#undef socket
+#define socket Hsocket
+#undef fcntl
+#define fcntl Hfcntl
+#undef connect
+#define connect Hconnect
+#undef close
+#define close Hclose
+#undef sendto
+#define sendto Hsendto
+#undef recvfrom
+#define recvfrom Hrecvfrom
+#undef read
+#define read Hread
+#undef write
+#define write Hwrite
+#undef int
+#define writev Hwritev
+#undef int
+#define gettimeofday Hgettimeofday
+#undef void*
+#define malloc Hmalloc
+#undef void
+#define free Hfree
+#undef void*
+#define realloc Hrealloc
+#undef void
+#define exit Hexit
+#endif
diff --git a/regress/hsyscalls.h b/regress/hsyscalls.h
new file mode 100644 (file)
index 0000000..afec8ca
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef HSYSCALLS_H_INCLUDED
+#define HSYSCALLS_H_INCLUDED
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#ifdef HAVE_POLL
+#include <sys/poll.h>
+#endif
+int Hselect(   int max , fd_set *rfds , fd_set *wfds , fd_set *efds , struct timeval *to       );
+#ifdef HAVE_POLL
+int Hpoll(     struct pollfd *fds , int nfds , int timeout     );
+#endif
+int Hsocket(   int domain , int type , int protocol    );
+int Hfcntl(    int fd , int cmd , ...  );
+int Hconnect(  int fd , const struct sockaddr *addr , int addrlen      );
+int Hclose(    int fd  );
+int Hsendto(   int fd , const void *msg , int msglen , unsigned int flags , const struct sockaddr *addr , int addrlen  );
+int Hrecvfrom( int fd , void *buf , int buflen , unsigned int flags , struct sockaddr *addr , int *addrlen     );
+int Hread(     int fd , void *buf , size_t buflen      );
+int Hwrite(    int fd , const void *buf , size_t len   );
+int Hwritev(int fd, const struct iovec *vector, size_t count);
+int Hgettimeofday(struct timeval *tv, struct timezone *tz);
+void* Hmalloc(size_t sz);
+void Hfree(void *ptr);
+void* Hrealloc(void *op, size_t nsz);
+void Hexit(int rv)NONRETURNING;
+#endif