Added ncftp to rosapps
authorSteven Edwards <winehacker@gmail.com>
Sun, 30 Dec 2001 06:31:25 +0000 (06:31 +0000)
committerSteven Edwards <winehacker@gmail.com>
Sun, 30 Dec 2001 06:31:25 +0000 (06:31 +0000)
svn path=/trunk/; revision=2453

118 files changed:
rosapps/net/ncftp/Strn/Dynscat.c [new file with mode: 0644]
rosapps/net/ncftp/Strn/Makefile.in [new file with mode: 0644]
rosapps/net/ncftp/Strn/Strn.h [new file with mode: 0644]
rosapps/net/ncftp/Strn/Strncat.c [new file with mode: 0644]
rosapps/net/ncftp/Strn/Strncpy.c [new file with mode: 0644]
rosapps/net/ncftp/Strn/Strnpcat.c [new file with mode: 0644]
rosapps/net/ncftp/Strn/Strnpcpy.c [new file with mode: 0644]
rosapps/net/ncftp/Strn/Strntok.c [new file with mode: 0644]
rosapps/net/ncftp/Strn/config.h.in [new file with mode: 0644]
rosapps/net/ncftp/Strn/configure.in [new file with mode: 0644]
rosapps/net/ncftp/Strn/strtokc.c [new file with mode: 0644]
rosapps/net/ncftp/Strn/tester.c [new file with mode: 0644]
rosapps/net/ncftp/Strn/version.c [new file with mode: 0644]
rosapps/net/ncftp/autoconf/acconfig.h [new file with mode: 0644]
rosapps/net/ncftp/autoconf/aclocal.m4 [new file with mode: 0644]
rosapps/net/ncftp/libncftp/Makefile.in [new file with mode: 0644]
rosapps/net/ncftp/libncftp/Readme.txt [new file with mode: 0644]
rosapps/net/ncftp/libncftp/cmds.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/config.h.in [new file with mode: 0644]
rosapps/net/ncftp/libncftp/configure.in [new file with mode: 0644]
rosapps/net/ncftp/libncftp/dos2unix.sh [new file with mode: 0644]
rosapps/net/ncftp/libncftp/errno.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/ftp.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/ftp.h [new file with mode: 0644]
rosapps/net/ncftp/libncftp/glob.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/io.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/libncftp.dsp [new file with mode: 0644]
rosapps/net/ncftp/libncftp/libncftp.dsw [new file with mode: 0644]
rosapps/net/ncftp/libncftp/linelist.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/mksrctar.sh [new file with mode: 0644]
rosapps/net/ncftp/libncftp/mksrczip.bat [new file with mode: 0644]
rosapps/net/ncftp/libncftp/ncftp.h [new file with mode: 0644]
rosapps/net/ncftp/libncftp/ncftp_errno.h [new file with mode: 0644]
rosapps/net/ncftp/libncftp/open.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/rcmd.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/syshdrs.h [new file with mode: 0644]
rosapps/net/ncftp/libncftp/util.c [new file with mode: 0644]
rosapps/net/ncftp/libncftp/util.h [new file with mode: 0644]
rosapps/net/ncftp/libncftp/util2.cpp [new file with mode: 0644]
rosapps/net/ncftp/libncftp/wincfg.h [new file with mode: 0644]
rosapps/net/ncftp/makefile [new file with mode: 0644]
rosapps/net/ncftp/ncftp.rc [new file with mode: 0644]
rosapps/net/ncftp/ncftp/Makefile.in [new file with mode: 0644]
rosapps/net/ncftp/ncftp/bookmark.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/bookmark.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/cmdlist.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/cmds.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/cmds.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/getline.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/getline.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/getopt.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/getopt.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/log.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/log.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/ls.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/ls.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/main.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/main.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/pref.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/pref.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/preffw.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/progress.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/progress.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/readln.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/readln.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/resource.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/shell.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/shell.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/spool.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/spool.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/syshdrs.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/trace.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/trace.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/util.c [new file with mode: 0644]
rosapps/net/ncftp/ncftp/util.h [new file with mode: 0644]
rosapps/net/ncftp/ncftp/version.c [new file with mode: 0644]
rosapps/net/ncftp/sio/Makefile.in [new file with mode: 0644]
rosapps/net/ncftp/sio/PRead.c [new file with mode: 0644]
rosapps/net/ncftp/sio/PWrite.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SAcceptA.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SAcceptS.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SBind.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SClose.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SConnect.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SConnectByName.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SError.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SNew.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SRead.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SReadline.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SRecv.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SRecvfrom.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SRecvmsg.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SSelect.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SSend.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SSendto.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SSendtoByName.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SWait.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SWrite.c [new file with mode: 0644]
rosapps/net/ncftp/sio/SocketUtil.c [new file with mode: 0644]
rosapps/net/ncftp/sio/StrAddr.c [new file with mode: 0644]
rosapps/net/ncftp/sio/UAcceptA.c [new file with mode: 0644]
rosapps/net/ncftp/sio/UAcceptS.c [new file with mode: 0644]
rosapps/net/ncftp/sio/UBind.c [new file with mode: 0644]
rosapps/net/ncftp/sio/UConnect.c [new file with mode: 0644]
rosapps/net/ncftp/sio/UConnectByName.c [new file with mode: 0644]
rosapps/net/ncftp/sio/UNew.c [new file with mode: 0644]
rosapps/net/ncftp/sio/URecvfrom.c [new file with mode: 0644]
rosapps/net/ncftp/sio/USendto.c [new file with mode: 0644]
rosapps/net/ncftp/sio/USendtoByName.c [new file with mode: 0644]
rosapps/net/ncftp/sio/config.h.in [new file with mode: 0644]
rosapps/net/ncftp/sio/configure.in [new file with mode: 0644]
rosapps/net/ncftp/sio/main.c [new file with mode: 0644]
rosapps/net/ncftp/sio/sio.h [new file with mode: 0644]
rosapps/net/ncftp/sio/sio.html [new file with mode: 0644]
rosapps/net/ncftp/sio/srltest.c [new file with mode: 0644]
rosapps/net/ncftp/sio/syshdrs.h [new file with mode: 0644]
rosapps/net/ncftp/sio/usio.h [new file with mode: 0644]
rosapps/net/ncftp/sio/wincfg.h [new file with mode: 0644]

diff --git a/rosapps/net/ncftp/Strn/Dynscat.c b/rosapps/net/ncftp/Strn/Dynscat.c
new file mode 100644 (file)
index 0000000..a341379
--- /dev/null
@@ -0,0 +1,54 @@
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "Strn.h"
+
+/*VARARGS*/
+char *
+Dynscat(char **dst, ...)
+{
+       va_list ap;
+       const char *src;
+       char *newdst, *dcp;
+       size_t curLen, catLen, srcLen;
+
+       if (dst == (char **) 0)
+               return NULL;
+
+       catLen = 0;
+       va_start(ap, dst);
+       src = va_arg(ap, char *);
+       while (src != NULL) {
+               catLen += strlen(src);
+               src = va_arg(ap, char *);
+       }
+       va_end(ap);
+
+       if ((*dst == NULL) || (**dst == '\0'))
+               curLen = 0;
+       else
+               curLen = strlen(*dst);
+
+       if (*dst == NULL)
+               newdst = malloc(curLen + catLen + 2);
+       else
+               newdst = realloc(*dst, curLen + catLen + 2);
+       if (newdst == NULL)
+               return NULL;
+
+       dcp = newdst + curLen;
+       va_start(ap, dst);
+       src = va_arg(ap, char *);
+       while (src != NULL) {
+               srcLen = strlen(src);
+               memcpy(dcp, src, srcLen);
+               dcp += srcLen;
+               src = va_arg(ap, char *);
+       }
+       va_end(ap);
+       *dcp = '\0';
+
+       *dst = newdst;
+       return (newdst);
+}      /* Dynscat */
diff --git a/rosapps/net/ncftp/Strn/Makefile.in b/rosapps/net/ncftp/Strn/Makefile.in
new file mode 100644 (file)
index 0000000..e713549
--- /dev/null
@@ -0,0 +1,115 @@
+#
+# Strn makefile
+#
+VER=2.2.0
+PREFIX=@prefix@
+MAN=@prefix@/man
+SHELL=/bin/sh
+.SUFFIXES: .c .o .so
+LIB=libStrn.a
+LIBSO=libStrn.so.1
+LIBSOS=libStrn.so
+CC=@CC@
+CPPFLAGS=
+#CFLAGS=-O2
+CFLAGS=@CFLAGS@
+DEFS=-DSTRNP_ZERO_PAD=0 -DSTRN_ZERO_PAD=1
+
+OBJS=Dynscat.o Strncpy.o Strncat.o Strntok.o Strnpcpy.o Strnpcat.o strtokc.o version.o
+SOBJS=Dynscat.so Strncpy.so Strncat.so Strntok.so Strnpcpy.so Strnpcat.so strtokc.so version.so
+
+all: static
+       -@echo "Done making Strn."
+
+static: $(LIB)
+
+$(LIB): $(OBJS)
+       ar rv $(LIB) $(OBJS)
+       chmod 644 "$(LIB)"
+       -ranlib "$(LIB)"
+       echo "$(VER)" > Strn.version
+       -@/bin/ls -l "$(LIB)"
+
+.c.o:
+       $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c
+
+.c.so:
+       $(CC) -fpic $(CFLAGS) $(CPPFLAGS) $(DEFS) $*.c -c -o $*.so
+
+dynamic: $(LIBSO)
+
+shared: $(LIBSO)
+
+so: $(LIBSO)
+
+$(LIBSO): $(SOBJS)
+       /bin/rm -f "$(LIBSO)"
+       gcc -shared "-Wl,-soname,$(LIBSO)" -o "$(LIBSO)" $(SOBJS)
+       /bin/ln -s "$(LIBSO)" "$(LIBSOS)"
+       -@/bin/ls -l "$(LIBSOS)" "$(LIBSO)"
+
+soinstall: $(LIBSO)
+       cp "$(LIBSO)" "$(PREFIX)/lib/$(LIBSO)"
+       ( cd "$(PREFIX)/lib" ; /bin/ln -s "$(LIBSO)" "$(LIBSOS)" )
+       cp Strn.h "$(PREFIX)/include/Strn.h"
+       -chmod a+r "$(PREFIX)/lib/$(LIBSO)" "$(PREFIX)/include/Strn.h"
+
+tester: $(LIB) tester.c
+       $(CC) $(CFLAGS) tester.c -o tester -I. -L. -lStrn
+
+clean:
+       /bin/rm -f "$(LIB)" "$(LIBSO)" $(OBJS) $(SOBJS)
+
+install:
+       if test ! -d $(PREFIX)/include ; then mkdir -p "$(PREFIX)/include" ; fi
+       if test ! -d $(PREFIX)/lib ; then mkdir -p "$(PREFIX)/lib" ; fi
+       cp "$(LIB)" Strn.version "$(PREFIX)/lib"
+       cp Strn.h "$(PREFIX)/include/Strn.h"
+       -chmod 664 "$(PREFIX)/include/Strn.h" "$(PREFIX)/lib/Strn.version" "$(PREFIX)/lib/$(LIB)"
+       -cp Strn.3 "$(MAN)/man3/Strn.3"
+       -chmod 664 "$(MAN)/man3/Strn.3"
+       -ln "$(MAN)/man3/Strn.3" "$(MAN)/man3/Strncpy.3"
+       -ln "$(MAN)/man3/Strn.3" "$(MAN)/man3/Strncat.3"
+
+uninstall:
+       /bin/rm -f "$(PREFIX)/lib/$(LIB)" "$(PREFIX)/include/Strn.h"
+
+PACKAGE=configure Makefile.in configure.in Strn.dsp Strn.dsw Dynscat.c Strncpy.c Strncat.c Strnpcpy.c Strnpcat.c Strntok.c strtokc.c Strn.h Strn.3 tester.c version.c Strn.version
+
+TMPDIR=/tmp
+TARDIR=Strn
+TARFILE=$(TARDIR).tar
+TGZFILE=$(TARDIR).tgz
+
+tarcp:
+       -@mkdir -p $(TMPDIR)/TAR/$(TARDIR)
+       -@chmod ga+r $(PACKAGE)
+       -@chmod 755 $(TMPDIR)/TAR/$(TARDIR)
+       cp -pr $(PACKAGE) $(TMPDIR)/TAR/$(TARDIR)
+
+tar: $(PACKAGE)
+       -@mkdir $(TMPDIR)/TAR
+       -@mkdir $(TMPDIR)/TAR/$(TARDIR)
+       -@chmod ga+r $(PACKAGE)
+       -@chmod 755 $(TMPDIR)/TAR/$(TARDIR)
+       cp -pr $(PACKAGE) $(TMPDIR)/TAR/$(TARDIR)
+       ( cd $(TMPDIR)/TAR ; tar cf $(TARFILE) ./$(TARDIR) )
+       cp $(TMPDIR)/TAR/$(TARFILE) .
+       -@chmod 644 $(TARFILE)
+       -@rm -rf $(TMPDIR)/TAR
+       -@ls -l $(TARFILE)
+
+gz: tar
+       gzip -c $(TARFILE) > $(TGZFILE)
+       -@rm $(TARFILE)
+       -@chmod 644 $(TGZFILE)
+       -@ls -l $(TGZFILE)
+
+Dynscat.o: Dynscat.c Strn.h
+Strncat.o: Strncat.c Strn.h
+Strncpy.o: Strncpy.c Strn.h
+Strnpcat.o: Strnpcat.c Strn.h
+Strnpcpy.o: Strnpcpy.c Strn.h
+Strntok.o: Strntok.c Strn.h
+strtokc.o: strtokc.c Strn.h
+version.o: version.c
diff --git a/rosapps/net/ncftp/Strn/Strn.h b/rosapps/net/ncftp/Strn/Strn.h
new file mode 100644 (file)
index 0000000..3f8be36
--- /dev/null
@@ -0,0 +1,52 @@
+/* Strn.h */
+
+#ifndef _Strn_h_
+#define _Strn_h_ 1
+
+/* You should define this from the Makefile. */
+#ifndef STRN_ZERO_PAD
+#      define STRN_ZERO_PAD 1
+#endif
+
+/* You should define this from the Makefile. */
+#ifndef STRNP_ZERO_PAD
+#      define STRNP_ZERO_PAD 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Strncat.c */
+char *Strncat(char *const, const char *const, const size_t);
+
+/* Strncpy.c */
+char *Strncpy(char *const, const char *const, const size_t);
+
+/* Strnpcat.c */
+char *Strnpcat(char *const, const char *const, size_t);
+
+/* Strnpcpy.c */
+char *Strnpcpy(char *const, const char *const, size_t);
+
+/* Strntok.c */
+char *Strtok(char *, const char *);
+int Strntok(char *, size_t, char *, const char *);
+
+/* strtokc.c */
+char *strtokc(char *, const char *, char **);
+int strntokc(char *, size_t, char *, const char *, char **);
+
+/* Dynscat.c */
+char * Dynscat(char **dst, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define STRNCPY(d,s) Strncpy((d), (s), (size_t) sizeof(d))
+#define STRNCAT(d,s) Strncat((d), (s), (size_t) sizeof(d))
+
+#endif /* _Strn_h_ */
+
+/* eof Strn.h */
diff --git a/rosapps/net/ncftp/Strn/Strncat.c b/rosapps/net/ncftp/Strn/Strncat.c
new file mode 100644 (file)
index 0000000..0515555
--- /dev/null
@@ -0,0 +1,44 @@
+#include <sys/types.h>
+#include <string.h>
+#include "Strn.h"
+
+/*
+ * Concatenate src on the end of dst.  The resulting string will have at most
+ * n-1 characters, not counting the NUL terminator which is always appended
+ * unlike strncat.  The other big difference is that strncpy uses n as the
+ * max number of characters _appended_, while this routine uses n to limit
+ * the overall length of dst.
+ */
+char *
+Strncat(char *const dst, const char *const src, const size_t n)
+{
+       register size_t i;
+       register char *d;
+       register const char *s;
+
+       if (n != 0 && ((i = strlen(dst)) < (n - 1))) {
+               d = dst + i;
+               s = src;
+               /* If they specified a maximum of n characters, use n - 1 chars to
+                * hold the copy, and the last character in the array as a NUL.
+                * This is the difference between the regular strncpy routine.
+                * strncpy doesn't guarantee that your new string will have a
+                * NUL terminator, but this routine does.
+                */
+               for (++i; i<n; i++) {
+                       if ((*d++ = *s++) == 0) {
+#if (STRN_ZERO_PAD == 1)
+                               /* Pad with zeros. */
+                               for (; i<n; i++)
+                                       *d++ = 0;
+#endif /* STRN_ZERO_PAD */
+                               return dst;
+                       }
+               }
+               /* If we get here, then we have a full string, with n - 1 characters,
+                * so now we NUL terminate it and go home.
+                */
+               *d = 0;
+       }
+       return (dst);
+}      /* Strncat */
diff --git a/rosapps/net/ncftp/Strn/Strncpy.c b/rosapps/net/ncftp/Strn/Strncpy.c
new file mode 100644 (file)
index 0000000..1d77499
--- /dev/null
@@ -0,0 +1,45 @@
+#include <sys/types.h>
+#include <string.h>
+#include "Strn.h"
+
+
+/*
+ * Copy src to dst, truncating or null-padding to always copy n-1 bytes.
+ * Return dst.
+ */
+char *
+Strncpy(char *const dst, const char *const src, const size_t n)
+{
+       register char *d;
+       register const char *s;
+       register size_t i;
+
+       d = dst;
+       *d = 0;
+       if (n != 0) {
+               s = src;
+               /* If they specified a maximum of n characters, use n - 1 chars to
+                * hold the copy, and the last character in the array as a NUL.
+                * This is the difference between the regular strncpy routine.
+                * strncpy doesn't guarantee that your new string will have a
+                * NUL terminator, but this routine does.
+                */
+               for (i=1; i<n; i++) {
+                       if ((*d++ = *s++) == 0) {
+#if (STRN_ZERO_PAD == 1)
+                               /* Pad with zeros. */
+                               for (; i<n; i++)
+                                       *d++ = 0;
+#endif /* STRN_ZERO_PAD */
+                               return dst;
+                       }
+               }
+               /* If we get here, then we have a full string, with n - 1 characters,
+                * so now we NUL terminate it and go home.
+                */
+               *d = 0;
+       }
+       return (dst);
+}      /* Strncpy */
+
+/* eof Strn.c */
diff --git a/rosapps/net/ncftp/Strn/Strnpcat.c b/rosapps/net/ncftp/Strn/Strnpcat.c
new file mode 100644 (file)
index 0000000..c60d926
--- /dev/null
@@ -0,0 +1,54 @@
+#include <sys/types.h>
+#include <string.h>
+#include "Strn.h"
+
+/*
+ * Concatenate src on the end of dst.  The resulting string will have at most
+ * n-1 characters, not counting the NUL terminator which is always appended
+ * unlike strncat.  The other big difference is that strncpy uses n as the
+ * max number of characters _appended_, while this routine uses n to limit
+ * the overall length of dst.
+ *
+ * This routine also differs in that it returns a pointer to the end
+ * of the buffer, instead of strncat which returns a pointer to the start.
+ */
+char *
+Strnpcat(char *const dst, const char *const src, size_t n)
+{
+       register size_t i;
+       register char *d;
+       register const char *s;
+       register char c;
+       char *ret;
+
+       if (n != 0 && ((i = strlen(dst)) < (n - 1))) {
+               d = dst + i;
+               s = src;
+               /* If they specified a maximum of n characters, use n - 1 chars to
+                * hold the copy, and the last character in the array as a NUL.
+                * This is the difference between the regular strncpy routine.
+                * strncpy doesn't guarantee that your new string will have a
+                * NUL terminator, but this routine does.
+                */
+               for (++i; i<n; i++) {
+                       c = *s++;
+                       if (c == '\0') {
+                               ret = d;        /* Return ptr to end byte. */
+                               *d++ = c;
+#if (STRNP_ZERO_PAD == 1)
+                               /* Pad with zeros. */
+                               for (; i<n; i++)
+                                       *d++ = 0;
+#endif /* STRNP_ZERO_PAD */
+                               return ret;
+                       }
+                       *d++ = c;
+               }
+               /* If we get here, then we have a full string, with n - 1 characters,
+                * so now we NUL terminate it and go home.
+                */
+               *d = 0;
+               return (d);     /* Return ptr to end byte. */
+       }
+       return (dst);
+}      /* Strnpcat */
diff --git a/rosapps/net/ncftp/Strn/Strnpcpy.c b/rosapps/net/ncftp/Strn/Strnpcpy.c
new file mode 100644 (file)
index 0000000..f12a877
--- /dev/null
@@ -0,0 +1,54 @@
+#include <sys/types.h>
+#include <string.h>
+#include "Strn.h"
+
+/*
+ * Copy src to dst, truncating or null-padding to always copy n-1 bytes.
+ *
+ * This routine differs from strncpy in that it returns a pointer to the end
+ * of the buffer, instead of strncat which returns a pointer to the start.
+ */
+char *
+Strnpcpy(char *const dst, const char *const src, size_t n)
+{
+       register char *d;
+       register const char *s;
+       register char c;
+       char *ret;
+       register size_t i;
+
+       d = dst;
+       if (n != 0) {
+               s = src;
+               /* If they specified a maximum of n characters, use n - 1 chars to
+                * hold the copy, and the last character in the array as a NUL.
+                * This is the difference between the regular strncpy routine.
+                * strncpy doesn't guarantee that your new string will have a
+                * NUL terminator, but this routine does.
+                */
+               for (i=1; i<n; i++) {
+                       c = *s++;
+                       if (c == '\0') {
+                               ret = d;        /* Return ptr to end byte. */
+                               *d++ = c;
+#if (STRNP_ZERO_PAD == 1)
+                               /* Pad with zeros. */
+                               for (; i<n; i++)
+                                       *d++ = 0;
+#endif /* STRNP_ZERO_PAD */
+                               return ret;
+                       }
+                       *d++ = c;
+               }
+               /* If we get here, then we have a full string, with n - 1 characters,
+                * so now we NUL terminate it and go home.
+                */
+               *d = '\0';
+               return (d);     /* Return ptr to end byte. */
+       } else {
+               *d = 0;
+       }
+       return (d);     /* Return ptr to end byte. */
+}      /* Strnpcpy */
+
+/* eof Strn.c */
diff --git a/rosapps/net/ncftp/Strn/Strntok.c b/rosapps/net/ncftp/Strn/Strntok.c
new file mode 100644 (file)
index 0000000..dfa1833
--- /dev/null
@@ -0,0 +1,179 @@
+/* Strntok.c */
+
+#include <string.h>
+#include "Strn.h"
+
+/* This version of Strtok differs from the regular ANSI strtok in that
+ * an empty token can be returned, and consecutive delimiters are not
+ * ignored like ANSI does.  Example:
+ *
+ * Parse String = ",,mike,gleason,-West Interactive,402-573-1000"
+ * Delimiters = ",-"
+ *
+ * (ANSI strtok:)
+ * strtok 1=[mike] length=4
+ * strtok 2=[gleason] length=7
+ * strtok 3=[West Interactive] length=16
+ * strtok 4=[402] length=3
+ * strtok 5=[573] length=3
+ * strtok 6=[1000] length=4
+ * 
+ * (Strtok:)
+ * Strtok 1=[] length=0
+ * Strtok 2=[] length=0
+ * Strtok 3=[mike] length=4
+ * Strtok 4=[gleason] length=7
+ * Strtok 5=[] length=0
+ * Strtok 6=[West Interactive] length=16
+ * Strtok 7=[402] length=3
+ * Strtok 8=[573] length=3
+ * Strtok 9=[1000] length=4
+ *
+ */
+
+char *
+Strtok(char *buf, const char *delims)
+{
+       static char *p = NULL;
+       char *start, *end;
+
+       if (buf != NULL) {
+               p = buf;
+       } else {
+               if (p == NULL)
+                       return (NULL);          /* No more tokens. */
+       }
+       for (start = p, end = p; ; end++) {
+               if (*end == '\0') {
+                       p = NULL;               /* This is the last token. */
+                       break;
+               }
+               if (strchr(delims, (int) *end) != NULL) {
+                       *end++ = '\0';
+                       p = end; 
+                       break;
+               }
+       }
+       return (start);
+}      /* Strtok */
+
+
+
+
+/* This is a bounds-safe version of Strtok, where you also pass a pointer
+ * to the token to write into, and its size.  Using the example above,
+ * with a char token[8], you get the following.  Notice that the token
+ * is not overrun, and is always nul-terminated:
+ *
+ * Strntok 1=[] length=0
+ * Strntok 2=[] length=0
+ * Strntok 3=[mike] length=4
+ * Strntok 4=[gleason] length=7
+ * Strntok 5=[] length=0
+ * Strntok 6=[West In] length=7
+ * Strntok 7=[402] length=3
+ * Strntok 8=[573] length=3
+ * Strntok 9=[1000] length=4
+ */
+
+int
+Strntok(char *dstTokenStart, size_t tokenSize, char *buf, const char *delims)
+{
+       static char *p = NULL;
+       char *end;
+       char *lim;
+       char *dst;
+       int len;
+
+       dst = dstTokenStart;
+       lim = dst + tokenSize - 1;              /* Leave room for nul byte. */
+
+       if (buf != NULL) {
+               p = buf;
+       } else {
+               if (p == NULL) {
+                       *dst = '\0';
+                       return (-1);            /* No more tokens. */
+               }
+       }
+
+       for (end = p; ; end++) {
+               if (*end == '\0') {
+                       p = NULL;               /* This is the last token. */
+                       break;
+               }
+               if (strchr(delims, (int) *end) != NULL) {
+                       ++end;
+                       p = end; 
+                       break;
+               }
+               if (dst < lim)                  /* Don't overrun token size. */
+                       *dst++ = *end;
+       }
+       *dst = '\0';
+       len = (int) (dst - dstTokenStart);      /* Return length of token. */
+
+#if (STRN_ZERO_PAD == 1)
+       /* Pad with zeros. */
+       for (++dst; dst <= lim; )
+               *dst++ = 0;
+#endif /* STRN_ZERO_PAD */
+
+       return (len);
+}      /* Strntok */
+
+
+
+#ifdef TESTING_STRTOK
+#include <stdio.h>
+
+void
+main(int argc, char **argv)
+{
+       char buf[256];
+       int i;
+       char *t;
+       char token[8];
+       int tokenLen;
+
+       if (argc < 3) {
+               fprintf(stderr, "Usage: test \"buffer,with,delims\" <delimiters>\n");
+               exit(1);
+       }
+       strcpy(buf, argv[1]);
+       i = 1;
+       t = strtok(buf, argv[2]);
+       if (t == NULL)
+               exit(0);
+       do {
+               printf("strtok %d=[%s] length=%d\n", i, t, (int) strlen(t));
+               t = strtok(NULL, argv[2]);
+               ++i;
+       } while (t != NULL);
+
+       printf("------------------------------------------------\n");
+       strcpy(buf, argv[1]);
+       i = 1;
+       t = Strtok(buf, argv[2]);
+       if (t == NULL)
+               exit(0);
+       do {
+               printf("Strtok %d=[%s] length=%d\n", i, t, (int) strlen(t));
+               t = Strtok(NULL, argv[2]);
+               ++i;
+       } while (t != NULL);
+
+       printf("------------------------------------------------\n");
+       strcpy(buf, argv[1]);
+       i = 1;
+       tokenLen = Strntok(token, sizeof(token), buf, argv[2]);
+       if (tokenLen < 0)
+               exit(0);
+       do {
+               printf("Strntok %d=[%s] length=%d\n", i, token, tokenLen);
+               tokenLen = Strntok(token, sizeof(token), NULL, argv[2]);
+               ++i;
+       } while (tokenLen >= 0);
+       exit(0);
+}
+#endif
diff --git a/rosapps/net/ncftp/Strn/config.h.in b/rosapps/net/ncftp/Strn/config.h.in
new file mode 100644 (file)
index 0000000..2122b45
--- /dev/null
@@ -0,0 +1,10 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
diff --git a/rosapps/net/ncftp/Strn/configure.in b/rosapps/net/ncftp/Strn/configure.in
new file mode 100644 (file)
index 0000000..be5b946
--- /dev/null
@@ -0,0 +1,19 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(Strn.h)
+wi_ARG_ENABLE_DEBUG
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_LN_S
+AC_PROG_RANLIB
+
+dnl Checks for header files.
+AC_HEADER_STDC
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+
+dnl Checks for library functions.
+
+AC_OUTPUT(Makefile)
diff --git a/rosapps/net/ncftp/Strn/strtokc.c b/rosapps/net/ncftp/Strn/strtokc.c
new file mode 100644 (file)
index 0000000..ee1841d
--- /dev/null
@@ -0,0 +1,240 @@
+/* strtokc.c */
+
+#include <string.h>
+#include "Strn.h"
+
+char *
+strtokc(char *parsestr, const char *delims, char **context)
+{
+       char *cp;
+       const char *cp2;
+       char c, c2;
+       char *start;
+
+       if (parsestr == NULL)
+               start = *context;
+       else
+               start = parsestr;
+
+       if ((start == NULL) || (delims == NULL)) {
+               *context = NULL;
+               return NULL;
+       }
+
+       /* Eat leading delimiters. */
+       for (cp = start; ; ) {
+next1:
+               c = *cp++;
+               if (c == '\0') {
+                       /* No more tokens. */
+                       *context = NULL;
+                       return (NULL);
+               }
+               for (cp2 = delims; ; ) {
+                       c2 = (char) *cp2++;
+                       if (c2 == '\0') {
+                               /* This character was not a delimiter.
+                                * The token starts here.
+                                */
+                               start = cp - 1;
+                               goto starttok;
+                       }
+                       if (c2 == c) {
+                               /* This char was a delimiter. */
+                               /* Skip it, look at next character. */
+                               goto next1;
+                       }
+               }
+               /*NOTREACHED*/
+       }
+
+starttok:
+       for ( ; ; cp++) {
+               c = *cp;
+               if (c == '\0') {
+                       /* Token is finished. */
+                       *context = cp;
+                       break;
+               }
+               for (cp2 = delims; ; ) {
+                       c2 = (char) *cp2++;
+                       if (c2 == '\0') {
+                               /* This character was not a delimiter.
+                                * Keep it as part of current token.
+                                */
+                               break;
+                       }
+                       if (c2 == c) {
+                               /* This char was a delimiter. */
+                               /* End of token. */
+                               *cp++ = '\0';
+                               *context = cp;
+                               return (start);
+                       }
+               }
+       }
+       return (start);
+}      /* strtokc */
+
+
+
+
+/* Same as strtokc, only you specify the destination buffer to write
+ * the token in along with its size.  strntokc will write to the dst
+ * buffer, always nul-terminating it.
+ *
+ * It also returns the length of the token, or zero if there was no
+ * token.  This differs from strtokc, which returns a pointer to the
+ * token or NULL for no token.
+ */
+
+int
+strntokc(char *dstTokenStart, size_t tokenSize, char *parsestr, const char *delims, char **context)
+{
+       char *cp;
+       const char *cp2;
+       char c, c2;
+       char *start;
+       int len;
+       char *dst, *lim;
+
+       dst = dstTokenStart;
+       lim = dst + tokenSize - 1;              /* Leave room for nul byte. */
+
+       if (parsestr == NULL)
+               start = *context;
+       else
+               start = parsestr;
+
+       if ((start == NULL) || (delims == NULL)) {
+               *context = NULL;
+               goto done;
+       }
+
+       /* Eat leading delimiters. */
+       for (cp = start; ; ) {
+next1:
+               c = *cp++;
+               if (c == '\0') {
+                       /* No more tokens. */
+                       *context = NULL;
+                       goto done;
+               }
+               for (cp2 = delims; ; ) {
+                       c2 = (char) *cp2++;
+                       if (c2 == '\0') {
+                               /* This character was not a delimiter.
+                                * The token starts here.
+                                */
+                               start = cp - 1;
+                               if (dst < lim)
+                                       *dst++ = c;
+                               goto starttok;
+                       }
+                       if (c2 == c) {
+                               /* This char was a delimiter. */
+                               /* Skip it, look at next character. */
+                               goto next1;
+                       }
+               }
+               /*NOTREACHED*/
+       }
+
+starttok:
+       for ( ; ; cp++) {
+               c = *cp;
+               if (c == '\0') {
+                       /* Token is finished. */
+                       *context = cp;
+                       break;
+               }
+               for (cp2 = delims; ; ) {
+                       c2 = (char) *cp2++;
+                       if (c2 == '\0') {
+                               /* This character was not a delimiter.
+                                * Keep it as part of current token.
+                                */
+                               break;
+                       }
+                       if (c2 == c) {
+                               /* This char was a delimiter. */
+                               /* End of token. */
+                               *cp++ = '\0';
+                               *context = cp;
+                               goto done;
+                       }
+               }
+               if (dst < lim)                  /* Don't overrun token size. */
+                       *dst++ = c;
+       }
+
+done:
+       *dst = '\0';
+       len = (int) (dst - dstTokenStart);      /* Return length of token. */
+
+#if (STRN_ZERO_PAD == 1)
+       /* Pad with zeros. */
+       for (++dst; dst <= lim; )
+               *dst++ = 0;
+#endif /* STRN_ZERO_PAD */
+
+       return (len);
+}      /* strntokc */
+
+
+
+
+#ifdef TESTING_STRTOK
+#include <stdio.h>
+
+void
+main(int argc, char **argv)
+{
+       char buf[256];
+       int i;
+       char *t;
+       char token[8];
+       int tokenLen;
+       char *context;
+
+       if (argc < 3) {
+               fprintf(stderr, "Usage: test \"buffer,with,delims\" <delimiters>\n");
+               exit(1);
+       }
+       strcpy(buf, argv[1]);
+       i = 1;
+       t = strtok(buf, argv[2]);
+       if (t == NULL)
+               exit(0);
+       do {
+               printf("strtok %d=[%s] length=%d\n", i, t, (int) strlen(t));
+               t = strtok(NULL, argv[2]);
+               ++i;
+       } while (t != NULL);
+
+       printf("------------------------------------------------\n");
+       strcpy(buf, argv[1]);
+       i = 1;
+       t = strtokc(buf, argv[2], &context);
+       if (t == NULL)
+               exit(0);
+       do {
+               printf("strtokc %d=[%s] length=%d\n", i, t, (int) strlen(t));
+               t = strtokc(NULL, argv[2], &context);
+               ++i;
+       } while (t != NULL);
+
+       printf("------------------------------------------------\n");
+       strcpy(buf, argv[1]);
+       i = 1;
+       tokenLen = strntokc(token, sizeof(token), buf, argv[2], &context);
+       if (tokenLen <= 0)
+               exit(0);
+       do {
+               printf("strntokc %d=[%s] length=%d\n", i, token, tokenLen);
+               tokenLen = strntokc(token, sizeof(token), NULL, argv[2], &context);
+               ++i;
+       } while (tokenLen > 0);
+       exit(0);
+}
+#endif
diff --git a/rosapps/net/ncftp/Strn/tester.c b/rosapps/net/ncftp/Strn/tester.c
new file mode 100644 (file)
index 0000000..66e3034
--- /dev/null
@@ -0,0 +1,135 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Strn.h>
+
+int main(int argc, char **argv)
+{
+       char a[8];
+       char pad1[32];
+       char *b;
+       char c[37];
+       char pad2[23];
+       int i;
+       int len1, len2;
+
+       b = Strncpy(a, "hello", sizeof(a));
+       b = Strncat(b, "world", sizeof(a));
+       printf("1: result=[%s] should be=[%s]\n",
+               b,
+               "hellowo"
+       );
+
+       for (i=0; i<sizeof(c); i++)
+               c[i] = 'X';
+       b = Strncpy(c, "testing", sizeof(c) - 2);
+#if (STRN_ZERO_PAD == 1)
+       for (i=7; i<sizeof(c) - 2; i++) {
+               if (c[i] != '\0') {
+                       printf("2: did not clear to end of buffer\n");
+                       break;
+               }
+       }
+#endif
+       for (i=sizeof(c) - 2; i<sizeof(c); i++) {
+               if (c[i] != 'X') {
+                       printf("2: overwrote buffer\n");
+                       break;
+               }
+       }
+
+       for (i=0; i<sizeof(c); i++)
+               c[i] = 'X';
+       b = Strncpy(c, "testing", sizeof(c) - 2);
+       b = Strncat(b, " still", sizeof(c) - 2);
+#if (STRN_ZERO_PAD == 1)
+       for (i=13; i<sizeof(c) - 2; i++) {
+               if (c[i] != '\0') {
+                       printf("3: did not clear to end of buffer\n");
+                       break;
+               }
+       }
+#endif
+       for (i=sizeof(c) - 2; i<sizeof(c); i++) {
+               if (c[i] != 'X') {
+                       printf("3: overwrote buffer\n");
+                       break;
+               }
+       }
+
+/*--------------*/
+
+       b = Strnpcpy(a, "hello", sizeof(a));
+       len1 = (int) (b - a);
+       b = Strnpcat(a, "world", sizeof(a));
+       len2 = (int) (b - a);
+       printf("4: result=[%s] should be=[%s] len1=%d len2=%d\n",
+               a,
+               "hellowo",
+               len1,
+               len2
+       );
+
+       for (i=0; i<sizeof(c); i++)
+               c[i] = 'X';
+       b = Strnpcpy(c, "testing", sizeof(c) - 2);
+#if (STRNP_ZERO_PAD == 1)
+       for (i=7; i<sizeof(c) - 2; i++) {
+               if (c[i] != '\0') {
+                       printf("5: did not clear to end of buffer\n");
+                       break;
+               }
+       }
+#endif
+       for (i=sizeof(c) - 2; i<sizeof(c); i++) {
+               if (c[i] != 'X') {
+                       printf("5: overwrote buffer\n");
+                       break;
+               }
+       }
+
+       for (i=0; i<sizeof(c); i++)
+               c[i] = 'X';
+       b = Strnpcpy(c, "testing", sizeof(c) - 2);
+       b = Strnpcat(c, " still", sizeof(c) - 2);
+#if (STRNP_ZERO_PAD == 1)
+       for (i=13; i<sizeof(c) - 2; i++) {
+               if (c[i] != '\0') {
+                       printf("6: did not clear to end of buffer\n");
+                       break;
+               }
+       }
+#endif
+       for (i=sizeof(c) - 2; i<sizeof(c); i++) {
+               if (c[i] != 'X') {
+                       printf("6: overwrote buffer\n");
+                       break;
+               }
+       }
+
+/*--------------*/
+       {
+               char *str;
+
+               str = NULL;
+               if (Dynscat(&str, "this is a test", 0) == NULL) {
+                       printf("7a: fail\n");
+               } else if (strcmp(str, "this is a test") != 0) {
+                       printf("7b: fail\n");
+               }
+               free(str);
+
+               str = NULL;
+               if (Dynscat(&str, "this is a test", 0) == NULL) {
+                       printf("7c: fail\n");
+               } else if (strcmp(str, "this is a test") != 0) {
+                       printf("7d: fail\n");
+               } else if (Dynscat(&str, " ", "", "and", " ", "so is this", 0) == NULL) {
+                       printf("7e: fail\n");
+               } else if (strcmp(str, "this is a test and so is this") != 0) {
+                       printf("7f: fail\n");
+               }
+               free(str);
+       }
+       exit(0);
+}
diff --git a/rosapps/net/ncftp/Strn/version.c b/rosapps/net/ncftp/Strn/version.c
new file mode 100644 (file)
index 0000000..4afb9b5
--- /dev/null
@@ -0,0 +1 @@
+char gStrnLibVersion[20] = "@(#) Strn 2.2.0";
diff --git a/rosapps/net/ncftp/autoconf/acconfig.h b/rosapps/net/ncftp/autoconf/acconfig.h
new file mode 100644 (file)
index 0000000..aefe313
--- /dev/null
@@ -0,0 +1,389 @@
+/* acconfig.h
+   This file is in the public domain.
+
+   Descriptive text for the C preprocessor macros that
+   the distributed Autoconf macros can define.
+   No software package will use all of them; autoheader copies the ones
+   your configure.in uses into your configuration header file templates.
+
+   The entries are in sort -df order: alphabetical, case insensitive,
+   ignoring punctuation (such as underscores).  Although this order
+   can split up related entries, it makes it easier to check whether
+   a given entry is in the file.
+
+   Leave the following blank line there!!  Autoheader needs it.  */
+\f
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+#undef CAN_USE_SYS_SELECT_H
+
+/* Define if using alloca.c.  */
+#undef C_ALLOCA
+
+/* Define if type char is unsigned and you are not using gcc.  */
+#ifndef __CHAR_UNSIGNED__
+#undef __CHAR_UNSIGNED__
+#endif
+
+/* Define if the closedir function returns void instead of int.  */
+#undef CLOSEDIR_VOID
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+#undef CRAY_STACKSEG_END
+
+/* Define for DGUX with <sys/dg_sys_info.h>.  */
+#undef DGUX
+
+/* Define if you have <dirent.h>.  */
+#undef DIRENT
+
+/* Define to the type of elements in the array set by `getgroups'.
+   Usually this is either `int' or `gid_t'.  */
+#undef GETGROUPS_T
+
+/* Define if the `getloadavg' function needs to be run setuid or setgid.  */
+#undef GETLOADAVG_PRIVILEGED
+
+/* Define if the `getpgrp' function takes no argument.  */
+#undef GETPGRP_VOID
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef gid_t
+
+/* Define if you have alloca, as a function or macro.  */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#undef HAVE_ALLOCA_H
+
+/* Define if your curses library has this functionality. */
+#undef HAVE_BEEP
+
+#undef HAVE_CURSES_H
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+#undef HAVE_DOPRNT
+
+/* Define if your system has a working fnmatch function.  */
+#undef HAVE_FNMATCH
+
+/* Define if your curses library has this functionality. */
+#undef HAVE_GETBEGX
+
+/* Define if your system has its own `getloadavg' function.  */
+#undef HAVE_GETLOADAVG
+
+/* Define if your curses library has this functionality. */
+#undef HAVE_GETMAXX
+
+/* Define if your curses library has this functionality. */
+#undef HAVE_GETMAXYX
+
+/* Define if you have the getmntent function.  */
+#undef HAVE_GETMNTENT
+
+/* Define if you have <hpsecurity.h>.  */
+#undef HAVE_HPSECURITY_H
+
+/* Define if you have the curses library. */
+#undef HAVE_LIBCURSES
+
+/* Define if you want to use the Hpwd library, and you also have it's corresponding database library (such as *dbm). */
+#undef HAVE_LIBHPWD
+
+/* Define if you have the ncurses library. */
+#undef HAVE_LIBNCURSES
+
+/* Define if you have the readline library, version 2.0 or higher. */
+#undef HAVE_LIBREADLINE
+
+/* Define if the `long double' type works.  */
+#undef HAVE_LONG_DOUBLE
+
+/* Define if you support file names longer than 14 characters.  */
+#undef HAVE_LONG_FILE_NAMES
+
+/* Define if your compiler supports the "long long" integral type. */
+#undef HAVE_LONG_LONG
+
+/* Most system's curses library uses a _maxx field instead of maxx. */
+#undef HAVE__MAXX
+
+/* Define if you have a working `mmap' system call.  */
+#undef HAVE_MMAP
+
+#undef HAVE_MSGHDR_ACCRIGHTS
+
+#undef HAVE_MSGHDR_CONTROL
+
+#undef HAVE_PR_PASSWD_FG_OLDCRYPT
+
+/* Define if you have a _res global variable used by resolve routines. */
+#undef HAVE__RES_DEFDNAME
+
+/* Define if system calls automatically restart after interruption
+   by a signal.  */
+#undef HAVE_RESTARTABLE_SYSCALLS
+
+/* Define if you have sigsetjmp and siglongjmp. */
+#undef HAVE_SIGSETJMP
+
+#undef HAVE_SOCKADDR_UN_SUN_LEN
+
+#undef HAVE_STATFS_F_BAVAIL
+
+/* Define if your struct stat has st_blksize.  */
+#undef HAVE_ST_BLKSIZE
+
+/* Define if your struct stat has st_blocks.  */
+#undef HAVE_ST_BLOCKS
+
+/* Define if you have the strcoll function and it is properly defined.  */
+#undef HAVE_STRCOLL
+
+/* Define if your struct stat has st_rdev.  */
+#undef HAVE_ST_RDEV
+
+/* Define if you have the strftime function.  */
+#undef HAVE_STRFTIME
+
+/* Define if you have the ANSI # stringizing operator in cpp. */
+#undef HAVE_STRINGIZE
+
+#undef HAVE_STRUCT_CMSGDHR
+
+#undef HAVE_STRUCT_STAT64
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if your curses library has this functionality. */
+#undef HAVE_TOUCHWIN
+
+/* Define if your struct tm has tm_zone.  */
+#undef HAVE_TM_ZONE
+
+/* Define if you don't have tm_zone but do have the external array
+   tzname.  */
+#undef HAVE_TZNAME
+
+/* Define if you have <unistd.h>.  */
+#undef HAVE_UNISTD_H
+
+/* Define if utime(file, NULL) sets file's timestamp to the present.  */
+#undef HAVE_UTIME_NULL
+
+/* Define if you have a ut_host field in your struct utmp. */
+#undef HAVE_UTMP_UT_HOST
+
+#undef HAVE_UTMP_UT_NAME
+
+#undef HAVE_UTMP_UT_USER
+
+#undef HAVE_UTMP_UT_PID
+
+#undef HAVE_UTMP_UT_TIME
+
+#undef HAVE_UTMPX_UT_SYSLEN
+
+/* Define if you have <vfork.h>.  */
+#undef HAVE_VFORK_H
+
+/* Define if you have the vprintf function.  */
+#undef HAVE_VPRINTF
+
+/* Define if you have the wait3 system call.  */
+#undef HAVE_WAIT3
+
+/* Define as __inline if that's what the C compiler calls it.  */
+#undef inline
+
+/* Define if chown is promiscuous (regular user can give away ownership) */
+#undef INSECURE_CHOWN
+
+/* Define if int is 16 bits instead of 32.  */
+#undef INT_16_BITS
+
+/* Define if long int is 64 bits.  */
+#undef LONG_64_BITS
+
+/* Define if major, minor, and makedev are declared in <mkdev.h>.  */
+#undef MAJOR_IN_MKDEV
+
+/* Define if major, minor, and makedev are declared in <sysmacros.h>.  */
+#undef MAJOR_IN_SYSMACROS
+
+/* Define if on MINIX.  */
+#undef _MINIX
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef mode_t
+
+/* Define if you don't have <dirent.h>, but have <ndir.h>.  */
+#undef NDIR
+
+/* Define if you have <memory.h>, and <string.h> doesn't declare the
+   mem* functions.  */
+#undef NEED_MEMORY_H
+
+/* Define if your struct nlist has an n_un member.  */
+#undef NLIST_NAME_UNION
+
+/* Define if you have <nlist.h>.  */
+#undef NLIST_STRUCT
+
+/* Define if your C compiler doesn't accept -c and -o together.  */
+#undef NO_MINUS_C_MINUS_O
+
+/* Define if your Fortran 77 compiler doesn't accept -c and -o together. */
+#undef F77_NO_MINUS_C_MINUS_O
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+#undef OS
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef pid_t
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+#undef _POSIX_1_SOURCE
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Format string for the printf() family for 64 bit integers. */
+#undef PRINTF_LONG_LONG
+
+/* Define if printing a "long long" with "%lld" works . */
+#undef PRINTF_LONG_LONG_LLD
+
+/* Define if printing a "long long" with "%qd" works . */
+#undef PRINTF_LONG_LONG_QD
+
+/* Define if your C compiler supports ANSI C function prototyping. */
+#undef PROTOTYPES
+
+/* Define as the return type of signal handlers (int or void).  */
+#undef RETSIGTYPE
+
+/* Format string for the scanf() family for 64 bit integers. */
+#undef SCANF_LONG_LONG
+
+/* Define if scanning a "long long" with "%lld" works. */
+#undef SCANF_LONG_LONG_LLD
+
+/* Define if scanning a "long long" with "%qd" works. */
+#undef SCANF_LONG_LONG_QD
+  
+/* Define to the type of arg1 for select(). */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for select(). */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg5 for select(). */
+#undef SELECT_TYPE_ARG5
+
+/* Define if the `setpgrp' function takes no argument.  */
+#undef SETPGRP_VOID
+
+/* Define if the setvbuf function takes the buffering type as its second
+   argument and the buffer pointer as the third, as on System V
+   before release 3.  */
+#undef SETVBUF_REVERSED
+
+/* Define to `int' if <sys/signal.h> doesn't define.  */
+#undef sig_atomic_t
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+#undef SNPRINTF_TERMINATES
+
+#undef SPRINTF_RETURNS_PTR
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly.  */
+#undef STAT_MACROS_BROKEN
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define on System V Release 4.  */
+#undef SVR4
+
+/* Define if you don't have <dirent.h>, but have <sys/dir.h>.  */
+#undef SYSDIR
+
+/* Define if you don't have <dirent.h>, but have <sys/ndir.h>.  */
+#undef SYSNDIR
+
+/* Define if `sys_siglist' is declared by <signal.h>.  */
+#undef SYS_SIGLIST_DECLARED
+
+/* Define to the full path of the Tar program, if you have it. */
+#undef TAR
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your <sys/time.h> declares struct tm.  */
+#undef TM_IN_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef uid_t
+
+/* Define for Encore UMAX.  */
+#undef UMAX
+
+/* Result of "uname -a" */
+#undef UNAME
+
+/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
+   instead of <sys/cpustats.h>.  */
+#undef UMAX4_3
+
+/* Define if you do not have <strings.h>, index, bzero, etc..  */
+#undef USG
+
+/* Define vfork as fork if vfork does not work.  */
+#undef vfork
+
+/* Define if the closedir function returns void instead of int.  */
+#undef VOID_CLOSEDIR
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
+#undef WORDS_BIGENDIAN
+
+/* Define if the X Window System is missing or not being used.  */
+#undef X_DISPLAY_MISSING
+
+/* Define if lex declares yytext as a char * by default, not a char[].  */
+#undef YYTEXT_POINTER
+
+\f
+/* Leave that blank line there!!  Autoheader needs it.
+   If you're adding to this file, keep in mind:
+   The entries are in sort -df order: alphabetical, case insensitive,
+   ignoring punctuation (such as underscores).  */
diff --git a/rosapps/net/ncftp/autoconf/aclocal.m4 b/rosapps/net/ncftp/autoconf/aclocal.m4
new file mode 100644 (file)
index 0000000..1c5a95e
--- /dev/null
@@ -0,0 +1,2391 @@
+AC_DEFUN(wi_ARG_ENABLE_DEBUG, [
+# if DEBUGBUILD is yes, other macros try to set up a compilation environment
+# with debugging symbols enabled.  Example macros which are affected are
+# wi_CFLAGS and wi_SFLAG.
+#
+DEBUGBUILD=no
+DEBUGCONFIGUREFLAG=""
+AC_ARG_ENABLE(debug,
+[  --enable-debug          enable debugging symbols],
+[
+       DEBUGBUILD=yes
+       DEBUGCONFIGUREFLAG="--enable-debug"
+],[
+       DEBUGBUILD=no
+       DEBUGCONFIGUREFLAG=""
+])
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_EXTRA_IDIR, [
+incdir="$1"
+if test -r $incdir ; then
+       case "$CPPFLAGS" in
+               *${incdir}*)
+                       # echo "   + already had $incdir" 1>&6
+                       ;;
+               *)
+                       if test "$CPPFLAGS" = "" ; then
+                               CPPFLAGS="-I$incdir"
+                       else
+                               CPPFLAGS="$CPPFLAGS -I$incdir"
+                       fi
+                       echo "   + found $incdir" 1>&6
+                       ;;
+       esac
+fi
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_PROG_TAR, [
+TAR=""
+AC_PATH_PROG(TAR, "tar")
+if test -x "$TAR" ; then
+       AC_DEFINE_UNQUOTED(TAR, "$TAR")
+fi
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_EXTRA_LDIR, [
+libdir="$1"
+if test -r $libdir ; then
+       case "$LDFLAGS" in
+               *${libdir}*)
+                       # echo "   + already had $libdir" 1>&6
+                       ;;
+               *)
+                       if test "$LDFLAGS" = "" ; then
+                               LDFLAGS="-L$libdir"
+                       else
+                               LDFLAGS="$LDFLAGS -L$libdir"
+                       fi
+                       echo "   + found $libdir" 1>&6
+                       ;;
+       esac
+fi
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_GNU_LD, [
+AC_MSG_CHECKING([for GNU ld])
+wi_cv_prog_ld="ld"
+result="no"
+x=`ld --version 2>/dev/null | fgrep GNU`
+if test "$x" != "" ; then
+       wi_cv_prog_ld="gld"
+       result="yes"
+fi
+AC_MSG_RESULT($result)
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LD_READONLY_TEXT, [
+if test "$SYS$wi_cv_prog_ld" = "linuxgld" ; then
+       LDFLAGS="$LDFLAGS -Xlinker -n"
+fi
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_EXTRA_SYSV_SUNOS_DIRS, [
+AC_MSG_CHECKING([for System V compatibility directories])
+AC_MSG_RESULT([])
+wi_EXTRA_IDIR("/usr/5include")
+wi_EXTRA_LDIR("/usr/5lib")
+])
+dnl
+dnl
+dnl If you want to also look for include and lib subdirectories in the
+dnl $HOME tree, you supply "yes" as the first argument to this macro.
+dnl
+dnl If you want to look for subdirectories in include/lib directories,
+dnl you pass the names in argument 3, otherwise pass a dash.
+dnl
+AC_DEFUN(wi_EXTRA_DIRS, [
+AC_MSG_CHECKING([for extra include and lib directories])
+AC_MSG_RESULT([])
+ifelse([$1], yes, [dnl
+b1=`cd .. ; pwd`
+b2=`cd ../.. ; pwd`
+exdirs="$HOME $j $b1 $b2 $prefix $2"
+if test -x "$HOME/bin/OS" ; then
+       b3=`$HOME/bin/OS`
+       b3="$HOME/$b3"
+       if test -d "$b3" ; then
+               exdirs="$b3 $exdirs"
+       fi
+fi
+],[dnl
+exdirs="$prefix $2"
+])
+subexdirs="$3"
+if test "$subexdirs" = "" ; then
+       subexdirs="-"
+fi
+for subexdir in $subexdirs ; do
+if test "$subexdir" = "-" ; then
+       subexdir=""
+else
+       subexdir="/$subexdir"
+fi
+for exdir in $exdirs ; do
+       case "$exdir" in
+               "/usr"|"/"|"//")
+                       if test "$exdir" = "//" ; then exdir="/" ; fi
+                       if test "$subexdir" != ""; then
+                               incdir="${exdir}/include${subexdir}"
+                               wi_EXTRA_IDIR($incdir)
+
+                               libdir="${exdir}/lib${subexdir}"
+                               wi_EXTRA_LDIR($libdir)
+                       fi
+                       ;;
+               *)
+                       if test "$subexdir" = ""; then
+                               incdir="${exdir}/include${subexdir}"
+                               wi_EXTRA_IDIR($incdir)
+
+                               libdir="${exdir}/lib${subexdir}"
+                               wi_EXTRA_LDIR($libdir)
+                       fi
+                       ;;
+       esac
+done
+done
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_HPUX_CFLAGS,
+[AC_MSG_CHECKING(if HP-UX ansi C compiler flags are needed)
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([wi_OS_VAR])
+ac_cv_hpux_flags=no
+if test "$os" = hp-ux ; then
+       if test "$ac_cv_prog_gcc" = yes ; then
+               if test "$CFLAGS" != "" ; then
+                       # Shouldn't be in there.
+changequote(<<, >>)dnl
+                       CFLAGS=`echo "$CFLAGS" | sed 's/-A[ae]//g'`
+changequote([, ])dnl
+                       case "$CFLAGS" in
+                               *_HPUX_SOURCE*)
+                                       ;;
+                               *)
+                                       # This is required for the extended
+                                       # namespace.
+                                       #
+                                       CFLAGS="-D_HPUX_SOURCE $CFLAGS"
+                                       ;;
+                       esac
+               fi
+       else
+               # If you're not using gcc, then you better have a cc/c89
+               # that is usable.  If you have the barebones compiler, it
+               # won't work.  The good compiler uses -Aa for the ANSI
+               # compatible stuff.
+changequote(<<, >>)dnl
+               x=`echo "$CFLAGS" | grep 'A[ae]' 2>/dev/null`
+changequote([, ])dnl
+               if test "$x" = "" ; then
+                       CFLAGS="$CFLAGS -Ae"
+               fi
+       fi
+       ac_cv_hpux_flags=yes
+fi
+AC_MSG_RESULT($ac_cv_hpux_flags)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_SFLAG, [AC_REQUIRE([AC_PROG_CC])
+STRIP="strip"
+if test "$SFLAG" = "" ; then
+       SFLAG="-s"
+       case "$OS" in
+               macosx*)
+                       SFLAG='-Wl,-x'
+                       ;;
+       esac
+fi
+#
+# Was it ./configure --enable-debug ?
+#
+if test "$DEBUGBUILD" = yes ; then
+       SFLAG=""
+       STRIP=":"
+fi
+case "$CFLAGS" in
+       "-g"|"-g "*|*" -g"|*" -g "*|*"-g"[0-9]*)
+               # SFLAG="# $SFLAG"
+               SFLAG=""
+               STRIP=":"
+               ;;
+esac
+STRIPFLAG="$SFLAG"
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_REQUEST_NO_Y2K_WARNINGS, [
+       wi_cv_request_no_y2k=yes
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_CFLAGS_NO_Y2K_WARNINGS, [AC_REQUIRE([AC_PROG_CC])
+if test "$ac_cv_prog_gcc" = yes ; then
+       case "$CFLAGS" in
+               *-Wno-format-y2k*)
+                       ;;
+               *)
+                       oldCFLAGS="$CFLAGS"
+                       CFLAGS="$CFLAGS -Wno-format-y2k"
+                       #
+                       # Now check if this version of GCC
+                       # accepts this flag...
+                       #
+AC_TRY_COMPILE([],[int junk;],[],[CFLAGS="$oldCFLAGS"])
+                       unset oldCFLAGS
+                       ;;
+       esac
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_CFLAGS, [AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE_CPP()
+wi_HPUX_CFLAGS
+       if test "$CFLAGS" = "" ; then
+               AC_MSG_WARN([Your CFLAGS environment variable was not set.  A default of \"-g\" will be used.])
+               CFLAGS="-g"
+       fi
+       if test "x$wi_cv_request_no_y2k" = xyes ; then
+               wi_CFLAGS_NO_Y2K_WARNINGS
+       fi
+       if test "$NOOPTCFLAGS" = "" ; then
+changequote(<<, >>)dnl
+               NOOPTCFLAGS=`echo "$CFLAGS" | sed 's/[-+]O[0-9A-Za-z]*//g;s/-xO[0-9]//g;s/-Wc,-O3//g;s/-IPA//g;s/\ \ */ /g;s/^\ *//;s/\ *$//;'`
+changequote([, ])dnl
+       fi
+       if test "$DEBUGCFLAGS" = "" ; then
+               DEBUGCFLAGS="-g $NOOPTCFLAGS"
+       fi
+       #
+       # Was it ./configure --enable-debug ?
+       #
+       AC_MSG_CHECKING([if this is a debug build])
+       if test "$DEBUGBUILD" = yes ; then
+               AC_MSG_RESULT(yes)
+               CFLAGS="$DEBUGCFLAGS"
+               SFLAG=""
+               STRIPFLAG=""
+               STRIP=":"
+       else
+               AC_MSG_RESULT(no)
+       fi
+       AC_MSG_CHECKING([NOOPTCFLAGS])
+       AC_MSG_RESULT($NOOPTCFLAGS)
+       AC_MSG_CHECKING([DEBUGCFLAGS])
+       AC_MSG_RESULT($DEBUGCFLAGS)
+       AC_MSG_CHECKING([CFLAGS])
+       AC_MSG_RESULT($CFLAGS)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_CFLAGS_LFS64, [AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([wi_OS_VAR])
+wi_CFLAGS
+if test "os_${os}_gcc_${ac_cv_prog_gcc}" = os_hp-ux_gcc_yes ; then
+       case "$CFLAGS" in
+               *__STDC_EXT__*)
+                       ;;
+               *)
+                       # This is required for the extended
+                       # namespace symbols for Large Files.
+                       #
+                       CFLAGS="-D__STDC_EXT__ $CFLAGS"
+                       ;;
+       esac
+fi
+case "$CFLAGS" in
+       *-D_LARGEFILE64_SOURCE*)
+               ;;
+       *)
+               CFLAGS="-D_LARGEFILE64_SOURCE $CFLAGS"
+               ;;
+esac
+AC_MSG_CHECKING([additional CFLAGS for LFS64 support])
+AC_MSG_RESULT($CFLAGS)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_PROTOTYPES, [
+AC_MSG_CHECKING(if the compiler supports function prototypes)
+AC_TRY_COMPILE(,[extern void exit(int status);],[wi_cv_prototypes=yes
+AC_DEFINE(PROTOTYPES)],wi_cv_prototypes=no)
+AC_MSG_RESULT($wi_cv_prototypes)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_INSECURE_CHOWN, [
+AC_MSG_CHECKING(if chown can be used to subvert security)
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+main()
+{
+       int result;
+       char fn[64];
+       FILE *fp;
+       struct stat st;
+
+       setuid(1);      /* if you're root, try set to someone else. */
+       sprintf(fn, "/tmp/fu%06ld", (long) getpid());
+       unlink(fn);
+       fp = fopen(fn, "w");
+       if (fp == NULL)
+               exit(1);        /* assume the worst */
+       fprintf(fp, "%s\n", "hello world");
+       fclose(fp);
+
+       result = chown(fn, 0, 0);
+       if (stat(fn, &st) < 0) {
+               unlink(fn);
+               exit((result == 0) ? 0 : 1);
+       }
+       unlink(fn);
+
+       /* exit(0) if the insecure chown to uid 0 succeeded. */
+       exit((st.st_uid == 0) ? 0 : 1);
+}],[
+       # action if true
+       wi_cv_insecure_chown=yes
+       AC_DEFINE(INSECURE_CHOWN)
+],[
+       # action if false
+       wi_cv_insecure_chown=no
+],[
+       # action if cross-compiling, guess
+       wi_cv_insecure_chown=no
+])
+
+AC_MSG_RESULT($wi_cv_insecure_chown)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_SNPRINTF, [
+if test "$ac_cv_func_snprintf" = "no" ; then
+       AC_CHECK_LIB(snprintf,snprintf)
+       if test "$ac_cv_lib_snprintf_snprintf" = yes ; then
+               unset ac_cv_func_snprintf
+               AC_CHECK_FUNCS(snprintf)
+       fi
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_SNPRINTF_TERMINATES, [
+if test "$ac_cv_func_snprintf" != "no" ; then
+AC_MSG_CHECKING(if snprintf always NUL terminates)
+       if test "$ac_cv_func_snprintf" = "no" ; then
+               AC_CHECK_LIB(snprintf,snprintf)
+       fi
+AC_TRY_RUN([
+       /* program */
+#include <stdio.h>
+#include <string.h>
+main()
+{
+       char s[10];
+       int i, result;
+
+       for (i=0; i<(int)(sizeof(s)/sizeof(char)); i++)
+               s[i] = 'x';
+       result = (int) snprintf(s, sizeof(s), "%s %s!", "hello", "world");
+       if (s[sizeof(s) - 1] == '\0')
+               exit(0);
+       exit(1);
+
+}
+],[
+       # action if true
+       wi_cv_snprintf_terminates=no
+       AC_DEFINE(SNPRINTF_TERMINATES)
+       x="yes";
+],[
+       # action if false
+       wi_cv_snprintf_terminates=yes
+       x="no";
+],[
+       # action if cross compiling
+       wi_cv_snprintf_terminates=no
+       x="unknown";
+])
+AC_MSG_RESULT($x)
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_SNPRINTF, [
+wi_SPRINTF_RETVAL
+dnl Uncache these -- config.cache doesn't cache it right for this case.
+unset ac_cv_func_snprintf
+unset ac_cv_func_vsnprintf
+
+AC_CHECK_FUNCS(snprintf vsnprintf)
+wi_SNPRINTF_TERMINATES
+
+AC_CHECK_HEADERS(snprintf.h)
+wi_LIB_SNPRINTF
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_HEADER_HPSECURITY_H, [
+AC_MSG_CHECKING(for hpsecurity.h)
+wi_cv_header_hpsecurity_h=no
+if test -f /usr/include/hpsecurity.h ; then
+       wi_cv_header_hpsecurity_h=yes
+       AC_DEFINE(HAVE_HPSECURITY_H)
+fi
+AC_MSG_RESULT($wi_cv_header_hpsecurity_h)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_HEADER_SYS_SELECT_H, [
+# See if <sys/select.h> is includable after <sys/time.h>
+if test "$ac_cv_header_sys_time_h" = no ; then
+AC_CHECK_HEADERS(sys/time.h sys/select.h)
+else
+AC_CHECK_HEADERS(sys/select.h)
+fi
+if test "$ac_cv_header_sys_select_h" = yes ; then
+       AC_MSG_CHECKING([if <sys/select.h> is compatible with <sys/time.h>])
+       selecth=yes
+       if test "$ac_cv_header_sys_time_h" = yes ; then
+               AC_TRY_COMPILE([
+#if defined(_AIX) || defined(__aix) || defined(__AIX)
+#      define _ALL_SOURCE 1
+#endif
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>],[
+               fd_set a;
+               struct timeval tmval;
+
+               tmval.tv_sec = 0;],selecth=yes,selecth=no)
+       fi
+       if test "$selecth" = yes ; then
+               AC_DEFINE(CAN_USE_SYS_SELECT_H)
+       fi
+       AC_MSG_RESULT($selecth)
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_44BSD, [
+AC_CHECK_FUNC(strerror,[a=yes],[a=no])
+if test "$a" = no ; then
+       # Not in libc, try lib44bsd.
+       AC_CHECK_LIB(44bsd,strerror)
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_NSL, [
+dnl Note: Check for socket lib first, then nsl.
+
+case "$OS" in
+       hpux1[123456789]*)
+               # HP-UX 11 uses NSL for YP services
+               AC_CHECK_LIB(nsl,getpwent)
+               ;;
+
+       *)
+               AC_CHECK_FUNC(gethostbyname,[a=yes],[a=no])
+               if test "$a" = no ; then
+                       # Not in libc, try libnsl.
+                       AC_CHECK_LIB(nsl,gethostbyname)
+               fi
+               ;;
+esac
+
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_SOCKET, [
+AC_CHECK_FUNC(socket,[a=yes],[a=no])
+if test "$a" = no ; then
+       # Not in libc, try libsocket.
+       AC_CHECK_LIB(socket,socket)
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_RESOLV, [
+# See if we could access two well-known sites without help of any special
+# libraries, like resolv.
+dnl
+AC_MSG_WARN([the following check may take several minutes if networking is not up.  You may want to bring it up now and restart configure, otherwise please be patient.])
+dnl
+AC_MSG_CHECKING([if we need to look for -lresolv])
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+main()
+{
+       struct hostent *hp1, *hp2;
+       int result;
+
+       hp1 = gethostbyname("gatekeeper.dec.com");
+       hp2 = gethostbyname("ftp.ncsa.uiuc.edu");
+       result = ((hp1 != (struct hostent *) 0) && (hp2 != (struct hostent *) 0));
+       exit(! result);
+}],look_for_resolv=no,look_for_resolv=yes,look_for_resolv=yes)
+
+AC_MSG_RESULT($look_for_resolv)
+if test "$look_for_resolv" = yes ; then
+AC_CHECK_LIB(resolv,main)
+else
+       ac_cv_lib_resolv=no
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_TCP_WRAPPERS, [
+AC_MSG_CHECKING([for tcp wrappers library (libwrap)])
+
+AC_TRY_LINK([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+
+/* These are needed if libwrap.a was compiled with
+ * PROCESS_OPTIONS defined.
+ */
+int allow_severity = 1;        /* arbitrary for this test */
+int deny_severity = 2; /* arbitrary for this test */
+
+],[
+       /* function-body */
+       exit((allow_severity == deny_severity) ? 1 : 0);
+],[
+dnl    ...Don't bother defining this symbol...
+dnl    ...Check for tcpd.h instead...
+dnl    AC_DEFINE(HAVE_LIBWRAP)
+dnl
+dnl    ...Don't modify LIBS, instead set WRAPLIB...
+dnl    LIBS="-lwrap  $LIBS"
+dnl
+       WRAPLIB="-lwrap"
+       wi_cv_lib_wrap_hosts_access=yes
+],[
+       WRAPLIB=""
+       wi_cv_lib_wrap_hosts_access=no
+])
+AC_MSG_RESULT($wi_cv_lib_wrap_hosts_access)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_NET_LIBS, [
+# Mostly for SunOS 4 -- needs to come first because other libs depend on it
+wi_LIB_44BSD
+
+wi_LIB_SOCKET
+
+if test "$SYS" = unixware ; then
+       # So far, only UnixWare needs this.
+       AC_CHECK_LIB(gen,syslog)
+
+       case "$OS" in
+               unixware2*)
+                       if test -f /usr/ucblib/libucb.a ; then
+                               LDFLAGS="$LDFLAGS -L/usr/ucblib"
+                               LIBS="$LIBS -lucb"
+                       fi
+                       if test -f /usr/include/unistd.h ; then
+                               ac_cv_header_unistd_h=yes
+                       fi
+
+                       # UnixWare 2 needs both lsocket and lnsl, and configure
+                       # script won't detect this condition properly because 
+                       # the libraries are interdependent.
+                       #
+                       LIBS="$LIBS -lsocket -lnsl"
+
+                       # Now look for socket()
+                       #
+                       # AC_CHECK_FUNC(socket,[a=yes],[a=no])
+                       #
+                       AC_CHECK_FUNC(socket,[a=yes],[a=no])
+                       ;;
+               *)
+                       ;;
+       esac
+fi
+
+dnl AC_CHECK_LIB(inet,main)
+
+wi_LIB_NSL
+wi_LIB_RESOLV
+
+if test "$SYS" = dynixptx ; then
+       LIBS="$LIBS -lsocket -lnsl"
+fi
+
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_DEFINE_UNAME, [
+# Get first 127 chars of all uname information.  Some folks have
+# way too much stuff there, so grab only the first 127.
+unam=`uname -a 2>/dev/null | cut -c1-127`
+if test "$unam" != "" ; then
+       AC_DEFINE_UNQUOTED(UNAME, "$unam")
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_FUNC_SIGSETJMP, [
+AC_MSG_CHECKING([for sigsetjmp and siglongjmp])
+
+AC_TRY_LINK([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <signal.h>
+#include <setjmp.h>
+],[
+       /* function-body */
+       sigjmp_buf sjb;
+
+       if (sigsetjmp(sjb, 1) != 0)
+               siglongjmp(sjb, 1);     /* bogus code, of course. */
+       exit(0);
+],[
+       AC_DEFINE(HAVE_SIGSETJMP)
+       wi_cv_func_sigsetjmp=yes
+],[
+       wi_cv_func_sigsetjmp=no
+])
+AC_MSG_RESULT($wi_cv_func_sigsetjmp)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_UTMP_UT_NAME, [
+AC_MSG_CHECKING([for ut_name field in struct utmp])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <utmp.h>
+],[
+struct utmp u;
+
+u.ut_name[0] = '\0';
+exit(((int) &u.ut_name) & 0xff);       /* bogus code, of course. */
+],[
+       wi_cv_utmp_ut_name=yes
+       AC_DEFINE(HAVE_UTMP_UT_NAME)
+],[
+       wi_cv_utmp_ut_name=no
+])
+AC_MSG_RESULT($wi_cv_utmp_ut_name)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_UTMPX_UT_SYSLEN, [
+AC_MSG_CHECKING([for ut_syslen field in struct utmpx])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <utmpx.h>
+],[
+struct utmpx u;
+
+u.ut_syslen = 0;
+exit(((int) &u.ut_syslen) & 0xff);     /* bogus code, of course. */
+],[
+       wi_cv_utmpx_ut_syslen=yes
+       AC_DEFINE(HAVE_UTMPX_UT_SYSLEN)
+],[
+       wi_cv_utmpx_ut_syslen=no
+])
+AC_MSG_RESULT($wi_cv_utmpx_ut_syslen)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_UTMP_UT_USER, [
+AC_MSG_CHECKING([for ut_user field in struct utmp])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <utmp.h>
+],[
+struct utmp u;
+
+u.ut_user[0] = '\0';
+exit(((int) &u.ut_user) & 0xff);       /* bogus code, of course. */
+],[
+       wi_cv_utmp_ut_user=yes
+       AC_DEFINE(HAVE_UTMP_UT_USER)
+],[
+       wi_cv_utmp_ut_user=no
+])
+AC_MSG_RESULT($wi_cv_utmp_ut_user)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_UTMP_UT_PID, [
+AC_MSG_CHECKING([for ut_pid field in struct utmp])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <utmp.h>
+],[
+struct utmp u;
+
+u.ut_pid = 1;
+exit(((int) &u.ut_pid) & 0xff);        /* bogus code, of course. */
+],[
+       wi_cv_utmp_ut_pid=yes
+       AC_DEFINE(HAVE_UTMP_UT_PID)
+],[
+       wi_cv_utmp_ut_pid=no
+])
+AC_MSG_RESULT($wi_cv_utmp_ut_pid)
+])
+
+dnl
+dnl
+dnl
+AC_DEFUN(wi_UTMP_UT_TIME, [
+AC_MSG_CHECKING([for ut_time field in struct utmp])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <utmp.h>
+],[
+struct utmp u;
+
+u.ut_time = 1;
+exit(((int) &u.ut_time) & 0xff);       /* bogus code, of course. */
+],[
+       wi_cv_utmp_ut_time=yes
+       AC_DEFINE(HAVE_UTMP_UT_TIME)
+],[
+       wi_cv_utmp_ut_time=no
+])
+AC_MSG_RESULT($wi_cv_utmp_ut_time)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_UTMP_UT_HOST, [
+AC_MSG_CHECKING([for ut_host field in struct utmp])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <utmp.h>
+],[
+struct utmp u;
+
+u.ut_host[0] = '\0';
+exit(((int) &u.ut_host) & 0xff);       /* bogus code, of course. */
+],[
+       wi_cv_utmp_ut_host=yes
+       AC_DEFINE(HAVE_UTMP_UT_HOST)
+],[
+       wi_cv_utmp_ut_host=no
+])
+AC_MSG_RESULT($wi_cv_utmp_ut_host)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_STRUCT_STAT64, [
+AC_MSG_CHECKING([for struct stat64])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+],[
+struct stat64 st;
+
+st.st_size = 0;
+exit(((int) &st.st_size) & 0xff);      /* bogus code, of course. */
+],[
+       wi_cv_struct_stat64=yes
+       AC_DEFINE(HAVE_STRUCT_STAT64)
+],[
+       wi_cv_struct_stat64=no
+])
+AC_MSG_RESULT($wi_cv_struct_stat64)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_STRUCT_CMSGHDR, [
+AC_MSG_CHECKING([for struct cmsghdr])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+],[
+struct cmsghdr cm;
+
+cm.cmsg_len = 0;
+cm.cmsg_level = 0;
+cm.cmsg_type = 0;
+exit(((int) &cm.cmsg_type) & 0xff);    /* bogus code, of course. */
+],[
+       wi_cv_struct_cmsghdr=yes
+       AC_DEFINE(HAVE_STRUCT_CMSGDHR)
+],[
+       wi_cv_struct_cmsghdr=no
+])
+AC_MSG_RESULT($wi_cv_struct_cmsghdr)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_MSGHDR_CONTROL, [
+AC_MSG_CHECKING([for msg_control field in struct msghdr])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+],[
+struct msghdr m;
+
+m.msg_control = &m;
+m.msg_controllen = sizeof(m);
+exit(((int) &m.msg_control) & 0xff);   /* bogus code, of course. */
+],[
+       wi_cv_msghdr_control=yes
+       AC_DEFINE(HAVE_MSGHDR_CONTROL)
+],[
+       wi_cv_msghdr_control=no
+])
+AC_MSG_RESULT($wi_cv_msghdr_control)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_MSGHDR_ACCRIGHTS, [
+AC_MSG_CHECKING([for msg_accrights field in struct msghdr])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+],[
+struct msghdr m;
+
+m.msg_accrights = &m;
+m.msg_accrightslen = sizeof(m);
+exit(((int) &m.msg_accrights) & 0xff); /* bogus code, of course. */
+],[
+       wi_cv_msghdr_accrights=yes
+       AC_DEFINE(HAVE_MSGHDR_ACCRIGHTS)
+],[
+       wi_cv_msghdr_accrights=no
+])
+AC_MSG_RESULT($wi_cv_msghdr_accrights)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_PR_PASSWD_FG_OLDCRYPT, [
+AC_MSG_CHECKING([for fg_oldcrypt field in struct pr_passwd])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+
+#if defined(HAVE_USERPW_H) && defined(HAVE_GETUSERPW)  /* AIX */
+#      include <userpw.h>
+#elif defined(HAVE_PWDADJ_H) && defined(HAVE_GETPWANAM)        /* SunOS */
+#      include <sys/label.h>
+#      ifdef HAVE_SYS_AUDIT_H
+#              include <sys/audit.h>
+#      endif
+#      include <pwdadj.h>
+#elif defined(HAVE_GETESPWNAM) /* Digital UNIX 4 */
+#      ifdef HAVE_SYS_SECDEFINES_H
+#              include <sys/secdefines.h>
+#      endif
+#      ifdef HAVE_SYS_SECURITY_H
+#              include <sys/security.h>
+#      endif
+#      ifdef HAVE_SYS_AUDIT_H
+#              include <sys/audit.h>
+#      endif
+#      ifdef HAVE_KRB_H
+#              include <krb.h>
+#      endif
+#      ifdef HAVE_PROT_H
+#              include <prot.h>
+#      endif
+#elif defined(HAVE_GETPRPWNAM) /* SCO Open Server V, Digital UNIX 3, HP-UX 10 */
+#      ifdef HAVE_SYS_SECDEFINES_H
+#              include <sys/secdefines.h>
+#      endif
+#      ifdef HAVE_SYS_SECURITY_H
+#              include <sys/security.h>
+#      endif
+#      ifdef HAVE_SYS_AUDIT_H
+#              include <sys/audit.h>
+#      endif
+#      ifdef HAVE_HPSECURITY_H
+#              include <hpsecurity.h>
+#      endif
+#      ifdef HAVE_KRB_H
+#              include <krb.h>
+#      endif
+#      ifdef HAVE_PROT_H
+#              include <prot.h>
+#      endif
+#endif
+],[
+       struct pr_passwd xu;
+       memset(&xu, 0, sizeof(xu));
+       if (xu.uflg.fg_oldcrypt != 0)
+               xu.uflg.fg_oldcrypt++;  /* bogus code, of course */
+       exit(0);
+],[
+       wi_cv_pr_passwd_fg_oldcrypt=yes
+       AC_DEFINE(HAVE_PR_PASSWD_FG_OLDCRYPT)
+],[
+       wi_cv_pr_passwd_fg_oldcrypt=no
+])
+AC_MSG_RESULT($wi_cv_pr_passwd_fg_oldcrypt)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_SOCKADDR_UN_SUN_LEN, [
+AC_MSG_CHECKING([for sun_len field in struct sockaddr_un])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+],[
+struct sockaddr_un uaddr;
+
+uaddr.sun_len = strlen("/tmp/test.sock");
+exit(((int) uaddr.sun_len);    /* bogus code, of course. */
+],[
+       wi_cv_sockaddr_un_sun_len=yes
+       AC_DEFINE(HAVE_SOCKADDR_UN_SUN_LEN)
+],[
+       wi_cv_sockaddr_un_sun_len=no
+])
+AC_MSG_RESULT($wi_cv_sockaddr_un_sun_len)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_STATFS_F_BAVAIL, [
+AC_MSG_CHECKING([for f_bavail field in struct statfs])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_STATFS_H
+#      include <sys/statfs.h>
+#elif defined(HAVE_SYS_VFS_H)
+#      include <sys/vfs.h>
+#endif
+],[
+struct statfs st;
+
+st.f_bavail = 1;
+exit((int) st.f_bavail);       /* bogus code, of course. */
+],[
+       wi_cv_statfs_f_bavail=yes
+       AC_DEFINE(HAVE_STATFS_F_BAVAIL)
+],[
+       wi_cv_statfs_f_bavail=no
+])
+AC_MSG_RESULT($wi_cv_statfs_f_bavail)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_SPRINTF_RETVAL, [
+AC_MSG_CHECKING([what sprintf() returns])
+AC_TRY_RUN([
+       /* program */
+#include <stdio.h>
+#include <string.h>
+main()
+{
+       int result;
+       char s[8];
+
+       result = (int) sprintf(s, "%d", 22);
+       if (result == 2)
+               exit(0);
+       exit(1);
+
+}
+],[
+       # action if true
+       wi_cv_sprintf_returns_ptr=no
+       x="length of data written";
+],[
+       # action if false
+       wi_cv_sprintf_returns_ptr=yes
+       AC_DEFINE(SPRINTF_RETURNS_PTR)
+       x="pointer to data";
+],[
+       # action if cross compiling
+       wi_cv_sprintf_returns_ptr=no
+       x="unknown";
+])
+AC_MSG_RESULT($x)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_CRYPT, [
+AC_MSG_CHECKING([which library has usable crypt() function])
+ac_save_LIBS="$LIBS"
+crypt_lib=NONE
+
+for lib in "c" "crypt" "descrypt" "des"
+do
+
+if test "$lib" = "c" ; then
+       LIBS="$ac_save_LIBS"
+else
+       LIBS="$ac_save_LIBS -l${lib}"
+fi
+
+AC_TRY_RUN([
+       /* program */
+#include <stdio.h>
+#include <string.h>
+
+extern char *crypt(const char *key, const char *salt);
+
+main()
+{
+       char cleartext[256];
+       char *cp;
+
+       memset(cleartext, 0, sizeof(cleartext));
+       strcpy(cleartext, "password");
+
+       cp = crypt(cleartext, "xx");
+       if ((cp != NULL) && (strcmp(cp, "xxj31ZMTZzkVA") == 0)) {
+               /* printf("PASS\n"); */
+               exit(0);
+       }
+       /* printf("FAIL\n"); */
+       exit(1);
+}
+],[
+       # action if true
+       crypt_lib="$lib"
+],[
+       # action if false
+       :
+],[
+       # action if cross compiling
+       :
+])
+
+
+if test "$crypt_lib" != NONE ; then
+       break
+fi
+
+done
+
+
+LIBS="$ac_save_LIBS"
+
+if test "$crypt_lib" = NONE ; then
+       crypt_lib=c
+       AC_MSG_RESULT([none?])
+else
+       AC_MSG_RESULT([lib${crypt_lib}])
+fi
+if test "$crypt_lib" != c ; then
+       AC_CHECK_LIB(${lib},crypt)
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_TEST, [
+changequote(<^, ^>)dnl
+changequote([, ])dnl
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi__RES_DEFDNAME, [
+AC_MSG_CHECKING([for useable _res global variable])
+AC_TRY_LINK([
+       /* includes */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#ifdef HAVE_ARPA_NAMESER_H
+#      include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#      include <resolv.h>
+#endif
+],[
+       /* function-body */
+       int len;
+
+       res_init();
+       len = (int) strlen(_res.defdname);
+],[
+       wi_cv__res_defdname=yes
+       AC_DEFINE(HAVE__RES_DEFDNAME)
+],[
+       wi_cv__res_defdname=no
+])
+AC_MSG_RESULT($wi_cv__res_defdname)
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_TYPE_SIG_ATOMIC_T, [
+AC_MSG_CHECKING([for sig_atomic_t])
+AC_TRY_LINK([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <signal.h>    /* MG: for IRIX */
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+],[
+       /* function-body */
+       sig_atomic_t sample;
+
+       sample = (sig_atomic_t) getpid();       /* bogus code, of course */
+       exit((sample > 0) ? 0 : 1);
+],[
+       ac_cv_type_sig_atomic_t=yes
+],[
+       ac_cv_type_sig_atomic_t=no
+])
+AC_MSG_RESULT($ac_cv_type_sig_atomic_t)
+if test $ac_cv_type_sig_atomic_t = no ; then
+       AC_DEFINE(sig_atomic_t, int)
+fi
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_READLINE, [
+AC_MSG_CHECKING([for GNU Readline library, version 2.0 or newer])
+
+wi_cv_lib_readline=no
+wi_cv_lib_readline_result=no
+ac_save_LIBS="$LIBS"
+# Note: $LIBCURSES is permitted to be empty.
+for LIBREADLINE in "-lreadline" "-lreadline $LIBCURSES" "-lreadline -ltermcap" "-lreadline -lncurses" "-lreadline -lcurses"
+do
+       LIBS="$ac_save_LIBS $LIBREADLINE"
+       AC_TRY_RUN([
+       /* program */
+#include <stdio.h>
+#include <stdlib.h>
+main(int argc, char **argv)
+{
+       /* Note:  don't actually call readline, since it may block;
+        * We just want to see if it (dynamic) linked in okay.
+        */
+       if (argc == 0)  /* never true */
+               readline(0);
+       exit(0);
+}
+],[
+       # action if true
+       wi_cv_lib_readline=yes
+],[
+       # action if false
+       wi_cv_lib_readline=no
+],[
+       # action if cross compiling
+       wi_cv_lib_readline=no
+])
+
+       if test "$wi_cv_lib_readline" = yes ; then break ; fi
+done
+
+# Now try it again, to be sure it is recent enough.
+# rl_function_of_keyseq appeared in version 2.0
+#
+dnl AC_CHECK_FUNC(rl_function_of_keyseq, [wi_cv_lib_readline=yes],[
+dnl    wi_cv_lib_readline=no;wi_cv_lib_readline_result="no (it is present but too old to use)"
+dnl ])
+       AC_TRY_LINK([
+               /* includes */
+       ],[
+               /* function-body */
+               readline(0);
+               rl_function_of_keyseq(0);
+       ],[
+               wi_cv_lib_readline=yes
+       ],[
+               wi_cv_lib_readline=no
+               wi_cv_lib_readline_result="no (it is present but too old to use)"
+       ])
+
+if test "$wi_cv_lib_readline" = no ; then
+       LIBREADLINE=""
+       # restore LIBS
+       LIBS="$ac_save_LIBS"
+else
+       /bin/rm -f readline.ver
+       touch readline.ver
+
+       AC_TRY_RUN([
+       /* program */
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+extern char *rl_library_version;
+
+main()
+{
+       FILE *fp;
+       double d;
+
+       sscanf(rl_library_version, "%lf", &d);
+       fp = fopen("readline.ver", "w");
+       if (fp == NULL) exit(1);
+       if (fprintf(fp, "%s\n", rl_library_version) < 0) exit(1);
+       if (fprintf(fp, "%03d\n", (int) (d * 100.0)) < 0) exit(1);
+       if (fclose(fp) < 0) exit(1);
+       exit(0);
+}
+       ],[
+               # action if true
+               rl_library_version=`sed -n 1,1p readline.ver 2>/dev/null`
+               rlver=`sed -n 2,2p readline.ver 2>/dev/null`
+               /bin/rm -f readline.ver
+       ],[
+               # action if false
+               rl_library_version=''
+               rlver=''
+               /bin/rm -f readline.ver
+       ],[
+               # action if cross compiling
+               rl_library_version=''
+               rlver=''
+               /bin/rm -f readline.ver
+       ])
+
+       case "$rlver" in
+               ???)
+                       wi_cv_lib_readline_result="yes, installed version is $rl_library_version"
+                       ;;
+               *)
+                       # Test using current LIBS.
+                       AC_TRY_LINK([
+                               /* includes */
+                               extern int rl_completion_append_character;
+                       ],[
+                               /* function-body */
+                               readline(0);
+                               rl_completion_append_character = 0;
+                       ],[
+                               rlver="210"
+                       ],[
+                               rlver="200"
+                       ])
+
+                       if test "$rlver" = "210" ; then
+                               wi_cv_lib_readline_result="yes, version 2.1 or higher"
+                       else
+                               wi_cv_lib_readline_result="yes, version 2.0"
+                       fi
+                       ;;
+       esac
+
+       wi_cv_lib_readline=yes
+       # restore LIBS
+       LIBS="$ac_save_LIBS"
+fi
+AC_MSG_RESULT($wi_cv_lib_readline_result)
+AC_SUBST(LIBREADLINE)
+
+if test "$wi_cv_lib_readline" = yes ; then
+       # Now verify that all the headers are installed.
+       #
+       AC_REQUIRE_CPP()
+       unset ac_cv_header_readline_chardefs_h
+       unset ac_cv_header_readline_history_h
+       unset ac_cv_header_readline_keymaps_h
+       unset ac_cv_header_readline_readline_h
+       unset ac_cv_header_readline_tilde_h
+       AC_CHECK_HEADERS([readline/chardefs.h readline/history.h readline/keymaps.h readline/readline.h readline/tilde.h])
+
+       for xxwi in \
+               "$ac_cv_header_readline_chardefs_h" \
+               "$ac_cv_header_readline_history_h" \
+               "$ac_cv_header_readline_keymaps_h" \
+               "$ac_cv_header_readline_readline_h" \
+               "$ac_cv_header_readline_tilde_h" 
+       do
+               if test "$xxwi" = no ; then
+                       break
+               fi
+       done
+
+       if test "$xxwi" = no ; then
+               AC_MSG_WARN([GNU Readline headers are not installed or could not be found -- GNU Readline will not be used.])
+               wi_cv_lib_readline=no
+               wi_cv_lib_readline_result="no (headers not installed)"
+       else
+               AC_DEFINE_UNQUOTED(HAVE_LIBREADLINE, $rlver)
+       fi
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_USE_LONG_LONG, [
+AC_MSG_CHECKING([for 64-bit integral type: long long])
+LONGEST_INT="long"
+AC_TRY_RUN([
+       /* program */
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+long long hugeNumvar = 1;
+
+main()
+{
+       long long hugeNumtoo = 2;
+
+       if (hugeNumtoo > hugeNumvar)
+               hugeNumvar++;
+       if (sizeof(hugeNumvar) < 8)
+               exit(1);
+       exit(0);
+}
+
+],[
+       # action if true
+       wi_cv_type_long_long=yes
+       LONGEST_INT="long long"
+],[
+       # action if false
+       wi_cv_type_long_long=no
+],[
+       # action if cross compiling
+       wi_cv_type_long_long=no
+])
+AC_MSG_RESULT($wi_cv_type_long_long)
+
+if test "$wi_cv_type_long_long" = yes ; then
+       
+AC_MSG_CHECKING([how to print a 64-bit integral type])
+wi_cv_printf_long_long=fail
+
+AC_TRY_RUN([
+       /* program */
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+main()
+{
+       char s[80];
+       long long hugeNum;
+
+       hugeNum = (long long) 1000000000;
+       hugeNum = hugeNum * (long long) 99;
+       hugeNum = hugeNum + (long long) 1;
+
+       (void) sprintf(s, "%lld", hugeNum);
+       exit((strcmp(s, "99000000001") == 0) ? 0 : 1);
+}
+],[
+       # action if true
+       wi_cv_printf_long_long="%lld"
+],[
+       # action if false
+       :
+],[
+       # action if cross compiling
+       :
+])
+
+
+if test "$wi_cv_printf_long_long" = fail ; then
+
+AC_TRY_RUN([
+       /* program */
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+main()
+{
+       char s[80];
+       long long hugeNum;
+
+       hugeNum = (long long) 1000000000;
+       hugeNum = hugeNum * (long long) 99;
+       hugeNum = hugeNum + (long long) 1;
+
+       (void) sprintf(s, "%qd", hugeNum);
+       exit((strcmp(s, "99000000001") == 0) ? 0 : 1);
+}
+],[
+       # action if true
+       wi_cv_printf_long_long="%qd"
+],[
+       # action if false
+       :
+],[
+       # action if cross compiling
+       :
+])
+fi
+
+if test "$wi_cv_printf_long_long" = fail ; then
+       wi_cv_printf_long_long_msg_result='cannot print'
+else
+       wi_cv_printf_long_long_msg_result="$wi_cv_printf_long_long"
+fi
+
+AC_MSG_RESULT($wi_cv_printf_long_long_msg_result)
+
+       
+AC_MSG_CHECKING([how to scan a 64-bit integral type])
+wi_cv_scanf_long_long=fail
+
+AC_TRY_RUN([
+       /* program */
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+main()
+{
+       long long hugeNum, justAsHugeNum;
+
+       hugeNum = (long long) 1000000000;
+       hugeNum = hugeNum * (long long) 99;
+       hugeNum = hugeNum + (long long) 1;
+
+       justAsHugeNum = (long long) 0;
+       --justAsHugeNum;
+       sscanf("99000000001", "%lld", &justAsHugeNum);
+       if (memcmp(&hugeNum, &justAsHugeNum, sizeof(hugeNum)) == 0)
+               exit(0);
+       exit(1);
+}
+],[
+       # action if true
+       wi_cv_scanf_long_long="%lld"
+],[
+       # action if false
+       :
+],[
+       # action if cross compiling
+       :
+])
+
+
+if test "$wi_cv_scanf_long_long" = fail ; then
+
+AC_TRY_RUN([
+       /* program */
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+main()
+{
+       long long hugeNum, justAsHugeNum;
+
+       hugeNum = (long long) 1000000000;
+       hugeNum = hugeNum * (long long) 99;
+       hugeNum = hugeNum + (long long) 1;
+
+       justAsHugeNum = (long long) 0;
+       --justAsHugeNum;
+       sscanf("99000000001", "%qd", &justAsHugeNum);
+       if (memcmp(&hugeNum, &justAsHugeNum, sizeof(hugeNum)) == 0)
+               exit(0);
+       exit(1);
+}
+],[
+       # action if true
+       wi_cv_scanf_long_long="%qd"
+],[
+       # action if false
+       :
+],[
+       # action if cross compiling
+       :
+])
+fi
+
+if test "$wi_cv_scanf_long_long" = fail ; then
+       wi_cv_scanf_long_long_msg_result='cannot scan'
+else
+       wi_cv_scanf_long_long_msg_result="$wi_cv_scanf_long_long"
+fi
+
+AC_MSG_RESULT($wi_cv_scanf_long_long_msg_result)
+
+fi
+
+AC_MSG_CHECKING([if everything was available to use the 64-bit integral type])
+
+if test "$wi_cv_type_long_long" = no ; then
+       wi_cv_use_long_long_msg_result="no (long long type not available)"
+       wi_cv_use_long_long="no"
+       wi_cv_scanf_long_long="fail"
+       wi_cv_prihtf_long_long="fail"
+       LONGEST_INT="long"
+elif test "$wi_cv_printf_long_long" = fail ; then
+       wi_cv_use_long_long_msg_result="no (libc printf() does not support them)"
+       wi_cv_use_long_long="no"
+       wi_cv_scanf_long_long="fail"
+       wi_cv_prihtf_long_long="fail"
+       LONGEST_INT="long"
+elif test "$wi_cv_scanf_long_long" = fail ; then
+       wi_cv_use_long_long_msg_result="no (libc scanf() does not support them)"
+       wi_cv_use_long_long="no"
+       wi_cv_scanf_long_long="fail"
+       wi_cv_prihtf_long_long="fail"
+       LONGEST_INT="long"
+else
+       AC_DEFINE(HAVE_LONG_LONG)
+       if test "$wi_cv_printf_long_long$wi_cv_scanf_long_long" = "%lld%qd" ; then
+               # FreeBSD 3.2 has %lld and %qd, but we want to
+               # run on 3.1 and 3.0.
+               #
+               wi_cv_printf_long_long="%qd"
+       fi
+       AC_DEFINE_UNQUOTED(PRINTF_LONG_LONG, "$wi_cv_printf_long_long")
+       AC_DEFINE_UNQUOTED(SCANF_LONG_LONG , "$wi_cv_scanf_long_long")
+       if test "$wi_cv_printf_long_long" = "%qd" ; then
+               AC_DEFINE(PRINTF_LONG_LONG_QD)
+       else
+               AC_DEFINE(PRINTF_LONG_LONG_LLD)
+       fi
+       if test "$wi_cv_scanf_long_long" = "%qd" ; then
+               AC_DEFINE(SCANF_LONG_LONG_QD)
+       else
+               AC_DEFINE(SCANF_LONG_LONG_LLD)
+       fi
+       wi_cv_use_long_long="yes"
+       wi_cv_use_long_long_msg_result="yes"
+fi
+AC_MSG_RESULT($wi_cv_use_long_long_msg_result)
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_CREATE_TAR_FILES, [
+AC_MSG_CHECKING([how to create TAR files])
+changequote(<<, >>)dnl
+TAR=/usr/bin/tar
+if [ ! -f /usr/bin/tar ] && [ -f /bin/tar ] ; then
+       TAR=/bin/tar
+fi
+x=""
+if [ -x /usr/bin/what ] ; then
+       x=`/usr/bin/what "$TAR" 2>&1 | sed -n 's/.*pax.*/pax/g;/pax/p'`
+elif [ -x /bin/what ] ; then
+       x=`/bin/what "$TAR" 2>&1 | sed -n 's/.*pax.*/pax/g;/pax/p'`
+fi
+if [ "x$x" != "xpax" ] ; then
+       # The junk above is because Mac OS X Server's tar freaks out
+       # and does not exit if you do "tar --help".
+       #
+       x=`$TAR --help 2>&1 | sed -n 's/.*owner=NAME.*/owner=NAME/g;/owner=NAME/p'`
+fi
+case "$x" in
+       *owner=NAME*)
+               TARFLAGS="-c --owner=root --group=bin --verbose -f"
+               ;;
+       *)
+               TARFLAGS="cvf"
+               x2=`gtar --help 2>&1 | sed -n 's/.*owner=NAME.*/owner=NAME/g;/owner=NAME/p'`
+               case "$x2" in
+                       *owner=NAME*)
+                               TARFLAGS="-c --owner=root --group=bin --verbose -f"
+                               TAR=gtar
+                               ;;
+               esac
+               ;;
+esac
+changequote([, ])dnl
+AC_SUBST(TARFLAGS)
+AC_SUBST(TAR)
+AC_MSG_RESULT([$TAR $TARFLAGS])
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_HEADER_CURSES, [
+AC_MSG_CHECKING([for curses library headers])
+if test "$nc_cv_ncurses" != "no" ; then
+       AC_CHECK_HEADERS(ncurses.h curses.h)
+else
+       AC_CHECK_HEADERS(curses.h)
+fi
+dnl needed for Solaris 7
+if test "$ac_cv_header_curses_h" = no ; then
+       if test -f /usr/include/curses.h ; then
+               AC_DEFINE(HAVE_CURSES_H)
+               ac_cv_header_curses_h=yes
+       fi
+fi
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_LIB_CURSES, [
+wi_HEADER_CURSES
+AC_MSG_CHECKING([for curses library])
+
+wi_cv_lib_curses=no
+wi_cv_lib_curses_result=no
+ac_save_LIBS="$LIBS"
+for LIBCURSES in "-lncurses" "-lcurses" "-lcurses -ltermcap" "-ltermcap -lcurses"
+do
+       if test "x$LIBCURSES-$nc_cv_ncurses" = "x-lncurses-no" ; then
+               # This should never work
+               LIBCURSES="-lkdfjkdjfs"
+       fi
+       LIBS="$ac_save_LIBS $LIBCURSES"
+       AC_TRY_RUN([
+       /* program */
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_NCURSES_H
+#      include <ncurses.h>
+#else
+#      include <curses.h>
+#endif
+
+main(int argc, char **argv)
+{
+       /* Note:  don't actually call curses, since it may block;
+        * We just want to see if it (dynamic) linked in okay.
+        */
+       if (argc == 4)
+               initscr();
+       exit(0);
+}
+],[
+       # action if true
+       wi_cv_lib_curses=yes
+       wi_cv_lib_curses_result="yes"
+],[
+       # action if false
+       wi_cv_lib_curses=no
+],[
+       # action if cross compiling
+       wi_cv_lib_curses=no
+])
+
+       if test "$wi_cv_lib_curses" = yes ; then break ; fi
+done
+
+# restore LIBS
+LIBS="$ac_save_LIBS"
+
+if test "$wi_cv_lib_curses_result" != "no" ; then
+       case "$LIBCURSES" in
+               "-lncurses")
+                       AC_DEFINE(HAVE_LIBNCURSES)
+                       ;;
+               "-lcurses")
+                       AC_DEFINE(HAVE_LIBCURSES)
+                       ;;
+               "-lcurses -ltermcap")
+                       AC_DEFINE(HAVE_LIBCURSES)
+                       ;;
+               "-ltermcap -lcurses")
+                       AC_DEFINE(HAVE_LIBCURSES)
+                       ;;
+       esac
+else
+       LIBCURSES=''
+fi
+
+AC_SUBST(LIBCURSES)
+AC_MSG_RESULT([$wi_cv_lib_curses_result])
+])
+dnl
+dnl
+dnl
+dnl
+AC_DEFUN(wi_CURSES_FEATURES, [
+if test "$wi_cv_lib_curses" = "yes" ; then
+       # Then $LIBCURSES is a list of curses and support libraries.
+       ac_save_LIBS="$LIBS";
+       LIBS="$LIBS $LIBCURSES";
+
+
+       # maxx or _maxx
+       AC_MSG_CHECKING([whether curses structure has maxx or _maxx field])
+       AC_TRY_COMPILE([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_NCURSES_H
+#      include <ncurses.h>
+#else
+#      include <curses.h>
+#endif
+],[
+               WINDOW *w;
+       
+               w = newwin(10, 10, 1, 1);
+               w->maxx = 0;
+],[
+AC_MSG_RESULT([maxx])
+],[
+AC_DEFINE(HAVE__MAXX)
+AC_MSG_RESULT([_maxx])
+])
+
+       AC_CHECK_FUNCS(__getmaxx __getmaxy __getbegx __getbegy)
+
+       # getbegx
+       AC_MSG_CHECKING([for getbegx() functionality in curses library])
+       AC_TRY_LINK([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_NCURSES_H
+#      include <ncurses.h>
+#else
+#      include <curses.h>
+#endif
+
+],[
+       /* function-body */
+       WINDOW *junk = 0;
+       int mx = 0;
+
+       mx = getbegx(junk);
+       exit(0);
+],[
+       AC_DEFINE(HAVE_GETBEGX)
+       AC_MSG_RESULT([yes])
+],[
+       AC_MSG_RESULT([no])
+])
+
+
+       # getmaxx
+       AC_MSG_CHECKING([for getmaxx() functionality in curses library])
+       AC_TRY_LINK([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_NCURSES_H
+#      include <ncurses.h>
+#else
+#      include <curses.h>
+#endif
+],[
+       /* function-body */
+       WINDOW *junk = 0;
+       int mx = 0;
+
+       mx = getmaxx(junk);
+       exit(0);
+],[
+       AC_DEFINE(HAVE_GETMAXX)
+       AC_MSG_RESULT([yes])
+],[
+       AC_MSG_RESULT([no])
+])
+
+       # getmaxyx
+       AC_MSG_CHECKING([for getmaxyx() functionality in curses library])
+       AC_TRY_LINK([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_NCURSES_H
+#      include <ncurses.h>
+#else
+#      include <curses.h>
+#endif
+],[
+       /* function-body */
+       WINDOW *junk = 0;
+       int mx = 0, my = 0;
+
+       getmaxyx(junk, my, mx);
+       exit(my < 0 ? my : 0);
+],[
+       AC_DEFINE(HAVE_GETMAXYX)
+       AC_MSG_RESULT([yes])
+],[
+       AC_MSG_RESULT([no])
+])
+
+       # touchwin
+       AC_MSG_CHECKING([for touchwin() functionality in curses library])
+       AC_TRY_LINK([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_NCURSES_H
+#      include <ncurses.h>
+#else
+#      include <curses.h>
+#endif
+],[
+       /* function-body */
+       WINDOW *junk = 0;
+       touchwin(junk);
+       exit(0);
+],[
+       AC_DEFINE(HAVE_TOUCHWIN)
+       AC_MSG_RESULT([yes])
+],[
+       AC_MSG_RESULT([no])
+])
+
+       # beep
+       AC_MSG_CHECKING([for beep() functionality in curses library])
+       AC_TRY_LINK([
+       /* includes */
+#ifdef HAVE_UNISTD_H
+#      include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_NCURSES_H
+#      include <ncurses.h>
+#else
+#      include <curses.h>
+#endif
+],[
+       /* function-body */
+       beep();
+       exit(getpid() & 1);
+],[
+       AC_DEFINE(HAVE_BEEP)
+       AC_MSG_RESULT([yes])
+],[
+       AC_MSG_RESULT([no])
+])
+
+       AC_CHECK_FUNCS(keypad nodelay curs_set doupdate wnoutrefresh)
+
+       LIBS="$ac_save_LIBS";
+fi
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_SHADOW_FUNCS, [
+AC_CHECK_FUNCS(md5_crypt md5crypt bcrypt getspnam)
+
+# UnixWare 7
+if test "$ac_cv_func_getspnam" = no ; then
+       unset ac_cv_func_getspnam
+       AC_CHECK_LIB(gen,getspnam)
+       if test "$ac_cv_lib_gen_getspnam" = yes ; then
+               AC_CHECK_FUNCS(getspnam)
+       fi
+fi
+
+# AIX
+#
+case "$SYS" in
+       "aix"|"")
+               AC_CHECK_FUNCS(getuserpw)
+               ;;
+       *)
+               ;;
+esac
+
+# C2: SCO Open Server 5; Digital UNIX
+AC_CHECK_FUNCS(set_auth_parameters bigcrypt)
+
+# C2: Digital UNIX 3.2, 4.0; SCO Open Server 5; HP-UX 11
+AC_CHECK_FUNCS(getprpwnam)
+
+# Digital UNIX 4.0
+AC_CHECK_FUNCS(getespwnam get_num_crypts get_crypt_name)
+
+# Digital Unix 4.0
+AC_CHECK_FUNCS(dispcrypt)
+
+# SunOS
+AC_CHECK_FUNCS(getpwanam)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_SHADOW_HEADERS, [
+AC_CHECK_HEADERS(shadow.h crypt.h)
+
+# AIX
+AC_CHECK_HEADERS(userpw.h)
+
+# SunOS
+AC_CHECK_HEADERS(pwdadj.h)
+
+# HP-UX
+#
+# Bug in header on these version 10 which cause is it not
+# to get detected.
+#
+wi_HEADER_HPSECURITY_H
+
+# SCO Open Server, Digital UNIX
+AC_CHECK_HEADERS(sys/security.h sys/audit.h krb.h prot.h)
+
+# Digital UNIX
+AC_CHECK_HEADERS(sys/secdefines.h)
+
+# Digital UNIX
+wi_PR_PASSWD_FG_OLDCRYPT
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_SHADOW_LIBS, [
+check_for_libcrypt=yes
+
+# AIX security library is libs.a
+AC_CHECK_LIB(s,getuserpw)
+if test "$ac_cv_lib_s" = yes ; then
+       check_for_libcrypt=no
+elif test "$ac_cv_lib_s_getuserpw" = yes ; then
+       check_for_libcrypt=no
+fi
+
+# SCO OpenServer 5 stuff for shadow password
+AC_CHECK_LIB(x,nap)
+AC_CHECK_LIB(prot,getprpwnam)
+
+# Digital UNIX
+AC_CHECK_LIB(security,endprpwent)
+
+# HP-UX
+AC_CHECK_LIB(sec,getprpwnam)
+
+if test "$ac_cv_lib_sec_getprpwnam" = no ; then
+       # DYNIX/ptx
+       AC_CHECK_LIB(sec,getspnam)
+fi
+
+if test "$check_for_libcrypt" = yes ; then
+       wi_LIB_CRYPT
+fi
+AC_CHECK_FUNCS(crypt)
+])
+dnl
+dnl
+dnl
+AC_DEFUN(wi_OS_VAR, [
+changequote(!@, @!)dnl
+if [ -x "$HOME/bin/OS" ] ; then
+       HOME_OS=`$HOME/bin/OS`
+       HOME_OS="$HOME/$HOME_OS"
+fi
+host=`uname -n 2>/dev/null | tr '[A-Z]' '[a-z]'`
+os=`uname -s 2>/dev/null | tr '[A-Z]' '[a-z]'`
+dnl work around inability to use $1
+os_v=`uname -v 2>/dev/null | sed 's/^[^0-9.]*//;s/[^0-9.]*$//;s/pre.*//;s/test.*//' | awk '-F[-/: ]' '{n = 1; print $n; }'`
+os_r=`uname -r 2>/dev/null | sed 's/^[^0-9.]*//;s/[^0-9.]*$//;s/pre.*//;s/test.*//' | awk '-F[-/: ]' '{n = 1; print $n; }'`
+os_r1=`echo "${os_r}" | cut -c1`
+arch=`uname -m 2>/dev/null | tr '[A-Z]' '[a-z]'`
+archp=`uname -p 2>/dev/null | tr '[A-Z]' '[a-z]'`
+OS=''
+SYS=''
+NDEFS=''
+
+# Special case a few systems where if your CFLAGS appear
+# to want to generate for 32 bit, use that mode rather
+# than 64 bit.
+#
+case "$os,$CFLAGS" in
+       irix64,*-n32*)
+               os=irix
+               # then go to regular "irix" instead of "irix64" below.
+               ;;
+esac
+
+case "$os" in
+       osf1)
+               case "$os_r" in
+                       3*|4*)
+                               OS="digitalunix${os_r}-$arch"
+                               SYS=digitalunix
+                               ;;
+                       *)
+                               OS="tru64unix${os_r}-$arch"
+                               SYS=tru64unix
+                               ;;
+               esac
+               NDEFS="$NDEFS -DDIGITAL_UNIX=$os_r1"
+               ;;
+       aix)
+               OS="aix${os_v}.${os_r}"
+               SYS=aix
+               NDEFS="$NDEFS -DAIX=${os_v}"
+               ;;
+       irix)
+               OS="irix${os_r}"
+               SYS=irix
+               NDEFS="$NDEFS -DIRIX=$os_r1"
+               ;;
+       irix64)
+               OS="irix64_${os_r}"
+               SYS=irix64
+               NDEFS="$NDEFS -DIRIX=$os_r1 -DIRIX64=$os_r1"
+               ;;
+       hp-ux)
+               os_r=`echo "${os_r}" | cut -d. -f2-`
+               os_r1=`echo "$os_r" | cut -d. -f1`
+               os_r2=`echo "${os_r}" | cut -d. -f2`
+               os_int=`expr "$os_r1" '*' 100 + "$os_r2"`
+               OS="hpux${os_r}"
+               SYS=hpux
+               NDEFS="$NDEFS -DHPUX=$os_int"
+               ;;
+       freebsd)
+               OS="freebsd${os_r}-$arch"
+               os_r1=`echo "$os_r" | cut -d. -f1`
+               os_r2=`echo "$os_r" | cut -d. -f2`
+               os_r3=`echo "$os_r" | cut -d. -f3`
+               if [ "$os_r3" = "" ] ; then os_r3=0 ; fi
+               os_int=`expr "$os_r1" '*' 100 + "$os_r2" '*' 10 + "$os_r3"`
+               SYS=freebsd
+               NDEFS="$NDEFS -DFREEBSD=$os_int"
+               ;;
+       netbsd)
+               OS="netbsd${os_r}-$arch"
+               NDEFS="$NDEFS -DNETBSD=$os_r1"
+               SYS=netbsd
+               ;;
+       openbsd)
+               OS="openbsd${os_r}-$arch"
+               SYS=openbsd
+               NDEFS="$NDEFS -DOPENBSD=$os_r1"
+               ;;
+       sco*)
+               OS=scosv
+               SYS=sco
+               NDEFS="$NDEFS -DSCO=$os_r1"
+               ;;
+       dynix*)
+               OS="dynixptx${os_v}"
+               SYS=dynixptx
+               os_v1=`echo "$os_v" | cut -d. -f1`
+               os_v2=`echo "$os_v" | cut -d. -f2`
+               os_v3=`echo "$os_v" | cut -d. -f3`
+               if [ "$os_v3" = "" ] ; then os_v3=0 ; fi
+               os_int=`expr "$os_v1" '*' 100 + "$os_v2" '*' 10 + "$os_v3"`
+               NDEFS="$NDEFS -DDYNIX=$os_int"
+               ;;
+       linux)
+               case "$arch" in
+                       *86)
+                               arch=x86
+                               ;;
+               esac
+
+               libc=""
+               os_r1=`echo "$os_r" | cut -d. -f1`
+               os_r2=`echo "$os_r" | cut -d. -f2`
+               os_r3=`echo "$os_r" | cut -d- -f1 | cut -d. -f3`
+               os_int=`expr "$os_r1" '*' 10000 + "$os_r2" '*' 1000 + "$os_r3"`
+               NDEFS="$NDEFS -DLINUX=$os_int"
+
+               vertest="./vertest.$$"
+               /bin/rm -f "$vertest" "$vertest.c"
+               cat <<EOF > "$vertest.c"
+#include <stdio.h>
+#include <gnu/libc-version.h>
+
+main()
+{
+       const char *ver = gnu_get_libc_version();
+       const char *rel = gnu_get_libc_release();
+
+       fprintf(stdout, "glibc%s\n", ver);
+       exit(0);
+}
+EOF
+               echo $ac_n "checking version of C library""... $ac_c" 1>&6
+               echo "configure:: checking version of C library" >&5
+               ${CC-cc} $DEFS $CPPFLAGS $CFLAGS "$vertest.c" -o "$vertest" >/dev/null 2>&1
+               if [ -x "$vertest" ] ; then libc=`$vertest` ; fi
+               /bin/rm -f "$vertest" "$vertest.c"
+
+               case "$libc" in
+                       glibc*)
+                               echo "$libc" 1>&6
+                               glibc_r=`echo "$libc" | sed 's/glibc//'`
+                               glibc_r1=`echo "$glibc_r" | cut -d. -f1`
+                               glibc_r2=`echo "$glibc_r" | cut -d. -f2`
+                               glibc_r3=`echo "$glibc_r" | cut -d- -f1 | cut -d. -f3`
+                               glibc_int=`expr "$glibc_r1" '*' 10000 + "$glibc_r2" '*' 1000 + "$glibc_r3"`
+                               NDEFS="$NDEFS -DLINUX_GLIBC=$glibc_int"
+                               libc="glibc${glibc_r1}.${glibc_r2}"
+                               OS="linux-$arch"
+                               ;;
+                       *)
+                               if test -f /lib/libc-2.2.2.so ; then
+                                       NDEFS="$NDEFS -DLINUX_GLIBC=22002"
+                                       libc="glibc2.2"
+                                       OS="linux-$arch"
+                               elif test -f /lib/libc-2.2.1.so ; then
+                                       NDEFS="$NDEFS -DLINUX_GLIBC=22001"
+                                       libc="glibc2.2"
+                                       OS="linux-$arch"
+                               elif test -f /lib/libc-2.2.0.so ; then
+                                       NDEFS="$NDEFS -DLINUX_GLIBC=22000"
+                                       libc="glibc2.1"
+                                       OS="linux-$arch"
+                               elif test -f /lib/libc-2.1.3.so ; then
+                                       NDEFS="$NDEFS -DLINUX_GLIBC=21003"
+                                       libc="glibc2.1"
+                                       OS="linux-$arch"
+                               elif test -f /lib/libc-2.1.2.so ; then
+                                       NDEFS="$NDEFS -DLINUX_GLIBC=21002"
+                                       libc="glibc2.1"
+                                       OS="linux-$arch"
+                               elif test -f /lib/libc-2.1.1.so ; then
+                                       NDEFS="$NDEFS -DLINUX_GLIBC=21001"
+                                       libc="glibc2.1"
+                                       OS="linux-$arch"
+                               elif test -f /lib/libc.so.6 ; then
+                                       NDEFS="$NDEFS -DLINUX_GLIBC=20000"
+                                       libc="glibc2.0"
+                                       OS="linux-$arch"
+                               elif test -f /lib/libc.so.6.1 ; then
+                                       NDEFS="$NDEFS -DLINUX_GLIBC=20001"
+                                       libc="glibc2.0"
+                                       OS="linux-$arch"
+                               else
+                                       NDEFS="$NDEFS -DLINUX_LIBC=5"
+                                       libc="libc5"
+                                       OS="linux-$arch"
+                               fi
+                               echo "$libc" 1>&6
+                               ;;
+               esac
+               SYS=linux
+               ;;
+       bsd/os)
+               OS="bsdos${os_r}"
+               SYS=bsdos
+               NDEFS="$NDEFS -DBSDOS=$os_r1"
+               ;;
+       ultrix)
+               OS="ultrix-$arch"
+               SYS=ultrix
+               ;;
+       unixware|eeyore)
+               OS="unixware${os_v}"
+               SYS=unixware
+               ;;
+       macos*|darwin|rhapsody)
+               OS="macosx"
+               SYS="macosx"
+               ;;
+       sunos)
+               if [ "$arch" = "" ] ; then arch="sparc" ; fi
+               if [ "$archp" = "" ] ; then archp="$arch" ; fi
+               case "$os_r" in
+                       5.[789]*)
+                               os_r=`echo "$os_r" | cut -c3-`
+                               OS="solaris${os_r}-$archp"
+                               NDEFS="$NDEFS -DSOLARIS=\\\"$os_r\\\""
+                               SYS=solaris
+                               ;;
+                       5.[0123456]*)
+                               maj=`echo "$os_r" | cut -c1-1`
+                               maj=`expr "$maj" - 3`
+                               os_r=`echo "$os_r" | cut -c2-`
+                               os_r="${maj}${os_r}"
+                               OS="solaris${os_r}-$archp"
+                               NDEFS="$NDEFS -DSOLARIS=\\\"$os_r\\\""
+                               SYS=solaris
+                               ;;
+                       4.*)
+                               OS="sunos${os_r}-sparc"
+                               NDEFS="$NDEFS -DSUNOS=\\\"$os_r\\\""
+                               SYS=sunos
+                               ;;
+                       *)
+                               OS="solaris${os_r}-$archp"
+                               NDEFS="$NDEFS -DSOLARIS=\\\"$os_r\\\""
+                               SYS=solaris
+                               ;;
+               esac
+               ;;
+       *)
+               OS="$os"
+               SYS="$os"
+
+               if grep Novell /usr/include/sys/types.h ; then
+                       OS="unixware${os_v}"
+                       SYS="unixware"
+               fi
+               ;;
+esac
+
+changequote([, ])
+
+AC_SUBST(NDEFS)
+AC_SUBST(OS)
+AC_SUBST(host)
+AC_SUBST(SYS)
+AC_SUBST(HOME_OS)
+])
diff --git a/rosapps/net/ncftp/libncftp/Makefile.in b/rosapps/net/ncftp/libncftp/Makefile.in
new file mode 100644 (file)
index 0000000..4810f0a
--- /dev/null
@@ -0,0 +1,144 @@
+#-----------------------------------------------------------------------------
+#
+# LibNcFTP makefile for the platform @OS@, on the host @host@.
+#
+#-----------------------------------------------------------------------------
+PKGNAME=libncftp
+VERSION=3.0.1
+PREFIX=@prefix@
+
+CC=@CC@
+CFLAGS=@CFLAGS@
+#CC=gcc
+#CFLAGS=-g -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wbad-function-cast -Wwrite-strings -Wconversion
+VPATH=@srcdir@
+CPPFLAGS=-I. -I../Strn -I../sio @CPPFLAGS@
+
+LIB=libncftp.a
+LIBSO=libncftp.so.2
+LIBSOS=libncftp.so
+
+# Any -D definitions:
+DEFS=@DEFS@@NDEFS@
+
+CFILES=open.c cmds.c util.c rcmd.c ftp.c io.c errno.c linelist.c glob.c
+OBJS=open.o cmds.o util.o rcmd.o ftp.o io.o errno.o linelist.o glob.o
+SOBJS=open.so cmds.so util.so rcmd.so ftp.so io.so errno.so linelist.so glob.so
+
+# LIBSET=@LIBSET@
+LIBSET=$(LIB)
+
+SHELL=/bin/sh
+.SUFFIXES: .c .o .so
+
+all: $(LIBSET)
+       ( cd ../sio ; $(MAKE) )
+       ( cd ../Strn ; $(MAKE) )
+       -[ -d ./samples/minincftp ] && cd ./samples/minincftp && $(MAKE)
+       -[ -d ./samples/misc ] && cd ./samples/misc && $(MAKE)
+       -[ -d ./samples/monkey ] && cd ./samples/monkey && $(MAKE)
+       -[ -d ./samples/ncftpget ] && cd ./samples/ncftpget && $(MAKE)
+       -[ -d ./samples/ncftpls ] && cd ./samples/ncftpls && $(MAKE)
+       -[ -d ./samples/ncftpput ] && cd ./samples/ncftpput && $(MAKE)
+       -[ -d ./samples/ncftpsyncput ] && cd ./samples/ncftpsyncput && $(MAKE)
+       @echo 'Done.'
+
+$(LIB): $(OBJS)
+       -@/bin/rm -f $(LIB)
+       ar rv $(LIB) $(OBJS)
+       -@chmod 644 $(LIB)
+       -@@RANLIB@ $(LIB)
+       @/bin/ls -l $(LIB)
+
+shared: $(LIBSO)
+
+so: $(LIBSO)
+
+$(LIBSO): $(SOBJS)
+       /bin/rm -f $(LIBSO) $(LIBSOS)
+       gcc -shared -Wl,-soname,$(LIBSO) -o $(LIBSO) $(SOBJS)
+       /bin/ln -s $(LIBSO) $(LIBSOS)
+       -@/bin/ls -l $(LIBSOS) $(LIBSO)
+
+soinstall: $(LIBSO)
+       [ -d "$(PREFIX)/lib" ] || mkdir -m 755 "$(PREFIX)/lib"
+       [ -d "$(PREFIX)/include" ] || mkdir -m 755 "$(PREFIX)/include"
+       cp $(LIBSO) $(PREFIX)/lib/$(LIBSO)
+       ( cd $(PREFIX)/lib ; /bin/rm -f $(LIBSOS) ; /bin/ln -s $(LIBSO) $(LIBSOS) )
+       cp ncftp.h ncftp_errno.h $(PREFIX)/include
+       -chmod a+r $(PREFIX)/lib/$(LIBSO) $(PREFIX)/include/ncftp.h $(PREFIX)/include/ncftp_errno.h
+
+install: $(LIB)
+       [ -d "$(PREFIX)/lib" ] || mkdir -m 755 "$(PREFIX)/lib"
+       [ -d "$(PREFIX)/include" ] || mkdir -m 755 "$(PREFIX)/include"
+       cp $(LIB) $(PREFIX)/lib/$(LIB)
+       cp ncftp.h ncftp_errno.h $(PREFIX)/include
+       -chmod a+r $(LIB) $(PREFIX)/lib/$(LIB) $(PREFIX)/include/ncftp.h $(PREFIX)/include/ncftp_errno.h
+       ( cd ../sio ; $(MAKE) "PREFIX=$(PREFIX)" install )
+       ( cd ../Strn ; $(MAKE) "PREFIX=$(PREFIX)" install )
+
+install_samples:
+       ( cd ./samples ; $(MAKE) install )
+
+.c.o:
+       $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c
+
+.c.so:
+       $(CC) -fpic $(CFLAGS) $(CPPFLAGS) $(DEFS) $*.c -c -o $*.so
+
+test: test.c $(OBJS)
+       $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) test.c $(OBJS) -o test $(LDFLAGS) $(LIBS)
+
+### Archiving #################################################################
+
+TARDIR=libncftp-$(VERSION)
+TMPDIR=/tmp
+STGZFILE=libncftp-$(VERSION)-src.tar.gz
+
+gz sgz: $(PACKAGE)
+       ./mksrctar.sh $(TARDIR) $(STGZFILE)
+
+### Cleaning supplies ########################################################
+
+clean:
+       -/bin/rm -f $(OBJS) $(SOBJS) core $(LIB) $(LIBSO) $(LIBSOS)
+       -[ -d ./samples/minincftp ] && cd ./samples/minincftp && $(MAKE) clean
+       -[ -d ./samples/monkey ] && cd ./samples/monkey && $(MAKE) clean
+       -[ -d ./samples/ncftpget ] && cd ./samples/ncftpget && $(MAKE) clean
+       -[ -d ./samples/ncftpls ] && cd ./samples/ncftpls && $(MAKE) clean
+       -[ -d ./samples/ncftpput ] && cd ./samples/ncftpput && $(MAKE) clean
+       -[ -d ./samples/ncftpsyncput ] && cd ./samples/ncftpsyncput && $(MAKE) clean
+       ( sleep 2 ; cd ../sio ; $(MAKE) clean )
+       ( sleep 2 ; cd ../Strn ; $(MAKE) clean )
+
+### Dependencies #############################################################
+
+dep:
+       gcc -MM $(CPPFLAGS) $(CFILES)
+
+open.o: open.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h
+open.so: open.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h
+
+cmds.o: cmds.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h
+cmds.so: cmds.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h
+
+util.o: util.c syshdrs.h ncftp.h ncftp_errno.h util.h
+util.so: util.c syshdrs.h ncftp.h ncftp_errno.h util.h
+
+rcmd.o: rcmd.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h
+rcmd.so: rcmd.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h
+
+ftp.o: ftp.c syshdrs.h ncftp.h ncftp_errno.h ftp.h util.h 
+ftp.so: ftp.c syshdrs.h ncftp.h ncftp_errno.h ftp.h util.h 
+
+io.o: io.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h
+io.so: io.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h
+
+errno.o: errno.c syshdrs.h ncftp.h ncftp_errno.h
+errno.so: errno.c syshdrs.h ncftp.h ncftp_errno.h
+
+linelist.o: linelist.c syshdrs.h ncftp.h ncftp_errno.h util.h
+linelist.so: linelist.c syshdrs.h ncftp.h ncftp_errno.h util.h
+
+glob.o: glob.c syshdrs.h ncftp.h ncftp_errno.h util.h
+glob.so: glob.c syshdrs.h ncftp.h ncftp_errno.h util.h
diff --git a/rosapps/net/ncftp/libncftp/Readme.txt b/rosapps/net/ncftp/libncftp/Readme.txt
new file mode 100644 (file)
index 0000000..265ea88
--- /dev/null
@@ -0,0 +1,73 @@
+Since you have the source distribution, you will need to compile the
+libraries before you can install them.
+
+UNIX INSTRUCTIONS:
+------------------
+
+Go to the source directory you extracted (here). There is a script you
+must run which will checks your system for certain features, so that the
+library can be compiled on a variety of UNIX systems.  Run this script
+by typing "./configure" in that directory.  After that, you can look at
+the Makefile it made if you like, and then you run "make" to create the
+"libncftp.a" and "libStrn.a" library files.
+
+Finally, install the libraries and headers, by doing "make install".
+
+View the libncftp.html file for the rest of the documentation.  An easy
+way to do that is use a URL of file://Localhost/path/to/libncftp.html
+with your favorite browser.
+
+
+WINDOWS INSTRUCTIONS:
+---------------------
+
+You will need Visual C++ 6.0 or greater to build the library and sample
+programs.  This version includes two supplementary libraries which you
+must build and link with your applications: a string utility library
+(Strn) and a Winsock utility library (sio).  Unlike the UNIX version of
+LibNcFTP, where the library can be built with or without the sio library,
+the sio library is required for the Windows version.
+
+Keep the source hierarchy intact, so that the samples and libraries
+build without problems.  Build the Strn library first, then the sio
+library, and then the LibNcFTP library.  To do that, open the appropriate
+.dsw file within Visual Studio, and then select "Rebuild All" from the
+"Build" menu.  Be sure to build both the Debug and the Release versions
+for each library.
+
+When that is complete you should be able to build the sample programs,
+which are in the libncftp\samples directory.
+
+View the libncftp.html file for the rest of the documentation.  An easy
+way to do that is use a URL of file://Localhost/path/to/libncftp.html
+with your favorite browser.  Note that there may be UNIX-specific
+instructions which you should ignore.
+
+To build your own applications using LibNcFTP, you'll need to make sure
+you configure your project to find the header files and library files.
+
+Your application may not use the sio or Strn libraries directly, but
+you still need to link with them.  For example, the "simpleget" sample
+uses "..\..\Debug,..\..\..\Strn\Debug,..\..\..\sio\Debug" in the
+project option for additional library paths for the linker, and
+"kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib
+ ws2_32.lib Strn.lib sio.lib libncftp.lib" for the list of libraries
+to link with.  Note that LibNcFTP uses advapi32 and shell32, in
+addition to the usual "kernel32.lib user32.lib gdi32.lib".  Of course,
+it also needs to link with Winsock (ws2_32.lib).
+
+Similarly, you'll need to make sure one of your additional include
+directories points to the LibNcFTP directory containing ncftp.h.  The
+"simpleget" sample uses "..\.." since it is in a subdirectory of the
+library itself.  If you actually use functions from Strn or sio (as
+some of the samples do), you'll need to have your project look in
+their directories for their headers as well.
+
+About Winsock2:  This version of the library was designed for use with
+Winsock version 2.  Note that older versions of Windows 95 do not include
+Winsock version 2, but can be upgraded by getting the updater from
+Microsoft:  http://www.microsoft.com/windows95/downloads/contents/wuadmintools/s_wunetworkingtools/w95sockets2/default.asp
+
+However, the library should also work with Winsock 1.1.  That is left as
+an exercise to the coder to change the Winsock initialization to use 1.1
+and to link with the 1.1 library (wsock32.lib).
\ No newline at end of file
diff --git a/rosapps/net/ncftp/libncftp/cmds.c b/rosapps/net/ncftp/libncftp/cmds.c
new file mode 100644 (file)
index 0000000..13804ac
--- /dev/null
@@ -0,0 +1,1700 @@
+/* cmds.c
+ *
+ * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
+ * All rights reserved.
+ *
+ */
+
+#include "syshdrs.h"
+
+int
+FTPChdir(const FTPCIPtr cip, const char *const cdCwd)
+{
+       int result;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if (cdCwd == NULL) {
+               result = kErrInvalidDirParam;
+               cip->errNo = kErrInvalidDirParam;
+       } else {
+               if (cdCwd[0] == '\0')   /* But allow FTPChdir(cip, ".") to go through. */
+                       result = 2;     
+               else if (strcmp(cdCwd, "..") == 0)
+                       result = FTPCmd(cip, "CDUP");
+               else
+                       result = FTPCmd(cip, "CWD %s", cdCwd);
+               if (result >= 0) {
+                       if (result == 2) {
+                               result = kNoErr;
+                       } else {
+                               result = kErrCWDFailed;
+                               cip->errNo = kErrCWDFailed;
+                       }
+               }
+       }
+       return (result);
+}      /* FTPChdir */
+
+
+
+
+int
+FTPChmod(const FTPCIPtr cip, const char *const pattern, const char *const mode, const int doGlob)
+{
+       LineList fileList;
+       LinePtr filePtr;
+       char *file;
+       int onceResult, batchResult;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob);
+       if (batchResult != kNoErr)
+               return (batchResult);
+
+       for (batchResult = kNoErr, filePtr = fileList.first;
+               filePtr != NULL;
+               filePtr = filePtr->next)
+       {
+               file = filePtr->line;
+               if (file == NULL) {
+                       batchResult = kErrBadLineList;
+                       cip->errNo = kErrBadLineList;
+                       break;
+               }
+               onceResult = FTPCmd(cip, "SITE CHMOD %s %s", mode, file);       
+               if (onceResult < 0) {
+                       batchResult = onceResult;
+                       break;
+               }
+               if (onceResult != 2) {
+                       batchResult = kErrChmodFailed;
+                       cip->errNo = kErrChmodFailed;
+               }
+       }
+       DisposeLineListContents(&fileList);
+       return (batchResult);
+}      /* FTPChmod */
+
+
+
+
+static int
+FTPRmdirRecursiveL2(const FTPCIPtr cip)
+{
+       LineList fileList;
+       LinePtr filePtr;
+       char *file;
+       int result;
+
+       result = FTPRemoteGlob(cip, &fileList, "**", kGlobYes);
+       if (result != kNoErr) {
+               return (result);
+       }
+
+       for (filePtr = fileList.first;
+               filePtr != NULL;
+               filePtr = filePtr->next)
+       {
+               file = filePtr->line;
+               if (file == NULL) {
+                       cip->errNo = kErrBadLineList;
+                       break;
+               }
+
+               if ((file[0] == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0'))))
+                       continue;       /* Skip . and .. */
+
+               if (FTPChdir(cip, file) == kNoErr) {
+                       /* It was a directory.
+                        * Go in and wax it.
+                        */
+                       result = FTPRmdirRecursiveL2(cip);
+
+                       if (FTPChdir(cip, "..") != kNoErr) {
+                               /* Panic -- we can no longer
+                                * cd back to the directory
+                                * we were in before.
+                                */
+                               result = kErrCannotGoToPrevDir;
+                               cip->errNo = kErrCannotGoToPrevDir;
+                               return (result);
+                       }
+
+                       if ((result < 0) && (result != kErrGlobNoMatch))
+                               return (result);
+
+                       result = FTPRmdir(cip, file, kRecursiveNo, kGlobNo);
+                       if (result != kNoErr) {
+                               /* Well, we couldn't remove the empty
+                                * directory.  Perhaps we screwed up
+                                * and the directory wasn't empty.
+                                */
+                               return (result);
+                       }
+               } else {
+                       /* Assume it was a file -- remove it. */
+                       result = FTPDelete(cip, file, kRecursiveNo, kGlobNo);
+                       /* Try continuing to remove the rest,
+                        * even if this failed.
+                        */
+               }
+       }
+       DisposeLineListContents(&fileList);
+
+       return (result);
+}      /* FTPRmdirRecursiveL2 */
+
+
+
+static int
+FTPRmdirRecursive(const FTPCIPtr cip, const char *const dir)
+{
+       int result, result2;
+
+       /* Preserve old working directory. */
+       (void) FTPGetCWD(cip, cip->buf, cip->bufSize);
+
+       result = FTPChdir(cip, dir);
+       if (result != kNoErr) {
+               return (result);
+       }
+
+       result = FTPRmdirRecursiveL2(cip);
+
+       if (FTPChdir(cip, cip->buf) != kNoErr) {
+               /* Could not cd back to the original user directory -- bad. */
+               if (result != kNoErr) {
+                       result = kErrCannotGoToPrevDir;
+                       cip->errNo = kErrCannotGoToPrevDir;
+               }
+               return (result);
+       }
+
+       /* Now rmdir the last node, the root of the tree
+        * we just went through.
+        */
+       result2 = FTPRmdir(cip, dir, kRecursiveNo, kGlobNo);
+       if ((result2 != kNoErr) && (result == kNoErr))
+               result = result2;
+
+       return (result);
+}      /* FTPRmdirRecursive */
+
+
+
+
+int
+FTPDelete(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob)
+{
+       LineList fileList;
+       LinePtr filePtr;
+       char *file;
+       int onceResult, batchResult;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob);
+       if (batchResult != kNoErr)
+               return (batchResult);
+
+       for (batchResult = kNoErr, filePtr = fileList.first;
+               filePtr != NULL;
+               filePtr = filePtr->next)
+       {
+               file = filePtr->line;
+               if (file == NULL) {
+                       batchResult = kErrBadLineList;
+                       cip->errNo = kErrBadLineList;
+                       break;
+               }
+               onceResult = FTPCmd(cip, "DELE %s", file);
+               if (onceResult < 0) {
+                       batchResult = onceResult;
+                       break;
+               }
+               if (onceResult != 2) {
+                       if (recurse != kRecursiveYes) {
+                               batchResult = kErrDELEFailed;
+                               cip->errNo = kErrDELEFailed;
+                       } else {
+                               onceResult = FTPCmd(cip, "RMD %s", file);       
+                               if (onceResult < 0) {
+                                       batchResult = onceResult;
+                                       break;
+                               }
+                               if (onceResult != 2) {
+                                       onceResult = FTPRmdirRecursive(cip, file);
+                                       if (onceResult < 0) {
+                                               batchResult = kErrRMDFailed;
+                                               cip->errNo = kErrRMDFailed;
+                                       }
+                               }
+                       }
+               }
+       }
+       DisposeLineListContents(&fileList);
+       return (batchResult);
+}      /* FTPDelete */
+
+
+
+
+int
+FTPGetCWD(const FTPCIPtr cip, char *const newCwd, const size_t newCwdSize)
+{
+       ResponsePtr rp;
+       char *l, *r;
+       int result;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((newCwd == NULL) || (newCwdSize == 0)) {
+               result = kErrInvalidDirParam;
+               cip->errNo = kErrInvalidDirParam;
+       } else {
+               rp = InitResponse();
+               if (rp == NULL) {
+                       result = kErrMallocFailed;
+                       cip->errNo = kErrMallocFailed;
+                       Error(cip, kDontPerror, "Malloc failed.\n");
+               } else {
+                       result = RCmd(cip, rp, "PWD");
+                       if (result == 2) {
+                               if ((r = strrchr(rp->msg.first->line, '"')) != NULL) {
+                                       /* "xxxx" is current directory.
+                                        * Strip out just the xxxx to copy into the remote cwd.
+                                        */
+                                       l = strchr(rp->msg.first->line, '"');
+                                       if ((l != NULL) && (l != r)) {
+                                               *r = '\0';
+                                               ++l;
+                                               (void) Strncpy(newCwd, l, newCwdSize);
+                                               *r = '"';       /* Restore, so response prints correctly. */
+                                       }
+                               } else {
+                                       /* xxxx is current directory.
+                                        * Mostly for VMS.
+                                        */
+                                       if ((r = strchr(rp->msg.first->line, ' ')) != NULL) {
+                                               *r = '\0';
+                                               (void) Strncpy(newCwd, (rp->msg.first->line), newCwdSize);
+                                               *r = ' ';       /* Restore, so response prints correctly. */
+                                       }
+                               }
+                               result = kNoErr;
+                       } else if (result > 0) {
+                               result = kErrPWDFailed;
+                               cip->errNo = kErrPWDFailed;
+                       }
+                       DoneWithResponse(cip, rp);
+               }
+       }
+       return (result);
+}      /* FTPGetCWD */
+
+
+
+
+int
+FTPChdirAndGetCWD(const FTPCIPtr cip, const char *const cdCwd, char *const newCwd, const size_t newCwdSize)
+{
+       ResponsePtr rp;
+       char *l, *r;
+       int result;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((newCwd == NULL) || (cdCwd == NULL)) {
+               result = kErrInvalidDirParam;
+               cip->errNo = kErrInvalidDirParam;
+       } else {
+               if (cdCwd[0] == '\0') { /* But allow FTPChdir(cip, ".") to go through. */
+                       result = FTPGetCWD(cip, newCwd, newCwdSize);
+                       return (result);
+               }
+               rp = InitResponse();
+               if (rp == NULL) {
+                       result = kErrMallocFailed;
+                       cip->errNo = kErrMallocFailed;
+                       Error(cip, kDontPerror, "Malloc failed.\n");
+               } else {
+                       if (strcmp(cdCwd, "..") == 0)
+                               result = RCmd(cip, rp, "CDUP");         
+                       else
+                               result = RCmd(cip, rp, "CWD %s", cdCwd);
+                       if (result == 2) {
+                               l = strchr(rp->msg.first->line, '"');
+                               if ((l == rp->msg.first->line) && ((r = strrchr(rp->msg.first->line, '"')) != NULL) && (l != r)) {
+                                       /* "xxxx" is current directory.
+                                        * Strip out just the xxxx to copy into the remote cwd.
+                                        *
+                                        * This is nice because we didn't have to do a PWD.
+                                        */
+                                       *r = '\0';
+                                       ++l;
+                                       (void) Strncpy(newCwd, l, newCwdSize);
+                                       *r = '"';       /* Restore, so response prints correctly. */
+                                       DoneWithResponse(cip, rp);
+                                       result = kNoErr;
+                               } else {
+                                       DoneWithResponse(cip, rp);
+                                       result = FTPGetCWD(cip, newCwd, newCwdSize);
+                               }
+                       } else if (result > 0) {
+                               result = kErrCWDFailed;
+                               cip->errNo = kErrCWDFailed;
+                               DoneWithResponse(cip, rp);
+                       } else {
+                               DoneWithResponse(cip, rp);
+                       }
+               }
+       }
+       return (result);
+}      /* FTPChdirAndGetCWD */
+
+
+
+
+int
+FTPChdir3(FTPCIPtr cip, const char *const cdCwd, char *const newCwd, const size_t newCwdSize, int flags)
+{
+       char *cp, *startcp;
+       int result;
+       int lastSubDir;
+       int mkd, pwd;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if (cdCwd == NULL) {
+               result = kErrInvalidDirParam;
+               cip->errNo = kErrInvalidDirParam;
+               return result;
+       }
+
+       if (flags == kChdirOnly)
+               return (FTPChdir(cip, cdCwd));
+       if (flags == kChdirAndGetCWD) {
+               return (FTPChdirAndGetCWD(cip, cdCwd, newCwd, newCwdSize));
+       } else if (flags == kChdirAndMkdir) {
+               result = FTPMkdir(cip, cdCwd, kRecursiveYes);
+               if (result == kNoErr)
+                       result = FTPChdir(cip, cdCwd);
+               return result;
+       } else if (flags == (kChdirAndMkdir|kChdirAndGetCWD)) {
+               result = FTPMkdir(cip, cdCwd, kRecursiveYes);
+               if (result == kNoErr)
+                       result = FTPChdirAndGetCWD(cip, cdCwd, newCwd, newCwdSize);
+               return result;
+       }
+
+       /* else: (flags | kChdirOneSubdirAtATime) == true */
+       
+       cp = cip->buf;
+       cp[cip->bufSize - 1] = '\0';
+       (void) Strncpy(cip->buf, cdCwd, cip->bufSize);
+       if (cp[cip->bufSize - 1] != '\0')
+               return (kErrBadParameter);
+       
+       mkd = (flags & kChdirAndMkdir);
+       pwd = (flags & kChdirAndGetCWD);
+
+       if ((cdCwd[0] == '\0') || (strcmp(cdCwd, ".") == 0)) {
+               result = 0;
+               if (flags == kChdirAndGetCWD)
+                       result = FTPGetCWD(cip, newCwd, newCwdSize);
+               return (result);
+       }
+
+       lastSubDir = 0;
+       do {
+               startcp = cp;
+               cp = StrFindLocalPathDelim(cp);
+               if (cp != NULL) {
+                       /* If this is the first slash in an absolute
+                        * path, then startcp will be empty.  We will
+                        * use this below to treat this as the root
+                        * directory.
+                        */
+                       *cp++ = '\0';
+               } else {
+                       lastSubDir = 1;
+               }
+               if (strcmp(startcp, ".") == 0) {
+                       result = 0;
+                       if ((lastSubDir != 0) && (pwd != 0))
+                               result = FTPGetCWD(cip, newCwd, newCwdSize);
+               } else if ((lastSubDir != 0) && (pwd != 0)) {
+                       result = FTPChdirAndGetCWD(cip, (*startcp != '\0') ? startcp : "/", newCwd, newCwdSize);
+               } else {
+                       result = FTPChdir(cip, (*startcp != '\0') ? startcp : "/");
+               }
+               if (result < 0) {
+                       if ((mkd != 0) && (*startcp != '\0')) {
+                               if (FTPCmd(cip, "MKD %s", startcp) == 2) {
+                                       result = FTPChdir(cip, startcp);
+                               } else {
+                                       /* couldn't change nor create */
+                                       cip->errNo = result;
+                               }
+                       } else {
+                               cip->errNo = result;
+                       }
+               }
+       } while ((!lastSubDir) && (result == 0));
+
+       return (result);
+}      /* FTPChdir3 */
+
+
+
+
+int
+FTPMkdir2(const FTPCIPtr cip, const char *const newDir, const int recurse, const char *const curDir)
+{
+       int result, result2;
+       char *cp, *newTreeStart, *cp2;
+       char dir[512];
+       char dir2[512];
+       char c;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((newDir == NULL) || (newDir[0] == '\0')) {
+               cip->errNo = kErrInvalidDirParam;
+               return (kErrInvalidDirParam);
+       }
+
+       /* Preserve old working directory. */
+       if ((curDir == NULL) || (curDir[0] == '\0')) {
+               /* This hack is nice so you can eliminate an
+                * unnecessary "PWD" command on the server,
+                * since if you already knew what directory
+                * you're in.  We want to minimize the number
+                * of client-server exchanges when feasible.
+                */
+               (void) FTPGetCWD(cip, cip->buf, cip->bufSize);
+       }
+
+       result = FTPChdir(cip, newDir);
+       if (result == kNoErr) {
+               /* Directory already exists -- but we
+                * must now change back to where we were.
+                */
+               result2 = FTPChdir(cip, ((curDir == NULL) || (curDir[0] == '\0')) ? cip->buf : curDir);
+               if (result2 < 0) {
+                       result = kErrCannotGoToPrevDir;
+                       cip->errNo = kErrCannotGoToPrevDir;
+                       return (result);
+               }
+
+               /* Don't need to create it. */
+               return (kNoErr);
+       }
+
+       if (recurse == kRecursiveNo) {
+               result = FTPCmd(cip, "MKD %s", newDir);
+               if (result > 0) {
+                       if (result != 2) {
+                               Error(cip, kDontPerror, "MKD %s failed; [%s]\n", newDir, cip->lastFTPCmdResultStr);
+                               result = kErrMKDFailed;
+                               cip->errNo = kErrMKDFailed;
+                               return (result);
+                       } else {
+                               result = kNoErr;
+                       }
+               }
+       } else {
+               (void) STRNCPY(dir, newDir);
+
+               /* Strip trailing slashes. */
+               cp = dir + strlen(dir) - 1;
+               for (;;) {
+                       if (cp <= dir) {
+                               if ((newDir == NULL) || (newDir[0] == '\0')) {
+                                       cip->errNo = kErrInvalidDirParam;
+                                       result = kErrInvalidDirParam;
+                                       return (result);
+                               }
+                       }
+                       if ((*cp != '/') && (*cp != '\\')) {
+                               cp[1] = '\0';
+                               break;
+                       }
+                       --cp;
+               }
+               (void) STRNCPY(dir2, dir);
+
+               if ((strrchr(dir, '/') == dir) || (strrchr(dir, '\\') == dir)) {
+                       /* Special case "mkdir /subdir" */
+                       result = FTPCmd(cip, "MKD %s", dir);
+                       if (result < 0) {
+                               return (result);
+                       }
+                       if (result != 2) {
+                               Error(cip, kDontPerror, "MKD %s failed; [%s]\n", dir, cip->lastFTPCmdResultStr);
+                               result = kErrMKDFailed;
+                               cip->errNo = kErrMKDFailed;
+                               return (result);
+                       }
+                       /* Haven't chdir'ed, don't need to goto goback. */
+                       return (kNoErr);
+               }
+
+               for (;;) {
+                       cp = strrchr(dir, '/');
+                       if (cp == NULL)
+                               cp = strrchr(dir, '\\');
+                       if (cp == NULL) {
+                               cp = dir + strlen(dir) - 1;
+                               if (dir[0] == '\0') {
+                                       result = kErrMKDFailed;
+                                       cip->errNo = kErrMKDFailed;
+                                       return (result);
+                               }
+                               /* Note: below we will refer to cp + 1
+                                * which is why we set cp to point to
+                                * the byte before the array begins!
+                                */
+                               cp = dir - 1;
+                               break;
+                       }
+                       if (cp == dir) {
+                               result = kErrMKDFailed;
+                               cip->errNo = kErrMKDFailed;
+                               return (result);
+                       }
+                       *cp = '\0';
+                       result = FTPChdir(cip, dir);
+                       if (result == 0) {
+                               break;  /* Found a valid parent dir. */
+                               /* from this point, we need to preserve old dir. */
+                       }
+               }
+
+               newTreeStart = dir2 + ((cp + 1) - dir);
+               for (cp = newTreeStart; ; ) {
+                       cp2 = cp;
+                       cp = strchr(cp2, '/');
+                       c = '/';
+                       if (cp == NULL)
+                               cp = strchr(cp2, '\\');
+                       if (cp != NULL) {
+                               c = *cp;
+                               *cp = '\0';
+                               if (cp[1] == '\0') {
+                                       /* Done, if they did "mkdir /tmp/dir/" */
+                                       break;
+                               }
+                       }
+                       result = FTPCmd(cip, "MKD %s", newTreeStart);
+                       if (result < 0) {
+                               return (result);
+                       }
+                       if (result != 2) {
+                               Error(cip, kDontPerror, "Cwd=%s; MKD %s failed; [%s]\n", cip->buf, newTreeStart, cip->lastFTPCmdResultStr);
+                               result = kErrMKDFailed;
+                               cip->errNo = kErrMKDFailed;
+                               goto goback;
+                       }
+                       if (cp == NULL)
+                               break;  /* No more to make, done. */
+                       *cp++ = c;
+               }
+               result = kNoErr;
+
+goback:
+               result2 = FTPChdir(cip, ((curDir == NULL) || (curDir[0] == '\0')) ? cip->buf : curDir);
+               if ((result == 0) && (result2 < 0)) {
+                       result = kErrCannotGoToPrevDir;
+                       cip->errNo = kErrCannotGoToPrevDir;
+               }
+       }
+       return (result);
+}      /* FTPMkdir2 */
+
+
+
+int
+FTPMkdir(const FTPCIPtr cip, const char *const newDir, const int recurse)
+{
+       return (FTPMkdir2(cip, newDir, recurse, NULL));
+}      /* FTPMkdir */
+
+
+
+int
+FTPFileModificationTime(const FTPCIPtr cip, const char *const file, time_t *const mdtm)
+{
+       int result;
+       ResponsePtr rp;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((mdtm == NULL) || (file == NULL))
+               return (kErrBadParameter);
+       *mdtm = kModTimeUnknown;
+
+       if (cip->hasMDTM == kCommandNotAvailable) {
+               cip->errNo = kErrMDTMNotAvailable;
+               result = kErrMDTMNotAvailable;
+       } else {
+               rp = InitResponse();
+               if (rp == NULL) {
+                       result = kErrMallocFailed;
+                       cip->errNo = kErrMallocFailed;
+                       Error(cip, kDontPerror, "Malloc failed.\n");
+               } else {
+                       result = RCmd(cip, rp, "MDTM %s", file);
+                       if (result < 0) {
+                               DoneWithResponse(cip, rp);
+                               return (result);
+                       } else if (strncmp(rp->msg.first->line, "19100", 5) == 0) {
+                               Error(cip, kDontPerror, "Warning: Server has Y2K Bug in \"MDTM\" command.\n");
+                               cip->errNo = kErrMDTMFailed;
+                               result = kErrMDTMFailed;
+                       } else if (result == 2) {
+                               *mdtm = UnMDTMDate(rp->msg.first->line);
+                               cip->hasMDTM = kCommandAvailable;
+                               result = kNoErr;
+                       } else if (UNIMPLEMENTED_CMD(rp->code)) {
+                               cip->hasMDTM = kCommandNotAvailable;
+                               cip->errNo = kErrMDTMNotAvailable;
+                               result = kErrMDTMNotAvailable;
+                       } else {
+                               cip->errNo = kErrMDTMFailed;
+                               result = kErrMDTMFailed;
+                       }
+                       DoneWithResponse(cip, rp);
+               }
+       }
+       return (result);
+}      /* FTPFileModificationTime */
+
+
+
+
+int
+FTPRename(const FTPCIPtr cip, const char *const oldname, const char *const newname)
+{
+       int result;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+       if ((oldname == NULL) || (oldname[0] == '\0'))
+               return (kErrBadParameter);
+       if ((newname == NULL) || (oldname[0] == '\0'))
+               return (kErrBadParameter);
+
+       
+       result = FTPCmd(cip, "RNFR %s", oldname);
+       if (result < 0)
+               return (result);
+       if (result != 3) {
+               cip->errNo = kErrRenameFailed;
+               return (cip->errNo);
+       }
+       
+       result = FTPCmd(cip, "RNTO %s", newname);
+       if (result < 0)
+               return (result);
+       if (result != 2) {
+               cip->errNo = kErrRenameFailed;
+               return (cip->errNo);
+       }
+       return (kNoErr);
+}      /* FTPRename */
+
+
+
+
+int
+FTPRemoteHelp(const FTPCIPtr cip, const char *const pattern, const LineListPtr llp)
+{
+       int result;
+       ResponsePtr rp;
+
+       if ((cip == NULL) || (llp == NULL))
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       InitLineList(llp);
+       rp = InitResponse();
+       if (rp == NULL) {
+               result = kErrMallocFailed;
+               cip->errNo = kErrMallocFailed;
+               Error(cip, kDontPerror, "Malloc failed.\n");
+       } else {
+               if ((pattern == NULL) || (*pattern == '\0'))
+                       result = RCmd(cip, rp, "HELP");
+               else
+                       result = RCmd(cip, rp, "HELP %s", pattern);
+               if (result < 0) {
+                       DoneWithResponse(cip, rp);
+                       return (result);
+               } else if (result == 2) {
+                       if (CopyLineList(llp, &rp->msg) < 0) {
+                               result = kErrMallocFailed;
+                               cip->errNo = kErrMallocFailed;
+                               Error(cip, kDontPerror, "Malloc failed.\n");
+                       } else {
+                               result = kNoErr;
+                       }
+               } else {
+                       cip->errNo = kErrHELPFailed;
+                       result = kErrHELPFailed;
+               }
+               DoneWithResponse(cip, rp);
+       }
+       return (result);
+}      /* FTPRemoteHelp */
+
+
+
+
+int
+FTPRmdir(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob)
+{
+       LineList fileList;
+       LinePtr filePtr;
+       char *file;
+       int onceResult, batchResult;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob);
+       if (batchResult != kNoErr)
+               return (batchResult);
+
+       for (batchResult = kNoErr, filePtr = fileList.first;
+               filePtr != NULL;
+               filePtr = filePtr->next)
+       {
+               file = filePtr->line;
+               if (file == NULL) {
+                       batchResult = kErrBadLineList;
+                       cip->errNo = kErrBadLineList;
+                       break;
+               }
+               onceResult = FTPCmd(cip, "RMD %s", file);       
+               if (onceResult < 0) {
+                       batchResult = onceResult;
+                       break;
+               }
+               if (onceResult != 2) {
+                       if (recurse == kRecursiveYes) {
+                               onceResult = FTPRmdirRecursive(cip, file);
+                               if (onceResult < 0) {
+                                       batchResult = kErrRMDFailed;
+                                       cip->errNo = kErrRMDFailed;
+                               }
+                       } else {
+                               batchResult = kErrRMDFailed;
+                               cip->errNo = kErrRMDFailed;
+                       }
+               }
+       }
+       DisposeLineListContents(&fileList);
+       return (batchResult);
+}      /* FTPRmdir */
+
+
+
+
+int
+FTPSetTransferType(const FTPCIPtr cip, int type)
+{
+       int result;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if (cip->curTransferType != type) {
+               switch (type) {
+                       case kTypeAscii:
+                       case kTypeBinary:
+                       case kTypeEbcdic:
+                               break;
+                       case 'i':
+                       case 'b':
+                       case 'B':
+                               type = kTypeBinary;
+                               break;
+                       case 'e':
+                               type = kTypeEbcdic;
+                               break;
+                       case 'a':
+                               type = kTypeAscii;
+                               break;
+                       default:
+                               /* Yeah, we don't support Tenex.  Who cares? */
+                               Error(cip, kDontPerror, "Bad transfer type [%c].\n", type);
+                               cip->errNo = kErrBadTransferType;
+                               return (kErrBadTransferType);
+               }
+               result = FTPCmd(cip, "TYPE %c", type);
+               if (result != 2) {
+                       result = kErrTYPEFailed;
+                       cip->errNo = kErrTYPEFailed;
+                       return (result);
+               }
+               cip->curTransferType = type;
+       }
+       return (kNoErr);
+}      /* FTPSetTransferType */
+
+
+
+
+/* If the remote host supports the SIZE command, we can find out the exact
+ * size of a remote file, depending on the transfer type in use.  SIZE
+ * returns different values for ascii and binary modes!
+ */
+int
+FTPFileSize(const FTPCIPtr cip, const char *const file, longest_int *const size, const int type)
+{
+       int result;
+       ResponsePtr rp;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((size == NULL) || (file == NULL))
+               return (kErrBadParameter);
+       *size = kSizeUnknown;
+
+       result = FTPSetTransferType(cip, type);
+       if (result < 0)
+               return (result);
+
+       if (cip->hasSIZE == kCommandNotAvailable) {
+               cip->errNo = kErrSIZENotAvailable;
+               result = kErrSIZENotAvailable;
+       } else {
+               rp = InitResponse();
+               if (rp == NULL) {
+                       result = kErrMallocFailed;
+                       cip->errNo = kErrMallocFailed;
+                       Error(cip, kDontPerror, "Malloc failed.\n");
+               } else {
+                       result = RCmd(cip, rp, "SIZE %s", file);
+                       if (result < 0) {
+                               DoneWithResponse(cip, rp);
+                               return (result);
+                       } else if (result == 2) {
+#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
+                               (void) sscanf(rp->msg.first->line, SCANF_LONG_LONG, size);
+#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
+                               *size = (longest_int) strtoq(rp->msg.first->line, NULL, 0);
+#else
+                               (void) sscanf(rp->msg.first->line, "%ld", size);
+#endif
+                               cip->hasSIZE = kCommandAvailable;
+                               result = kNoErr;
+                       } else if (UNIMPLEMENTED_CMD(rp->code)) {
+                               cip->hasSIZE = kCommandNotAvailable;
+                               cip->errNo = kErrSIZENotAvailable;
+                               result = kErrSIZENotAvailable;
+                       } else {
+                               cip->errNo = kErrSIZEFailed;
+                               result = kErrSIZEFailed;
+                       }
+                       DoneWithResponse(cip, rp);
+               }
+       }
+       return (result);
+}      /* FTPFileSize */
+
+
+
+
+int
+FTPMListOneFile(const FTPCIPtr cip, const char *const file, const MLstItemPtr mlip)
+{
+       int result;
+       ResponsePtr rp;
+
+       /* We do a special check for older versions of NcFTPd which
+        * are based off of an incompatible previous version of IETF
+        * extensions.
+        *
+        * Roxen also seems to be way outdated, where MLST was on the
+        * data connection among other things.
+        *
+        */
+       if (
+               (cip->hasMLST == kCommandNotAvailable) ||
+               ((cip->serverType == kServerTypeNcFTPd) && (cip->ietfCompatLevel < 19981201)) ||
+               (cip->serverType == kServerTypeRoxen)
+       ) {
+               cip->errNo = kErrMLSTNotAvailable;
+               return (cip->errNo);
+       }
+
+       rp = InitResponse();
+       if (rp == NULL) {
+               result = cip->errNo = kErrMallocFailed;
+               Error(cip, kDontPerror, "Malloc failed.\n");
+       } else {
+               result = RCmd(cip, rp, "MLST %s", file);
+               if (
+                       (result == 2) &&
+                       (rp->msg.first->line != NULL) &&
+                       (rp->msg.first->next != NULL) &&
+                       (rp->msg.first->next->line != NULL)
+               ) {
+                       result = UnMlsT(rp->msg.first->next->line, mlip);
+                       if (result < 0) {
+                               cip->errNo = result = kErrInvalidMLSTResponse;
+                       }
+               } else if (UNIMPLEMENTED_CMD(rp->code)) {
+                       cip->hasMLST = kCommandNotAvailable;
+                       cip->errNo = kErrMLSTNotAvailable;
+                       result = kErrMLSTNotAvailable;
+               } else {
+                       cip->errNo = kErrMLSTFailed;
+                       result = kErrMLSTFailed;
+               }
+               DoneWithResponse(cip, rp);
+       }
+
+       return (result);
+}      /* FTPMListOneFile */
+
+
+
+
+/* We only use STAT to see if files or directories exist.
+ * But since it is so rarely used in the wild, we need to
+ * make sure the server supports the use where we pass
+ * a pathname as a parameter.
+ */
+int
+FTPFileExistsStat(const FTPCIPtr cip, const char *const file)
+{
+       int result;
+       ResponsePtr rp;
+       LineList fileList;
+       char savedCwd[512];
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if (file == NULL)
+               return (kErrBadParameter);
+
+       if (cip->STATfileParamWorks == kCommandNotAvailable) {
+               cip->errNo = result = kErrSTATwithFileNotAvailable;
+               return (result);
+       }
+
+       if (cip->STATfileParamWorks == kCommandAvailabilityUnknown) {
+               rp = InitResponse();
+               if (rp == NULL) {
+                       result = kErrMallocFailed;
+                       cip->errNo = kErrMallocFailed;
+                       Error(cip, kDontPerror, "Malloc failed.\n");
+                       return (result);
+
+               }
+
+               /* First, make sure that when we STAT a pathname
+                * that does not exist, that we get an error back.
+                *
+                * We also assume that a valid STAT response has
+                * at least 3 lines of response text, typically
+                * a "start" line, intermediate data, and then
+                * a trailing line.
+                *
+                * We also can see a one-line case.
+                */
+               result = RCmd(cip, rp, "STAT %s", "NoSuchFile");
+               if ((result == 2) && ((rp->msg.nLines >= 3) || (rp->msg.nLines == 1))) {
+                       /* Hmmm.... it gave back a positive
+                        * response.  So STAT <file> does not
+                        * work correctly.
+                        */
+                       if (
+                               (rp->msg.first->next != NULL) &&
+                               (rp->msg.first->next->line != NULL) &&
+                               (
+                                       (strstr(rp->msg.first->next->line, "o such file") != NULL) ||
+                                       (strstr(rp->msg.first->next->line, "ot found") != NULL)
+                               )
+                       ) {
+                               /* OK, while we didn't want a 200
+                                * level response, some servers,
+                                * like wu-ftpd print an error
+                                * message "No such file or
+                                * directory" which we can special
+                                * case.
+                                */
+                               result = kNoErr;
+                       } else {
+                               cip->STATfileParamWorks = kCommandNotAvailable;
+                               cip->errNo = result = kErrSTATwithFileNotAvailable;
+                               DoneWithResponse(cip, rp);
+                               return (result);
+                       }
+               }
+               DoneWithResponse(cip, rp);
+
+               /* We can't assume that we can simply say STAT rootdir/firstfile,
+                * since the remote host may not be using / as a directory
+                * delimiter.  So we have to change to the root directory
+                * and then do the STAT on that file.
+                */
+               if (
+                       (FTPGetCWD(cip, savedCwd, sizeof(savedCwd)) != kNoErr) ||
+                       (FTPChdir(cip, cip->startingWorkingDirectory) != kNoErr)
+               ) {
+                       return (cip->errNo);
+               }
+
+               /* OK, we get an error when we stat
+                * a non-existant file, but now we need to
+                * see if we get a positive reply when
+                * we stat a file that does exist.
+                *
+                * To do this, we list the root directory,
+                * which we assume has one or more items.
+                * If it doesn't, the user can't do anything
+                * anyway.  Then we stat the first item
+                * we found to see if STAT says it exists.
+                */
+               if (
+                       ((result = FTPListToMemory2(cip, "", &fileList, "", 0, (int *) 0)) < 0) ||
+                       (fileList.last == NULL) ||
+                       (fileList.last->line == NULL)
+               ) {
+                       /* Hmmm... well, in any case we can't use STAT. */
+                       cip->STATfileParamWorks = kCommandNotAvailable;
+                       cip->errNo = result = kErrSTATwithFileNotAvailable;
+                       DisposeLineListContents(&fileList);
+                       (void) FTPChdir(cip, savedCwd);
+                       return (result);
+               }
+
+               rp = InitResponse();
+               if (rp == NULL) {
+                       result = kErrMallocFailed;
+                       cip->errNo = kErrMallocFailed;
+                       Error(cip, kDontPerror, "Malloc failed.\n");
+                       DisposeLineListContents(&fileList);
+                       (void) FTPChdir(cip, savedCwd);
+                       return (result);
+
+               }
+
+               result = RCmd(cip, rp, "STAT %s", fileList.last->line);
+               DisposeLineListContents(&fileList);
+
+               if ((result != 2) || (rp->msg.nLines == 2)) {
+                       /* Hmmm.... it gave back a negative
+                        * response.  So STAT <file> does not
+                        * work correctly.
+                        */
+                       cip->STATfileParamWorks = kCommandNotAvailable;
+                       cip->errNo = result = kErrSTATwithFileNotAvailable;
+                       DoneWithResponse(cip, rp);
+                       (void) FTPChdir(cip, savedCwd);
+                       return (result);
+               } else if (
+                               (rp->msg.first->next != NULL) &&
+                               (rp->msg.first->next->line != NULL) &&
+                               (
+                                       (strstr(rp->msg.first->next->line, "o such file") != NULL) ||
+                                       (strstr(rp->msg.first->next->line, "ot found") != NULL)
+                               )
+               ) {
+                       /* Same special-case of the second line of STAT response. */
+                       cip->STATfileParamWorks = kCommandNotAvailable;
+                       cip->errNo = result = kErrSTATwithFileNotAvailable;
+                       DoneWithResponse(cip, rp);
+                       (void) FTPChdir(cip, savedCwd);
+                       return (result);
+               }
+               DoneWithResponse(cip, rp);
+               cip->STATfileParamWorks = kCommandAvailable;
+
+               /* Don't forget to change back to the original directory. */
+               (void) FTPChdir(cip, savedCwd);
+       }
+
+       rp = InitResponse();
+       if (rp == NULL) {
+               result = kErrMallocFailed;
+               cip->errNo = kErrMallocFailed;
+               Error(cip, kDontPerror, "Malloc failed.\n");
+               return (result);
+       }
+
+       result = RCmd(cip, rp, "STAT %s", file);
+       if (result == 2) {
+               result = kNoErr;
+               if (((rp->msg.nLines >= 3) || (rp->msg.nLines == 1))) {
+                       if (
+                               (rp->msg.first->next != NULL) &&
+                               (rp->msg.first->next->line != NULL) &&
+                               (
+                                       (strstr(rp->msg.first->next->line, "o such file") != NULL) ||
+                                       (strstr(rp->msg.first->next->line, "ot found") != NULL)
+                               )
+                       ) {
+                               cip->errNo = kErrSTATFailed;
+                               result = kErrSTATFailed;
+                       } else {
+                               result = kNoErr;
+                       }
+               } else if (rp->msg.nLines == 2) {
+                       cip->errNo = kErrSTATFailed;
+                       result = kErrSTATFailed;
+               } else {
+                       result = kNoErr;
+               }
+       } else {
+               cip->errNo = kErrSTATFailed;
+               result = kErrSTATFailed;
+       }
+       DoneWithResponse(cip, rp);
+       return (result);
+}      /* FTPFileExistsStat */
+
+
+
+
+/* We only use STAT to see if files or directories exist.
+ * But since it is so rarely used in the wild, we need to
+ * make sure the server supports the use where we pass
+ * a pathname as a parameter.
+ */
+int
+FTPFileExistsNlst(const FTPCIPtr cip, const char *const file)
+{
+       int result;
+       LineList fileList, rootFileList;
+       char savedCwd[512];
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if (file == NULL)
+               return (kErrBadParameter);
+
+       if (cip->NLSTfileParamWorks == kCommandNotAvailable) {
+               cip->errNo = result = kErrNLSTwithFileNotAvailable;
+               return (result);
+       }
+
+       if (cip->NLSTfileParamWorks == kCommandAvailabilityUnknown) {
+               /* First, make sure that when we NLST a pathname
+                * that does not exist, that we get an error back.
+                *
+                * We also assume that a valid NLST response has
+                * at least 3 lines of response text, typically
+                * a "start" line, intermediate data, and then
+                * a trailing line.
+                *
+                * We also can see a one-line case.
+                */
+               if (
+                       ((FTPListToMemory2(cip, "NoSuchFile", &fileList, "", 0, (int *) 0)) == kNoErr) &&
+                       (fileList.nLines >= 1) &&
+                       (strstr(fileList.last->line, "o such file") == NULL) &&
+                       (strstr(fileList.last->line, "ot found") == NULL) &&
+                       (strstr(fileList.last->line, "o Such File") == NULL) &&
+                       (strstr(fileList.last->line, "ot Found") == NULL)
+
+               ) {
+                       cip->NLSTfileParamWorks = kCommandNotAvailable;
+                       cip->errNo = result = kErrNLSTwithFileNotAvailable;
+                       DisposeLineListContents(&fileList);
+                       return (result);
+               }
+               DisposeLineListContents(&fileList);
+
+               /* We can't assume that we can simply say NLST rootdir/firstfile,
+                * since the remote host may not be using / as a directory
+                * delimiter.  So we have to change to the root directory
+                * and then do the NLST on that file.
+                */
+               if (
+                       (FTPGetCWD(cip, savedCwd, sizeof(savedCwd)) != kNoErr) ||
+                       (FTPChdir(cip, cip->startingWorkingDirectory) != kNoErr)
+               ) {
+                       return (cip->errNo);
+               }
+
+               /* OK, we get an error when we list
+                * a non-existant file, but now we need to
+                * see if we get a positive reply when
+                * we stat a file that does exist.
+                *
+                * To do this, we list the root directory,
+                * which we assume has one or more items.
+                * If it doesn't, the user can't do anything
+                * anyway.  Then we do the first item
+                * we found to see if NLST says it exists.
+                */
+               if (
+                       ((result = FTPListToMemory2(cip, "", &rootFileList, "", 0, (int *) 0)) < 0) ||
+                       (rootFileList.last == NULL) ||
+                       (rootFileList.last->line == NULL)
+               ) {
+                       /* Hmmm... well, in any case we can't use NLST. */
+                       cip->NLSTfileParamWorks = kCommandNotAvailable;
+                       cip->errNo = result = kErrNLSTwithFileNotAvailable;
+                       DisposeLineListContents(&rootFileList);
+                       (void) FTPChdir(cip, savedCwd);
+                       return (result);
+               }
+
+               if (
+                       ((FTPListToMemory2(cip, rootFileList.last->line, &fileList, "", 0, (int *) 0)) == kNoErr) &&
+                       (fileList.nLines >= 1) &&
+                       (strstr(fileList.last->line, "o such file") == NULL) &&
+                       (strstr(fileList.last->line, "ot found") == NULL) &&
+                       (strstr(fileList.last->line, "o Such File") == NULL) &&
+                       (strstr(fileList.last->line, "ot Found") == NULL)
+
+               ) {
+                       /* Good.  We listed the item. */
+                       DisposeLineListContents(&fileList);
+                       DisposeLineListContents(&rootFileList);
+                       cip->NLSTfileParamWorks = kCommandAvailable;
+
+                       /* Don't forget to change back to the original directory. */
+                       (void) FTPChdir(cip, savedCwd);
+               } else {
+                       cip->NLSTfileParamWorks = kCommandNotAvailable;
+                       cip->errNo = result = kErrNLSTwithFileNotAvailable;
+                       DisposeLineListContents(&fileList);
+                       DisposeLineListContents(&rootFileList);
+                       (void) FTPChdir(cip, savedCwd);
+                       return (result);
+               }
+       }
+
+       /* Check the requested item. */
+       InitLineList(&fileList);
+       if (
+               ((FTPListToMemory2(cip, file, &fileList, "", 0, (int *) 0)) == kNoErr) &&
+               (fileList.nLines >= 1) &&
+               (strstr(fileList.last->line, "o such file") == NULL) &&
+               (strstr(fileList.last->line, "ot found") == NULL) &&
+               (strstr(fileList.last->line, "o Such File") == NULL) &&
+               (strstr(fileList.last->line, "ot Found") == NULL)
+
+       ) {
+               /* The item existed. */
+               result = kNoErr;
+       } else {
+               cip->errNo = kErrNLSTFailed;
+               result = kErrNLSTFailed;
+       }
+
+       DisposeLineListContents(&fileList);
+       return (result);
+}      /* FTPFileExistsNlst*/
+
+
+
+
+/* This functions goes to a great deal of trouble to try and determine if the
+ * remote file specified exists.  Newer servers support commands that make
+ * it relatively inexpensive to find the answer, but older servers do not
+ * provide a standard way.  This means we may try a whole bunch of things,
+ * but the good news is that the library saves information about which things
+ * worked so if you do this again it uses the methods that work.
+ */
+int
+FTPFileExists2(const FTPCIPtr cip, const char *const file, const int tryMDTM, const int trySIZE, const int tryMLST, const int trySTAT, const int tryNLST)
+{
+       int result;
+       time_t mdtm;
+       longest_int size;
+       MLstItem mlsInfo;
+
+       if (tryMDTM != 0) {
+               result = FTPFileModificationTime(cip, file, &mdtm);
+               if (result == kNoErr)
+                       return (kNoErr);
+               if (result == kErrMDTMFailed) {
+                       cip->errNo = kErrNoSuchFileOrDirectory;
+                       return (kErrNoSuchFileOrDirectory);
+               }
+               /* else keep going */   
+       }
+
+       if (trySIZE != 0) {
+               result = FTPFileSize(cip, file, &size, kTypeBinary);
+               if (result == kNoErr)
+                       return (kNoErr);
+               /* SIZE could fail if the server does
+                * not support it for directories.
+                *
+                * if (result == kErrSIZEFailed)
+                *      return (kErrNoSuchFileOrDirectory);
+                */
+               /* else keep going */   
+       }
+
+
+       if (tryMLST != 0) {
+               result = FTPMListOneFile(cip, file, &mlsInfo);
+               if (result == kNoErr)
+                       return (kNoErr);
+               if (result == kErrMLSTFailed) {
+                       cip->errNo = kErrNoSuchFileOrDirectory;
+                       return (kErrNoSuchFileOrDirectory);
+               }
+               /* else keep going */   
+       }
+
+       if (trySTAT != 0) {
+               result = FTPFileExistsStat(cip, file);
+               if (result == kNoErr)
+                       return (kNoErr);
+               if (result == kErrSTATFailed) {
+                       cip->errNo = kErrNoSuchFileOrDirectory;
+                       return (kErrNoSuchFileOrDirectory);
+               }
+               /* else keep going */   
+       }
+
+       if (tryNLST != 0) {
+               result = FTPFileExistsNlst(cip, file);
+               if (result == kNoErr)
+                       return (kNoErr);
+               if (result == kErrNLSTFailed) {
+                       cip->errNo = kErrNoSuchFileOrDirectory;
+                       return (kErrNoSuchFileOrDirectory);
+               }
+               /* else keep going */   
+       }
+
+       cip->errNo = kErrCantTellIfFileExists;
+       return (kErrCantTellIfFileExists);
+}      /* FTPFileExists2 */
+
+
+
+
+int
+FTPFileExists(const FTPCIPtr cip, const char *const file)
+{
+       return (FTPFileExists2(cip, file, 1, 1, 1, 1, 1));
+}      /* FTPFileExists */
+
+
+
+
+
+int
+FTPFileSizeAndModificationTime(const FTPCIPtr cip, const char *const file, longest_int *const size, const int type, time_t *const mdtm)
+{
+       MLstItem mlsInfo;
+       int result;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((mdtm == NULL) || (size == NULL) || (file == NULL))
+               return (kErrBadParameter);
+
+       *mdtm = kModTimeUnknown;
+       *size = kSizeUnknown;
+
+       result = FTPSetTransferType(cip, type);
+       if (result < 0)
+               return (result);
+
+       result = FTPMListOneFile(cip, file, &mlsInfo);
+       if (result < 0) {
+               /* Do it the regular way, where
+                * we do a SIZE and then a MDTM.
+                */
+               result = FTPFileSize(cip, file, size, type);
+               if (result < 0)
+                       return (result);
+               result = FTPFileModificationTime(cip, file, mdtm);
+               return (result);
+       } else {
+               *mdtm = mlsInfo.ftime;
+               *size = mlsInfo.fsize;
+       }
+
+       return (result);
+}      /* FTPFileSizeAndModificationTime */
+
+
+
+
+int
+FTPFileType(const FTPCIPtr cip, const char *const file, int *const ftype)
+{
+       int result;
+       MLstItem mlsInfo;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((file == NULL) || (file[0] == '\0')) {
+               cip->errNo = kErrBadParameter;
+               return (kErrBadParameter);
+       }
+
+       if (ftype == NULL) {
+               cip->errNo = kErrBadParameter;
+               return (kErrBadParameter);
+       }
+
+       *ftype = 0;
+       result = FTPMListOneFile(cip, file, &mlsInfo);
+       if (result == kNoErr) {
+               *ftype = mlsInfo.ftype;
+               return (kNoErr);
+       }
+
+       /* Preserve old working directory. */
+       (void) FTPGetCWD(cip, cip->buf, cip->bufSize);
+
+       result = FTPChdir(cip, file);
+       if (result == kNoErr) {
+               *ftype = 'd';
+               /* Yes it was a directory, now go back to
+                * where we were.
+                */
+               (void) FTPChdir(cip, cip->buf);
+
+               /* Note:  This improperly assumes that we
+                * will be able to chdir back, which is
+                * not guaranteed.
+                */
+               return (kNoErr);
+       }
+
+       result = FTPFileExists2(cip, file, 1, 1, 0, 1, 1);
+       if (result != kErrNoSuchFileOrDirectory)
+               result = kErrFileExistsButCannotDetermineType;
+
+       return (result);
+}      /* FTPFileType */
+
+
+
+
+int
+FTPIsDir(const FTPCIPtr cip, const char *const dir)
+{
+       int result, ftype;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((dir == NULL) || (dir[0] == '\0')) {
+               cip->errNo = kErrInvalidDirParam;
+               return (kErrInvalidDirParam);
+       }
+
+       result = FTPFileType(cip, dir, &ftype);
+       if ((result == kNoErr) || (result == kErrFileExistsButCannotDetermineType)) {
+               result = 0;
+               if (ftype == 'd')
+                       result = 1;
+       }
+       return (result);
+}      /* FTPIsDir */
+
+
+
+
+int
+FTPIsRegularFile(const FTPCIPtr cip, const char *const file)
+{
+       int result, ftype;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if ((file == NULL) || (file[0] == '\0')) {
+               cip->errNo = kErrBadParameter;
+               return (kErrBadParameter);
+       }
+
+       result = FTPFileType(cip, file, &ftype);
+       if ((result == kNoErr) || (result == kErrFileExistsButCannotDetermineType)) {
+               result = 1;
+               if (ftype == 'd')
+                       result = 0;
+       }
+       return (result);
+}      /* FTPIsRegularFile */
+
+
+
+
+int
+FTPSymlink(const FTPCIPtr cip, const char *const lfrom, const char *const lto)
+{
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+       if ((cip == NULL) || (lfrom == NULL) || (lto == NULL))
+               return (kErrBadParameter);
+       if ((lfrom[0] == '\0') || (lto[0] == '\0'))
+               return (kErrBadParameter);
+       if (FTPCmd(cip, "SITE SYMLINK %s %s", lfrom, lto) == 2)
+               return (kNoErr);
+       return (kErrSYMLINKFailed);
+}      /* FTPSymlink */
+
+
+
+
+int
+FTPUmask(const FTPCIPtr cip, const char *const umsk)
+{
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+       if ((umsk == NULL) || (umsk[0] == '\0'))
+               return (kErrBadParameter);
+       if (FTPCmd(cip, "SITE UMASK %s", umsk) == 2)
+               return (kNoErr);
+       return (kErrUmaskFailed);
+}      /* FTPUmask */
+
+
+
+
+static void
+GmTimeStr(char *const dst, const size_t dstsize, time_t t)
+{
+       char buf[64];
+       struct tm *gtp;
+
+       gtp = gmtime(&t);
+       if (gtp == NULL) {
+               dst[0] = '\0';
+       } else {
+#ifdef HAVE_SNPRINTF
+               buf[sizeof(buf) - 1] = '\0';
+               (void) snprintf(buf, sizeof(buf) - 1, "%04d%02d%02d%02d%02d%02d",
+#else
+               (void) sprintf(buf, "%04d%02d%02d%02d%02d%02d",
+#endif
+                       gtp->tm_year + 1900,
+                       gtp->tm_mon + 1,
+                       gtp->tm_mday,
+                       gtp->tm_hour,
+                       gtp->tm_min,
+                       gtp->tm_sec
+               );
+               (void) Strncpy(dst, buf, dstsize);
+       }
+}      /* GmTimeStr */
+
+
+
+
+int
+FTPUtime(const FTPCIPtr cip, const char *const file, time_t actime, time_t modtime, time_t crtime)
+{
+       char mstr[64], astr[64], cstr[64];
+       int result;
+       ResponsePtr rp;
+
+       if (cip == NULL)
+               return (kErrBadParameter);
+       if (strcmp(cip->magic, kLibraryMagic))
+               return (kErrBadMagic);
+
+       if (cip->hasUTIME == kCommandNotAvailable) {
+               cip->errNo = kErrUTIMENotAvailable;
+               result = kErrUTIMENotAvailable;
+       } else {
+               if ((actime == (time_t) 0) || (actime == (time_t) -1))
+                       (void) time(&actime);
+               if ((modtime == (time_t) 0) || (modtime == (time_t) -1))
+                       (void) time(&modtime);
+               if ((crtime == (time_t) 0) || (crtime == (time_t) -1))
+                       crtime = modtime;
+
+               (void) GmTimeStr(astr, sizeof(astr), actime);
+               (void) GmTimeStr(mstr, sizeof(mstr), modtime);
+               (void) GmTimeStr(cstr, sizeof(cstr), crtime);
+
+               rp = InitResponse();
+               if (rp == NULL) {
+                       result = kErrMallocFailed;
+                       cip->errNo = kErrMallocFailed;
+                       Error(cip, kDontPerror, "Malloc failed.\n");
+               } else {
+                       result = RCmd(cip, rp, "SITE UTIME %s %s %s %s UTC", file, astr, mstr, cstr);   
+                       if (result < 0) {
+                               DoneWithResponse(cip, rp);
+                               return (result);
+                       } else if (result == 2) {
+                               cip->hasUTIME = kCommandAvailable;
+                               result = kNoErr;
+                       } else if (UNIMPLEMENTED_CMD(rp->code)) {
+                               cip->hasUTIME = kCommandNotAvailable;
+                               cip->errNo = kErrUTIMENotAvailable;
+                               result = kErrUTIMENotAvailable;
+                       } else {
+                               cip->errNo = kErrUTIMEFailed;
+                               result = kErrUTIMEFailed;
+                       }
+                       DoneWithResponse(cip, rp);
+               }
+       }
+       return (result);
+}      /* FTPUtime */
diff --git a/rosapps/net/ncftp/libncftp/config.h.in b/rosapps/net/ncftp/libncftp/config.h.in
new file mode 100644 (file)
index 0000000..3335191
--- /dev/null
@@ -0,0 +1,207 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+#undef CAN_USE_SYS_SELECT_H
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef gid_t
+
+/* Define if your compiler supports the "long long" integral type. */
+#undef HAVE_LONG_LONG
+
+/* Define if you have a _res global variable used by resolve routines. */
+#undef HAVE__RES_DEFDNAME
+
+/* Define if you have sigsetjmp and siglongjmp. */
+#undef HAVE_SIGSETJMP
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef mode_t
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef pid_t
+
+/* Format string for the printf() family for 64 bit integers. */
+#undef PRINTF_LONG_LONG
+
+/* Define if printing a "long long" with "%lld" works . */
+#undef PRINTF_LONG_LONG_LLD
+
+/* Define if printing a "long long" with "%qd" works . */
+#undef PRINTF_LONG_LONG_QD
+
+/* Format string for the scanf() family for 64 bit integers. */
+#undef SCANF_LONG_LONG
+
+/* Define if scanning a "long long" with "%lld" works. */
+#undef SCANF_LONG_LONG_LLD
+
+/* Define if scanning a "long long" with "%qd" works. */
+#undef SCANF_LONG_LONG_QD
+
+  
+/* Define to the type of arg1 for select(). */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for select(). */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg5 for select(). */
+#undef SELECT_TYPE_ARG5
+
+/* Define if the setvbuf function takes the buffering type as its second
+   argument and the buffer pointer as the third, as on System V
+   before release 3.  */
+#undef SETVBUF_REVERSED
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define to the full path of the Tar program, if you have it. */
+#undef TAR
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef uid_t
+
+/* Result of "uname -a" */
+#undef UNAME
+
+/* Define if you have the fstat64 function.  */
+#undef HAVE_FSTAT64
+
+/* Define if you have the getcwd function.  */
+#undef HAVE_GETCWD
+
+/* Define if you have the getdomainname function.  */
+#undef HAVE_GETDOMAINNAME
+
+/* Define if you have the gethostname function.  */
+#undef HAVE_GETHOSTNAME
+
+/* Define if you have the getpass function.  */
+#undef HAVE_GETPASS
+
+/* Define if you have the getwd function.  */
+#undef HAVE_GETWD
+
+/* Define if you have the inet_ntop function.  */
+#undef HAVE_INET_NTOP
+
+/* Define if you have the llseek function.  */
+#undef HAVE_LLSEEK
+
+/* Define if you have the lseek64 function.  */
+#undef HAVE_LSEEK64
+
+/* Define if you have the lstat64 function.  */
+#undef HAVE_LSTAT64
+
+/* Define if you have the mktime function.  */
+#undef HAVE_MKTIME
+
+/* Define if you have the open64 function.  */
+#undef HAVE_OPEN64
+
+/* Define if you have the res_init function.  */
+#undef HAVE_RES_INIT
+
+/* Define if you have the sigaction function.  */
+#undef HAVE_SIGACTION
+
+/* Define if you have the snprintf function.  */
+#undef HAVE_SNPRINTF
+
+/* Define if you have the socket function.  */
+#undef HAVE_SOCKET
+
+/* Define if you have the stat64 function.  */
+#undef HAVE_STAT64
+
+/* Define if you have the strcasecmp function.  */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strerror function.  */
+#undef HAVE_STRERROR
+
+/* Define if you have the strstr function.  */
+#undef HAVE_STRSTR
+
+/* Define if you have the strtoq function.  */
+#undef HAVE_STRTOQ
+
+/* Define if you have the symlink function.  */
+#undef HAVE_SYMLINK
+
+/* Define if you have the vsnprintf function.  */
+#undef HAVE_VSNPRINTF
+
+/* Define if you have the waitpid function.  */
+#undef HAVE_WAITPID
+
+/* Define if you have the <arpa/nameser.h> header file.  */
+#undef HAVE_ARPA_NAMESER_H
+
+/* Define if you have the <nserve.h> header file.  */
+#undef HAVE_NSERVE_H
+
+/* Define if you have the <resolv.h> header file.  */
+#undef HAVE_RESOLV_H
+
+/* Define if you have the <sys/select.h> header file.  */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <utime.h> header file.  */
+#undef HAVE_UTIME_H
+
+/* Define if you have the 44bsd library (-l44bsd).  */
+#undef HAVE_LIB44BSD
+
+/* Define if you have the com_err library (-lcom_err).  */
+#undef HAVE_LIBCOM_ERR
+
+/* Define if you have the crypto library (-lcrypto).  */
+#undef HAVE_LIBCRYPTO
+
+/* Define if you have the db library (-ldb).  */
+#undef HAVE_LIBDB
+
+/* Define if you have the gen library (-lgen).  */
+#undef HAVE_LIBGEN
+
+/* Define if you have the gssapi_krb5 library (-lgssapi_krb5).  */
+#undef HAVE_LIBGSSAPI_KRB5
+
+/* Define if you have the isode library (-lisode).  */
+#undef HAVE_LIBISODE
+
+/* Define if you have the krb5 library (-lkrb5).  */
+#undef HAVE_LIBKRB5
+
+/* Define if you have the nsl library (-lnsl).  */
+#undef HAVE_LIBNSL
+
+/* Define if you have the resolv library (-lresolv).  */
+#undef HAVE_LIBRESOLV
+
+/* Define if you have the socket library (-lsocket).  */
+#undef HAVE_LIBSOCKET
+
+/* Define if you have the socks5 library (-lsocks5).  */
+#undef HAVE_LIBSOCKS5
diff --git a/rosapps/net/ncftp/libncftp/configure.in b/rosapps/net/ncftp/libncftp/configure.in
new file mode 100644 (file)
index 0000000..778db85
--- /dev/null
@@ -0,0 +1,292 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(rcmd.c)
+AC_PREREQ(2.4)
+AC_CONFIG_HEADER(config.h)
+
+nc_cv_socks5=no
+no_signals=yes
+
+AC_ARG_ENABLE(socks5,[  --enable-socks5        try to find and use the socks5 library],nc_cv_socks5=yes,nc_cv_socks5=no)
+AC_ARG_ENABLE(signals,[  --enable-signals       allow use of signal handling],[no_signals=no])
+
+
+wi_OS_VAR
+
+changequote(<<, >>)dnl
+MAINDIR=`pwd`
+if test -f "$MAINDIR/dos2unix.sh" ; then
+       chmod u+rwx $MAINDIR/dos2unix.sh
+       for dir in . ../sio ../Strn ; do
+               if [ -d "$dir" ] ; then
+                       dir=`cd "$dir" ; pwd`
+                       find "$dir" -name '*.in' -exec "$MAINDIR/dos2unix.sh" {} \;
+                       find "$dir" -name '*.h' -exec "$MAINDIR/dos2unix.sh" {} \;
+                       find "$dir" -name '*.c' -exec "$MAINDIR/dos2unix.sh" {} \;
+               fi
+       done
+fi
+MAKE=make
+STATIC=""
+BDYNAMIC="# -Wl,-Bdynamic"
+BSTATIC="# -Wl,-Bstatic"
+LIBSET='$(LIB)'
+Z31=''
+Z32=''
+Z33=''
+Z34=''
+REDWING='no'
+SFLAG='-s'
+
+case "$host" in
+       redwing*)       CC=cc
+                       LDFLAGS=''
+                       STATIC=''
+                       Z31='   -@mv $(STGZFILE) newbin/'
+                       Z32='   -@mv $(DTGZFILE) newbin/'
+                       Z33='   -@mv $(MTGZFILE) newbin/'
+                       Z34='   -@mv $(PTGZFILE) newbin/'
+                       REDWING='yes'
+                       ;;
+esac
+
+case "$os" in
+       linux)
+               BDYNAMIC="-Wl,-Bdynamic"
+               BSTATIC="-Wl,-Bstatic"
+               if [ "$MAKEWORLD_SH" = "" ] ; then
+                       LIBSET='$(LIBSO) $(LIB)'
+               fi
+               ;;
+       freebsd)
+               BDYNAMIC="-Wl,-Bdynamic"
+               BSTATIC="-Wl,-Bstatic"
+               ;;
+       macosx*|rhapsody)
+               SFLAG='-Wl,-x'
+               ;;
+esac
+
+changequote([, ])dnl
+
+AC_SUBST(CC)
+AC_SUBST(CFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
+AC_SUBST(STATIC)
+AC_SUBST(SFLAG)
+AC_SUBST(LIBS)
+AC_SUBST(DEFS)
+AC_SUBST(MAKE)
+AC_SUBST(Z31)
+AC_SUBST(Z32)
+AC_SUBST(Z33)
+AC_SUBST(Z34)
+AC_SUBST(LIBSET)
+AC_SUBST(BDYNAMIC)
+AC_SUBST(BSTATIC)
+AC_SUBST(MAINDIR)
+
+if test -f ./samples/ncftpput2probe.c ; then
+       PROBE="ncftpget2probe ncftpput2probe"
+else
+       PROBE=""
+fi
+AC_SUBST(PROBE)
+
+AC_PROG_CC
+wi_REQUEST_NO_Y2K_WARNINGS
+wi_CFLAGS_LFS64
+wi_DEFINE_UNAME
+
+if test -f /usr/src/include/eos.h ; then
+       if test "$REDWING" = no ; then
+               prefix=/usr/src
+       fi
+fi
+
+if test "$wi_cv_prototypes" = no ; then
+       AC_WARN([Your compiler is probably won't be able to compile the package.])
+       AC_WARN([Get gcc, or any compiler that supports function prototypes.])
+fi
+
+dnl # See if we should add -I/usr/local/include -L/usr/local/lib, etc.
+dnl wi_EXTRA_DIRS(yes, /usr/local /usr/ccs, -)
+
+dnl For the sample programs.
+wi_NET_LIBS
+
+if test "$nc_cv_socks5" = yes ; then
+# Look for the "SOCKS" library for use with Firewalls/Gateways.
+savelibs="$LIBS"
+AC_CHECK_LIB(db,          main)
+AC_CHECK_LIB(isode,       main)
+AC_CHECK_LIB(com_err,     main)
+AC_CHECK_LIB(crypto,      main)
+AC_CHECK_LIB(krb5,        main)
+AC_CHECK_LIB(gssapi_krb5, main)
+AC_CHECK_LIB(socks5,SOCKSinit)
+      if test "$ac_cv_lib_socks5" = yes ; then
+              nc_cv_socks=no
+      else
+              LIBS="$savelibs"
+      fi
+else
+ac_cv_lib_socks5=no
+fi
+
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(sys/time.h unistd.h utime.h nserve.h resolv.h arpa/nameser.h)
+AC_TIME_WITH_SYS_TIME
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_TYPE_OFF_T
+AC_TYPE_MODE_T
+AC_TYPE_PID_T
+AC_TYPE_UID_T
+wi__RES_DEFDNAME
+wi_USE_LONG_LONG
+
+dnl Checks for library functions.
+if test "$SYS" != sunos ; then
+       # Use getwd on SunOS -- getcwd does a "popen("/bin/pwd")" -- aaaccck.
+       #
+       AC_CHECK_FUNCS(getcwd)
+fi
+AC_CHECK_FUNCS(getwd gethostname socket strerror strstr)
+AC_CHECK_FUNCS(getpass strcasecmp getdomainname mktime symlink inet_ntop)
+AC_CHECK_FUNCS(res_init snprintf vsnprintf strtoq sigaction waitpid)
+AC_CHECK_FUNCS(open64 stat64 fstat64 lstat64 lseek64 llseek)
+wi_FUNC_SIGSETJMP
+AC_FUNC_SETVBUF_REVERSED
+
+wi_HEADER_SYS_SELECT_H
+AC_FUNC_SELECT_ARGTYPES
+
+if test -f ../sio/sio.h ; then
+       ldir=`cd ../sio ; pwd`
+       LDFLAGS="$LDFLAGS -L${ldir}"
+       CPPFLAGS="$CPPFLAGS -I${ldir}"
+       LIBS="$LIBS -lsio"
+fi
+
+if test -f ../Strn/Strn.h ; then
+       ldir=`cd ../Strn ; pwd`
+       LDFLAGS="$LDFLAGS -L${ldir}"
+       CPPFLAGS="$CPPFLAGS -I${ldir}"
+       LIBS="$LIBS -lStrn"
+fi
+
+if test $ac_cv_func_getcwd = no && test $ac_cv_func_getwd = no ; then
+AC_WARN(This system does not have either getwd or getcwd?)
+AC_WARN(I find that a little hard to believe.)
+AC_WARN(You may want to try -DHAVE_GETWD anyway.)
+AC_WARN([
+This could also mean that your compiler isn't working])
+AC_WARN(with this configure script.  Check the ./config.log)
+AC_WARN(and look for anomalies.)
+fi
+
+wi_PROG_TAR
+AC_PROG_RANLIB
+
+if test "$LONGEST_INT" = "long long" ; then
+       if sed 's/^#define longest_int.*/#define longest_int long long/;
+s/^#define longest_uint.*/#define longest_uint unsigned long long/' ncftp.h > temp.h ; then
+               mv temp.h ncftp.h
+               chmod a+r ncftp.h
+       fi
+else
+       if sed 's/^#define longest_int.*/#define longest_int long/;
+s/^#define longest_uint.*/#define longest_uint unsigned long/' ncftp.h > temp.h ; then
+               mv temp.h ncftp.h
+               chmod a+r ncftp.h
+       fi
+fi
+
+CPPFLAGS="-I$MAINDIR $CPPFLAGS"
+
+if test "$no_signals" = no ; then
+       dv1='#  if 0'
+       dv2='#if 0'
+else
+       dv1='#  if 1'
+       dv2='#if 1'
+fi
+
+if sed "s!^.*/. %config1!${dv1} /* %config1!;s!^.*/. %config2!${dv2} /* %config2!" ncftp.h > temp.h ; then
+       mv temp.h ncftp.h
+       chmod a+r ncftp.h
+fi
+
+if sed "s!^.*/. %config1!${dv1} /* %config1!;s!^.*/. %config2!${dv2} /* %config2!" syshdrs.h > temp.h ; then
+       mv temp.h syshdrs.h
+       chmod a+r syshdrs.h
+fi
+
+changequote(<<, >>)dnl
+#
+# Configure sio specially, like it would do.
+#
+if [ -d ../sio ] ; then
+       if sed "s!^.*/. %config1!${dv1} /* %config1!;s!^.*/. %config2!${dv2} /* %config2!" ../sio/sio.h > temp.h ; then
+               mv temp.h ../sio/sio.h
+               chmod a+r ../sio/sio.h
+       fi
+       if sed "s!^.*/. %config1!${dv1} /* %config1!;s!^.*/. %config2!${dv2} /* %config2!" ../sio/usio.h > temp.h ; then
+               mv temp.h ../sio/usio.h
+               chmod a+r ../sio/usio.h
+       fi
+
+       patterns1=""
+       patterns2=""
+       if [ "$SYS" = solaris ] ; then
+               patterns1='s!/. %configure%.*!#define SAccept SAcceptS!'
+               patterns2='s!/. %configure%.*!#define UAccept UAcceptS!'
+       fi
+
+       if [ "$patterns1" != "" ] ; then
+               sed "$patterns1" < ../sio/sio.h > tmpfile
+               if [ $? -eq 0 ] ; then
+                       mv tmpfile ../sio/sio.h
+                       chmod 644 ../sio/sio.h
+               else
+                       /bin/rm tmpfile
+               fi
+       fi
+
+       if [ "$patterns2" != "" ] ; then
+               sed "$patterns2" < ../sio/usio.h > tmpfile
+               if [ $? -eq 0 ] ; then
+                       mv tmpfile ../sio/usio.h
+                       chmod 644 ../sio/usio.h
+               else
+                       /bin/rm tmpfile
+               fi
+       fi
+fi
+changequote([, ])dnl
+
+if test -d bin.only ; then
+       binonly="bin.only/Makefile bin.only/samples/Makefile"
+else
+       binonly=""
+fi
+
+LIBS=`echo "$LIBS" | sed 's/^ *//;s/ *$//;s/  */ /g'`
+LDFLAGS=`echo "$LDFLAGS" | sed 's/^ *//;s/ *$//;s/  */ /g'`
+CPPFLAGS=`echo "$CPPFLAGS" | sed 's/^ *//;s/ *$//;s/  */ /g'`
+CFLAGS=`echo "$CFLAGS" | sed 's/^ *//;s/ *$//;s/  */ /g'`
+DEFS=`echo "$DEFS" | sed 's/^ *//;s/ *$//;s/  */ /g'`
+
+samples=''
+for sample in minincftp monkey ncftpget ncftpput ncftpls simpleget ncftpsyncput misc ; do
+       if test -f samples/$sample/Makefile.in ; then
+               samples="$samples samples/$sample/Makefile"
+       fi
+done
+
+AC_OUTPUT([Makefile ../Strn/Makefile ../sio/Makefile $samples $binonly])
diff --git a/rosapps/net/ncftp/libncftp/dos2unix.sh b/rosapps/net/ncftp/libncftp/dos2unix.sh
new file mode 100644 (file)
index 0000000..0959d5e
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+es=1
+if [ $# -eq 0 ] ; then
+       exec tr -d '\015\032'
+elif [ ! -f "$1" ] ; then
+       echo "Not found: $1" 1>&2
+else
+       for f in "$@" ; do
+               if tr -d '\015\032' < "$f" > "$f.tmp" ; then
+                       if cmp "$f" "$f.tmp" > /dev/null ; then
+                               rm -f "$f.tmp"
+                       else
+                               touch -r "$f" "$f.tmp"
+                               if mv "$f" "$f.bak" ; then
+                                       if mv "$f.tmp" "$f" ; then
+                                               rm -f "$f.bak"
+                                               es=$?
+                                               echo "  converted $f"
+                                       else
+                                               rm -f "$f.tmp"
+                                       fi
+                               else
+                                       rm -f "$f.tmp"
+                               fi
+                       fi
+               else
+                       rm -f "$f.tmp"
+               fi
+       done
+fi
+
+exit $es
diff --git a/rosapps/net/ncftp/libncftp/errno.c b/rosapps/net/ncftp/libncftp/errno.c
new file mode 100644 (file)
index 0000000..2d40a9d
--- /dev/null
@@ -0,0 +1,163 @@
+/* errno.c
+ *
+ * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
+ * All rights reserved.
+ *
+ */
+
+#define _libncftp_errno_c_ 1
+#include "syshdrs.h"
+       
+static const char *gErrList[kErrLast - kErrFirst + 2] = {
+       "gethostname() failed",                                         /* -100 */
+       "hostname does not include domain name",                        /* -101 */
+       "could not set linger mode",                                    /* -102 */
+       "could not set type of service",                                /* -103 */
+       "could not enable out-of-band data inline",                     /* -104 */
+       "unknown host",                                                 /* -105 */
+       "could not get a new stream socket",                            /* -106 */
+       "could not duplicate a socket",                                 /* -107 */
+       "fdopen for reading failed",                                    /* -108 */
+       "fdopen for writing failed",                                    /* -109 */
+       "getsockname failed",                                           /* -110 */
+       "could not bind the data socket",                               /* -111 */
+       "could not listen on the data socket",                          /* -112 */
+       "passive mode failed",                                          /* -113 */
+       "server sent bogus port number",                                /* -114 */
+       "could not connect data socket",                                /* -115 */
+       "could not accept data socket",                                 /* -116 */
+       "could not set restart point",                                  /* -117 */
+       "could not connect to remote host",                             /* -118 */
+       "could not connect to remote host, but can try again",          /* -119 */
+       "remote host refused connection",                               /* -120 */
+       "bad transfer type",                                            /* -121 */
+       "invalid directory parameter",                                  /* -122 */
+       "malloc failed",                                                /* -123 */
+       "PWD failed",                                                   /* -124 */
+       "remote chdir failed",                                          /* -125 */
+       "remote rmdir failed",                                          /* -126 */
+       "bad line list",                                                /* -127 */
+       "unimplemented option",                                         /* -128 */
+       "unimplemented function",                                       /* -129 */
+       "remote directory listing failed",                              /* -130 */
+       "could not retrieve remote file",                               /* -131 */
+       "could not send file to remote host",                           /* -132 */
+       "file write error",                                             /* -133 */
+       "file read error",                                              /* -134 */
+       "socket write error",                                           /* -135 */
+       "socket read error",                                            /* -136 */
+       "could not open file",                                          /* -137 */
+       "bad magic number in FTP library structure",                    /* -138 */
+       "bad parameter given to library",                               /* -139 */
+       "remote mkdir failed",                                          /* -140 */
+       "remote cd .. failed",                                          /* -141 */
+       "remote chmod failed",                                          /* -142 */
+       "remote umask failed",                                          /* -143 */
+       "remote delete failed",                                         /* -144 */
+       "remote file size inquiry failed",                              /* -145 */
+       "remote file timestamp inquiry failed",                         /* -146 */
+       "remote transfer type change failed",                           /* -147 */
+       "file size inquiries not understood by remote server",          /* -148 */
+       "file timestamp inquiries not understood by remote server",     /* -149 */
+       "could not rename remote file",                                 /* -150 */
+       "could not do remote wildcard expansion",                       /* -151 */
+       "could not set keepalive option",                               /* -152 */
+       "remote host disconnected during login",                        /* -153 */
+       "username was not accepted for login",                          /* -154 */
+       "username and/or password was not accepted for login",          /* -155 */
+       "login failed",                                                 /* -156 */
+       "invalid reply from server",                                    /* -157 */
+       "remote host closed control connection",                        /* -158 */
+       "not connected",                                                /* -159 */
+       "could not start data transfer",                                /* -160 */
+       "data transfer failed",                                         /* -161 */
+       "PORT failed",                                                  /* -162 */
+       "PASV failed",                                                  /* -163 */
+       "UTIME failed",                                                 /* -164 */
+       "utime requests not understood by remote server",               /* -165 */
+       "HELP failed",                                                  /* -166 */
+       "file deletion on local host failed",                           /* -167 */
+       "lseek failed",                                                 /* -168 */
+       "data transfer aborted by local user",                          /* -169 */
+       "SYMLINK failed",                                               /* -170 */
+       "symlink requests not understood by remote server",             /* -171 */
+       "no match",                                                     /* -172 */
+       "server features request failed",                               /* -173 */
+       "no valid files were specified",                                /* -174 */
+       "file transfer buffer has not been allocated",                  /* -175 */
+       "will not overwrite local file with older remote file",         /* -176 */
+       "will not overwrite remote file with older local file",         /* -177 */
+       "local file appears to be the same as the remote file, no transfer necessary",  /* -178 */
+       "could not get extended directory information (MLSD)",          /* -179 */
+       "could not get extended file or directory information (MLST)",  /* -180 */
+       "could not parse extended file or directory information",       /* -181 */
+       "server does not support extended file or directory information",       /* -182 */
+       "server does not support extended directory information",       /* -183 */
+       "could not get information about specified file",               /* -184 */
+       "server does not support file or directory information",        /* -185 */
+       "could not get directory information about specified file",     /* -186 */
+       "server does not support directory information",                /* -187 */
+       "no such file or directory",                                    /* -188 */
+       "server provides no way to determine file existence",           /* -189 */
+       "item exists, but cannot tell if it is a file or directory",    /* -190 */
+       "not a directory",                                              /* -191 */
+       "directory recursion limit reached",                            /* -192 */
+       "timed out while waiting for server response",                  /* -193 */
+       "data transfer timed out",                                      /* -194 */
+       "canceled by user",                                             /* -195 */
+       NULL,                                                           
+};
+
+int gLibNcFTP_Uses_Me_To_Quiet_Variable_Unused_Warnings = 0;
+
+const char *
+FTPStrError(int e)
+{
+       if (e == kErrGeneric) {
+               return ("miscellaneous error");
+       } else if (e == kNoErr) {
+               return ("no error");
+       } else {
+               if (e < 0)
+                       e = -e;
+               if ((e >= kErrFirst) && (e <= kErrLast)) {
+                       return (gErrList[e - kErrFirst]);
+               }
+       }
+       return ("unrecognized error number");
+}      /* FTPStrError */
+
+
+
+
+void
+FTPPerror(const FTPCIPtr cip, const int err, const int eerr, const char *const s1, const char *const s2)
+{
+       if (err != kNoErr) {
+               if (err == eerr) {
+                       if ((s2 == NULL) || (s2[0] == '\0')) {
+                               if ((s1 == NULL) || (s1[0] == '\0')) { 
+                                       (void) fprintf(stderr, "server said: %s\n", cip->lastFTPCmdResultStr);
+                               } else {
+                                       (void) fprintf(stderr, "%s: server said: %s\n", s1, cip->lastFTPCmdResultStr);
+                               }
+                       } else if ((s1 == NULL) || (s1[0] == '\0')) { 
+                               (void) fprintf(stderr, "%s: server said: %s\n", s2, cip->lastFTPCmdResultStr);
+                       } else {
+                               (void) fprintf(stderr, "%s %s: server said: %s\n", s1, s2, cip->lastFTPCmdResultStr);
+                       }
+               } else {
+                       if ((s2 == NULL) || (s2[0] == '\0')) {
+                               if ((s1 == NULL) || (s1[0] == '\0')) { 
+                                       (void) fprintf(stderr, "%s.\n", FTPStrError(cip->errNo));
+                               } else {
+                                       (void) fprintf(stderr, "%s: %s.\n", s1, FTPStrError(cip->errNo));
+                               }
+                       } else if ((s1 == NULL) || (s1[0] == '\0')) { 
+                               (void) fprintf(stderr, "%s: %s.\n", s2, FTPStrError(cip->errNo));
+                       } else {
+                               (void) fprintf(stderr, "%s %s: %s.\n", s1, s2, FTPStrError(cip->errNo));
+                       }
+               }
+       }
+}      /* FTPPerror */
diff --git a/rosapps/net/ncftp/libncftp/ftp.c b/rosapps/net/ncftp/libncftp/ftp.c
new file mode 100644 (file)
index 0000000..ca1e484
--- /dev/null
@@ -0,0 +1,1362 @@
+/* ftp.c
+ *
+ * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
+ * All rights reserved.
+ *
+ */
+
+#define _libncftp_ftp_c_
+#include "syshdrs.h"
+
+char gLibNcFTPVersion[64] = kLibraryVersion;
+
+#ifdef NO_SIGNALS
+static char gNoSignalsMarker[] = "@(#) LibNcFTP - NO_SIGNALS";
+#else
+
+static int gGotSig = 0;
+#ifdef HAVE_SIGSETJMP
+static sigjmp_buf gCancelConnectJmp;
+#else
+static jmp_buf gCancelConnectJmp;
+#endif /* HAVE_SIGSETJMP */
+
+#endif /* NO_SIGNALS */
+
+
+#ifndef lint
+static char gCopyright[] = "@(#) LibNcFTP Copyright 1995-2000, by Mike Gleason.  All rights reserved.";
+#endif
+
+#ifdef HAVE_LIBSOCKS5
+#      define SOCKS 5
+#      include <socks.h>
+#else
+#      ifdef HAVE_LIBSOCKS
+#              define accept           Raccept
+#              define connect          Rconnect
+#              define getsockname      Rgetsockname
+#              define listen           Rlisten
+#      endif
+#endif
+
+
+
+
+/* On entry, you should have 'host' be set to a symbolic name (like
+ * cse.unl.edu), or set to a numeric address (like 129.93.3.1).
+ * If the function fails, it will return NULL, but if the host was
+ * a numeric style address, you'll have the ip_address to fall back on.
+ */
+
+static struct hostent *
+GetHostEntry(char *host, struct in_addr *ip_address)
+{
+       struct in_addr ip;
+       struct hostent *hp;
+       
+       /* See if the host was given in the dotted IP format, like "36.44.0.2."
+        * If it was, inet_addr will convert that to a 32-bit binary value;
+        * it not, inet_addr will return (-1L).
+        */
+       ip.s_addr = inet_addr(host);
+       if (ip.s_addr != INADDR_NONE) {
+               hp = NULL;
+       } else {
+               /* No IP address, so it must be a hostname, like ftp.wustl.edu. */
+               hp = gethostbyname(host);
+               if (hp != NULL)
+                       (void) memcpy(&ip.s_addr, hp->h_addr_list[0], (size_t) hp->h_length);
+       }
+       if (ip_address != NULL)
+               *ip_address = ip;
+       return (hp);
+}      /* GetHostEntry */
+
+
+
+
+/* Makes every effort to return a fully qualified domain name. */
+int
+GetOurHostName(char *host, size_t siz)
+{
+#ifdef HOSTNAME
+       /* You can hardcode in the name if this routine doesn't work
+        * the way you want it to.
+        */
+       Strncpy(host, HOSTNAME, siz);
+       return (1);             /* Success */
+#else
+       struct hostent *hp;
+       int result;
+       char **curAlias;
+       char domain[64];
+       char *cp;
+       int rc;
+
+       host[0] = '\0';
+       result = gethostname(host, (int) siz);
+       if ((result < 0) || (host[0] == '\0')) {
+               return (-1);
+       }
+
+       if (strchr(host, '.') != NULL) {
+               /* gethostname returned full name (like "cse.unl.edu"), instead
+                * of just the node name (like "cse").
+                */
+               return (2);             /* Success */
+       }
+       
+       hp = gethostbyname(host);
+       if (hp != NULL) {
+               /* Maybe the host entry has the full name. */
+               cp = strchr((char *) hp->h_name, '.');
+               if ((cp != NULL) && (cp[1] != '\0')) {
+                       /* The 'name' field for the host entry had full name. */
+                       (void) Strncpy(host, (char *) hp->h_name, siz);
+                       return (3);             /* Success */
+               }
+
+               /* Now try the list of aliases, to see if any of those look real. */
+               for (curAlias = hp->h_aliases; *curAlias != NULL; curAlias++) {
+                       cp = strchr(*curAlias, '.');
+                       if ((cp != NULL) && (cp[1] != '\0')) {
+                               (void) Strncpy(host, *curAlias, siz);
+                               return (4);             /* Success */
+                       }
+               }
+       }
+
+       /* Otherwise, we just have the node name.  See if we can get the
+        * domain name ourselves.
+        */
+#ifdef DOMAINNAME
+       (void) STRNCPY(domain, DOMAINNAME);
+       rc = 5;
+#else
+       rc = -1;
+       domain[0] = '\0';
+#      if defined(HAVE_RES_INIT) && defined(HAVE__RES_DEFDNAME)
+       if (domain[0] == '\0') {
+               (void) res_init();
+               if ((_res.defdname != NULL) && (_res.defdname[0] != '\0')) {
+                       (void) STRNCPY(domain, _res.defdname);
+                       rc = 6;
+               }
+       }
+#      endif   /* HAVE_RES_INIT && HAVE__RES_DEFDNAME */
+       
+       if (domain[0] == '\0') {
+               FILE *fp;
+               char line[256];
+               char *tok;
+
+               fp = fopen("/etc/resolv.conf", "r");
+               if (fp != NULL) {
+                       (void) memset(line, 0, sizeof(line));
+                       while (fgets(line, sizeof(line) - 1, fp) != NULL) {
+                               if (!isalpha((int) line[0]))
+                                       continue;       /* Skip comment lines. */
+                               tok = strtok(line, " \t\n\r");
+                               if (tok == NULL)
+                                       continue;       /* Impossible */
+                               if (strcmp(tok, "domain") == 0) {
+                                       tok = strtok(NULL, " \t\n\r");
+                                       if (tok == NULL)
+                                               continue;       /* syntax error */
+                                       (void) STRNCPY(domain, tok);
+                                       rc = 7;
+                                       break;  /* Done. */
+                               }
+                       }
+                       (void) fclose(fp);
+               }
+       }
+#endif /* DOMAINNAME */
+
+       if (domain[0] != '\0') {
+               /* Supposedly, it's legal for a domain name with
+                * a period at the end.
+                */
+               cp = domain + strlen(domain) - 1;
+               if (*cp == '.')
+                       *cp = '\0';
+               if (domain[0] != '.')
+                       (void) Strncat(host, ".", siz);
+               (void) Strncat(host, domain, siz);
+       }
+       if (rc < 0)
+               host[0] = '\0';
+       return(rc);     /* Success */
+#endif /* !HOSTNAME */
+}      /* GetOurHostName */
+
+
+
+void
+CloseControlConnection(const FTPCIPtr cip)
+{
+       /* This will close each file, if it was open. */
+#ifdef NO_SIGNALS
+       SClose(cip->ctrlSocketR, 3);
+       cip->ctrlSocketR = kClosedFileDescriptor;
+       cip->ctrlSocketW = kClosedFileDescriptor;
+       DisposeSReadlineInfo(&cip->ctrlSrl);
+#else  /* NO_SIGNALS */
+       if (cip->ctrlTimeout > 0)
+               (void) alarm(cip->ctrlTimeout);
+       CloseFile(&cip->cin);
+       CloseFile(&cip->cout);
+       cip->ctrlSocketR = kClosedFileDescriptor;
+       cip->ctrlSocketW = kClosedFileDescriptor;
+       if (cip->ctrlTimeout > 0)
+               (void) alarm(0);
+#endif /* NO_SIGNALS */
+       cip->connected = 0;
+       cip->loggedIn = 0;
+}      /* CloseControlConnection */
+
+
+
+static int
+GetSocketAddress(const FTPCIPtr cip, int sockfd, struct sockaddr_in *saddr)
+{
+       int len = (int) sizeof (struct sockaddr_in);
+       int result = 0;
+
+       if (getsockname(sockfd, (struct sockaddr *)saddr, &len) < 0) {
+               Error(cip, kDoPerror, "Could not get socket name.\n");
+               cip->errNo = kErrGetSockName;
+               result = kErrGetSockName;
+       }
+       return (result);
+}      /* GetSocketAddress */
+
+
+
+
+int
+SetKeepAlive(const FTPCIPtr cip, int sockfd)
+{
+#ifndef SO_KEEPALIVE
+       cip->errNo = kErrSetKeepAlive;
+       return (kErrSetKeepAlive);
+#else
+       int opt;
+
+       opt = 1;
+
+       if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, (int) sizeof(opt)) < 0) {
+               /* Error(cip, kDoPerror, "Could not set keep-alive mode.\n"); */
+               cip->errNo = kErrSetKeepAlive;
+               return (kErrSetKeepAlive);
+       }
+       return (kNoErr);
+#endif /* SO_KEEPALIVE */
+}      /* SetKeepAlive */
+
+
+
+
+int
+SetLinger(const FTPCIPtr cip, int sockfd, int onoff)
+{
+#ifndef SO_LINGER
+       cip->errNo = kErrSetLinger;
+       return (kErrSetLinger);
+#else
+       struct linger li;
+
+       if (onoff != 0) {
+               li.l_onoff = 1;
+               li.l_linger = 120;      /* 2 minutes, but system ignores field. */
+       } else {
+               li.l_onoff = 0;
+               li.l_linger = 0;
+       }
+       /* Have the system make an effort to deliver any unsent data,
+        * even after we close the connection.
+        */
+       if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (char *) &li, (int) sizeof(li)) < 0) {
+               /* Error(cip, kDoPerror, "Could not set linger mode.\n"); */
+               cip->errNo = kErrSetLinger;
+               return (kErrSetLinger);
+       }
+       return (kNoErr);
+#endif /* SO_LINGER */
+}      /* SetLinger */
+
+
+
+
+#ifdef IP_TOS
+int
+SetTypeOfService(const FTPCIPtr cip, int sockfd, int tosType)
+{
+       /* Specify to the router what type of connection this is, so it
+        * can prioritize packets.
+        */
+       if (setsockopt(sockfd, IPPROTO_IP, IP_TOS, (char *) &tosType, (int) sizeof(tosType)) < 0) {
+               /* Error(cip, kDoPerror, "Could not set type of service.\n"); */
+               cip->errNo = kErrSetTypeOfService;
+               return (kErrSetTypeOfService);
+       }
+       return (kNoErr);
+}      /* SetTypeOfService */
+#endif /* IP_TOS */
+
+
+
+
+#ifdef SO_OOBINLINE
+int
+SetInlineOutOfBandData(const FTPCIPtr cip, int sockfd)
+{
+       int on = 1;
+
+       if (setsockopt(sockfd, SOL_SOCKET, SO_OOBINLINE, (char *) &on, (int) sizeof(on)) < 0) {
+               Error(cip, kDoPerror, "Could not set out of band inline mode.\n");
+               cip->errNo = kErrSetOutOfBandInline;
+               return (kErrSetOutOfBandInline);
+       }
+       return (kNoErr);
+}      /* SetInlineOutOfBandData */
+#endif /* SO_OOBINLINE */
+
+
+
+
+#ifndef NO_SIGNALS
+
+static void
+CancelConnect(int signum)
+{
+       gGotSig = signum;
+#ifdef HAVE_SIGSETJMP
+       siglongjmp(gCancelConnectJmp, 1);
+#else
+       longjmp(gCancelConnectJmp, 1);
+#endif /* HAVE_SIGSETJMP */
+}      /* CancelConnect */
+
+#endif /* NO_SIGNALS */
+
+
+
+int
+OpenControlConnection(const FTPCIPtr cip, char *host, unsigned int port)
+{
+       struct in_addr ip_address;
+       int err = 0;
+       int result;
+       int oerrno;
+       volatile int sockfd = -1;
+       volatile int sock2fd = -1;
+       ResponsePtr rp;
+       char **volatile curaddr;
+       struct hostent *hp;
+       char *volatile fhost;
+       unsigned int fport;
+#ifndef NO_SIGNALS
+       volatile FTPSigProc osigint;
+       volatile FTPSigProc osigalrm;
+       volatile FTPCIPtr vcip;
+       int sj;
+#endif /* NO_SIGNALS */
+       const char *firstLine, *secondLine, *srvr;
+
+       LIBNCFTP_USE_VAR(gLibNcFTPVersion);
+       LIBNCFTP_USE_VAR(gCopyright);
+#ifdef NO_SIGNALS
+       LIBNCFTP_USE_VAR(gNoSignalsMarker);
+#endif /* NO_SIGNALS */
+
+       if (cip->firewallType == kFirewallNotInUse) {
+               fhost = host;
+               fport = port;
+       } else {
+               fhost = cip->firewallHost;
+               fport = cip->firewallPort;
+       }
+       if (fport == 0)
+               fport = cip->lip->defaultPort;
+
+       /* Since we're the client, we just have to get a socket() and
+        * connect() it.
+        */
+       (void) ZERO(cip->servCtlAddr);
+       cip->cin = NULL;
+       cip->cout = NULL;
+
+       /* Make sure we use network byte-order. */
+       fport = (unsigned int) htons((unsigned short) fport);
+
+       cip->servCtlAddr.sin_port = (unsigned short) fport;
+
+       hp = GetHostEntry(fhost, &ip_address);
+
+       if (hp == NULL) {
+               /* Okay, no Host entry, but maybe we have a numeric address
+                * in ip_address we can try.
+                */
+               if (ip_address.s_addr == INADDR_NONE) {
+                       Error(cip, kDontPerror, "%s: unknown host.\n", fhost);
+                       cip->errNo = kErrHostUnknown;
+                       return (kErrHostUnknown);
+               }
+               cip->servCtlAddr.sin_family = AF_INET;
+               cip->servCtlAddr.sin_addr.s_addr = ip_address.s_addr;
+       } else {
+               cip->servCtlAddr.sin_family = hp->h_addrtype;
+               /* We'll fill in the rest of the structure below. */
+       }
+       
+       /* After obtaining a socket, try to connect it to a remote
+        * address.  If we didn't get a host entry, we will only have
+        * one thing to try (ip_address);  if we do have one, we can try
+        * every address in the list from the host entry.
+        */
+
+       if (hp == NULL) {
+               /* Since we're given a single raw address, and not a host entry,
+                * we can only try this one address and not any other addresses
+                * that could be present for a site with a host entry.
+                */
+
+               if ((sockfd = socket(cip->servCtlAddr.sin_family, SOCK_STREAM, 0)) < 0) {
+                       Error(cip, kDoPerror, "Could not get a socket.\n");
+                       cip->errNo = kErrNewStreamSocket;
+                       return (kErrNewStreamSocket);
+               }
+
+               /* This doesn't do anything if you left these
+                * at their defaults (zero).  Otherwise it
+                * tries to set the buffer size to the
+                * size specified.
+                */
+               (void) SetSockBufSize(sockfd, cip->ctrlSocketRBufSize, cip->ctrlSocketSBufSize);
+
+#ifdef NO_SIGNALS
+               err = SConnect(sockfd, &cip->servCtlAddr, (int) cip->connTimeout);
+
+               if (err < 0) {
+                       oerrno = errno;
+                       (void) SClose(sockfd, 3);
+                       errno = oerrno;
+                       sockfd = -1;
+               }
+#else  /* NO_SIGNALS */
+               osigint = (volatile FTPSigProc) signal(SIGINT, CancelConnect);
+               if (cip->connTimeout > 0) {
+                       osigalrm = (volatile FTPSigProc) signal(SIGALRM, CancelConnect);
+                       (void) alarm(cip->connTimeout);
+               }
+
+               vcip = cip;
+
+#ifdef HAVE_SIGSETJMP
+               sj = sigsetjmp(gCancelConnectJmp, 1);
+#else
+               sj = setjmp(gCancelConnectJmp);
+#endif /* HAVE_SIGSETJMP */
+
+               if (sj != 0) {
+                       /* Interrupted by a signal. */
+                       (void) closesocket(sockfd);
+                       (void) signal(SIGINT, (FTPSigProc) osigint);
+                       if (vcip->connTimeout > 0) {
+                               (void) alarm(0);
+                               (void) signal(SIGALRM, (FTPSigProc) osigalrm);
+                       }
+                       if (gGotSig == SIGINT) {
+                               result = vcip->errNo = kErrConnectMiscErr;
+                               Error(vcip, kDontPerror, "Connection attempt canceled.\n");
+                               (void) kill(getpid(), SIGINT);
+                       } else if (gGotSig == SIGALRM) {
+                               result = vcip->errNo = kErrConnectRetryableErr;
+                               Error(vcip, kDontPerror, "Connection attempt timed-out.\n");
+                               (void) kill(getpid(), SIGALRM);
+                       } else {
+                               result = vcip->errNo = kErrConnectMiscErr;
+                               Error(vcip, kDontPerror, "Connection attempt failed due to an unexpected signal (%d).\n", gGotSig);
+                       }
+                       return (result);
+               } else  {
+                       err = connect(sockfd, (struct sockaddr *) &cip->servCtlAddr,
+                                     (int) sizeof (cip->servCtlAddr));
+                       if (cip->connTimeout > 0) {
+                               (void) alarm(0);
+                               (void) signal(SIGALRM, (FTPSigProc) osigalrm);
+                       }
+                       (void) signal(SIGINT, (FTPSigProc) osigint);
+               }
+
+               if (err < 0) {
+                       oerrno = errno;
+                       (void) closesocket(sockfd);
+                       errno = oerrno;
+                       sockfd = -1;
+               }
+#endif /* NO_SIGNALS */
+       } else {
+               /* We can try each address in the list.  We'll quit when we
+                * run out of addresses to try or get a successful connection.
+                */
+               for (curaddr = hp->h_addr_list; *curaddr != NULL; curaddr++) {
+                       if ((sockfd = socket(cip->servCtlAddr.sin_family, SOCK_STREAM, 0)) < 0) {
+                               Error(cip, kDoPerror, "Could not get a socket.\n");
+                               cip->errNo = kErrNewStreamSocket;
+                               return (kErrNewStreamSocket);
+                       }
+                       /* This could overwrite the address field in the structure,
+                        * but this is okay because the structure has a junk field
+                        * just for this purpose.
+                        */
+                       (void) memcpy(&cip->servCtlAddr.sin_addr, *curaddr, (size_t) hp->h_length);
+
+                       /* This doesn't do anything if you left these
+                        * at their defaults (zero).  Otherwise it
+                        * tries to set the buffer size to the
+                        * size specified.
+                        */
+                       (void) SetSockBufSize(sockfd, cip->ctrlSocketRBufSize, cip->ctrlSocketSBufSize);
+
+#ifdef NO_SIGNALS
+                       err = SConnect(sockfd, &cip->servCtlAddr, (int) cip->connTimeout);
+
+                       if (err == 0)
+                               break;
+                       oerrno = errno;
+                       (void) SClose(sockfd, 3);
+                       errno = oerrno;
+                       sockfd = -1;
+#else  /* NO_SIGNALS */
+
+                       osigint = (volatile FTPSigProc) signal(SIGINT, CancelConnect);
+                       if (cip->connTimeout > 0) {
+                               osigalrm = (volatile FTPSigProc) signal(SIGALRM, CancelConnect);
+                               (void) alarm(cip->connTimeout);
+                       }
+
+                       vcip = cip;
+#ifdef HAVE_SIGSETJMP
+                       sj = sigsetjmp(gCancelConnectJmp, 1);
+#else
+                       sj = setjmp(gCancelConnectJmp);
+#endif /* HAVE_SIGSETJMP */
+
+                       if (sj != 0) {
+                               /* Interrupted by a signal. */
+                               (void) closesocket(sockfd);
+                               (void) signal(SIGINT, (FTPSigProc) osigint);
+                               if (vcip->connTimeout > 0) {
+                                       (void) alarm(0);
+                                       (void) signal(SIGALRM, (FTPSigProc) osigalrm);
+                               }
+                               if (gGotSig == SIGINT) {
+                                       result = vcip->errNo = kErrConnectMiscErr;
+                                       Error(vcip, kDontPerror, "Connection attempt canceled.\n");
+                                       (void) kill(getpid(), SIGINT);
+                               } else if (gGotSig == SIGALRM) {
+                                       result = vcip->errNo = kErrConnectRetryableErr;
+                                       Error(vcip, kDontPerror, "Connection attempt timed-out.\n");
+                                       (void) kill(getpid(), SIGALRM);
+                               } else {
+                                       result = vcip->errNo = kErrConnectMiscErr;
+                                       Error(vcip, kDontPerror, "Connection attempt failed due to an unexpected signal (%d).\n", gGotSig);
+                               }
+                               return (result);
+                       } else {
+                               err = connect(sockfd, (struct sockaddr *) &cip->servCtlAddr,
+                                             (int) sizeof (cip->servCtlAddr));
+                               if (cip->connTimeout > 0) {
+                                       (void) alarm(0);
+                                       (void) signal(SIGALRM, (FTPSigProc) osigalrm);
+                               }
+                               (void) signal(SIGINT, (FTPSigProc) osigint);
+                       }
+
+                       if (err == 0)
+                               break;
+                       oerrno = errno;
+                       (void) closesocket(sockfd);
+                       errno = oerrno;
+                       sockfd = -1;
+#endif /* NO_SIGNALS */
+               }
+       }
+       
+       if (err < 0) {
+               /* Could not connect.  Close up shop and go home. */
+
+               /* If possible, tell the caller if they should bother
+                * calling back later.
+                */
+               switch (errno) {
+#ifdef ENETDOWN
+                       case ENETDOWN:
+#elif defined(WSAENETDOWN)
+                       case WSAENETDOWN:
+#endif
+#ifdef ENETUNREACH
+                       case ENETUNREACH:
+#elif defined(WSAENETUNREACH)
+                       case WSAENETUNREACH:
+#endif
+#ifdef ECONNABORTED
+                       case ECONNABORTED:
+#elif defined(WSAECONNABORTED)
+                       case WSAECONNABORTED:
+#endif
+#ifdef ETIMEDOUT
+                       case ETIMEDOUT:
+#elif defined(WSAETIMEDOUT)
+                       case WSAETIMEDOUT:
+#endif
+#ifdef EHOSTDOWN
+                       case EHOSTDOWN:
+#elif defined(WSAEHOSTDOWN)
+                       case WSAEHOSTDOWN:
+#endif
+#ifdef ECONNRESET
+                       case ECONNRESET:
+#elif defined(WSAECONNRESET)
+                       case WSAECONNRESET:
+#endif
+                               Error(cip, kDoPerror, "Could not connect to %s -- try again later.\n", fhost);
+                               result = cip->errNo = kErrConnectRetryableErr;
+                               break;
+#ifdef ECONNREFUSED
+                       case ECONNREFUSED:
+#elif defined(WSAECONNREFUSED)
+                       case WSAECONNREFUSED:
+#endif
+                               Error(cip, kDoPerror, "Could not connect to %s.\n", fhost);
+                               result = cip->errNo = kErrConnectRefused;
+                               break;
+                       default:
+                               Error(cip, kDoPerror, "Could not connect to %s.\n", fhost);
+                               result = cip->errNo = kErrConnectMiscErr;
+               }
+               goto fatal;
+       }
+
+       /* Get our end of the socket address for later use. */
+       if ((result = GetSocketAddress(cip, sockfd, &cip->ourCtlAddr)) < 0)
+               goto fatal;
+
+#ifdef SO_OOBINLINE
+       /* We want Out-of-band data to appear in the regular stream,
+        * since we can handle TELNET.
+        */
+       (void) SetInlineOutOfBandData(cip, sockfd);
+#endif
+       (void) SetKeepAlive(cip, sockfd);
+       (void) SetLinger(cip, sockfd, 0);       /* Don't need it for ctrl. */
+
+#if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
+       /* Control connection is somewhat interactive, so quick response
+        * is desired.
+        */
+       (void) SetTypeOfService(cip, sockfd, IPTOS_LOWDELAY);
+#endif
+
+#ifdef NO_SIGNALS
+       cip->ctrlSocketR = sockfd;
+       cip->ctrlSocketW = sockfd;
+       cip->cout = NULL;
+       cip->cin = NULL;
+       sock2fd = kClosedFileDescriptor;
+
+       if (InitSReadlineInfo(&cip->ctrlSrl, sockfd, cip->srlBuf, sizeof(cip->srlBuf), (int) cip->ctrlTimeout, 1) < 0) {
+               result = kErrFdopenW;
+               cip->errNo = kErrFdopenW;
+               Error(cip, kDoPerror, "Could not fdopen.\n");
+               goto fatal;
+       }
+#else  /* NO_SIGNALS */
+       if ((sock2fd = dup(sockfd)) < 0) {
+               result = kErrDupSocket;
+               cip->errNo = kErrDupSocket;
+               Error(cip, kDoPerror, "Could not duplicate a file descriptor.\n");
+               goto fatal;
+       }
+
+       /* Now setup the FILE pointers for use with the Std I/O library
+        * routines.
+        */
+       if ((cip->cin = fdopen(sockfd, "r")) == NULL) {
+               result = kErrFdopenR;
+               cip->errNo = kErrFdopenR;
+               Error(cip, kDoPerror, "Could not fdopen.\n");
+               goto fatal;
+       }
+
+       if ((cip->cout = fdopen(sock2fd, "w")) == NULL) {
+               result = kErrFdopenW;
+               cip->errNo = kErrFdopenW;
+               Error(cip, kDoPerror, "Could not fdopen.\n");
+               CloseFile(&cip->cin);
+               sockfd = kClosedFileDescriptor;
+               goto fatal;
+       }
+
+       cip->ctrlSocketR = sockfd;
+       cip->ctrlSocketW = sockfd;
+
+       /* We'll be reading and writing lines, so use line buffering.  This
+        * is necessary since the stdio library will use full buffering
+        * for all streams not associated with the tty.
+        */
+#ifdef HAVE_SETLINEBUF
+       setlinebuf(cip->cin);
+       setlinebuf(cip->cout);
+#else
+       (void) SETVBUF(cip->cin, NULL, _IOLBF, (size_t) BUFSIZ);
+       (void) SETVBUF(cip->cout, NULL, _IOLBF, (size_t) BUFSIZ);
+#endif
+#endif /* NO_SIGNALS */
+
+#ifdef HAVE_INET_NTOP  /* Mostly to workaround bug in IRIX 6.5's inet_ntoa */
+       (void) memset(cip->ip, 0, sizeof(cip->ip));
+       (void) inet_ntop(AF_INET, &cip->servCtlAddr.sin_addr, cip->ip, sizeof(cip->ip) - 1);
+#else
+       (void) STRNCPY(cip->ip, inet_ntoa(cip->servCtlAddr.sin_addr));
+#endif
+       if ((hp == NULL) || (hp->h_name == NULL))
+               (void) STRNCPY(cip->actualHost, fhost);
+       else
+               (void) STRNCPY(cip->actualHost, (char *) hp->h_name);
+
+       /* Read the startup message from the server. */ 
+       rp = InitResponse();
+       if (rp == NULL) {
+               Error(cip, kDontPerror, "Malloc failed.\n");
+               cip->errNo = kErrMallocFailed;
+               result = cip->errNo;
+               goto fatal;
+       }
+
+       result = GetResponse(cip, rp);
+       if ((result < 0) && (rp->msg.first == NULL)) {
+               goto fatal;
+       }
+       if (rp->msg.first != NULL) {
+               cip->serverType = kServerTypeUnknown;
+               srvr = NULL;
+               firstLine = rp->msg.first->line;
+               secondLine = NULL;
+               if (rp->msg.first->next != NULL)
+                       secondLine = rp->msg.first->next->line;
+               
+               if (strstr(firstLine, "Version wu-") != NULL) {
+                       cip->serverType = kServerTypeWuFTPd;
+                       srvr = "wu-ftpd";
+               } else if (strstr(firstLine, "NcFTPd") != NULL) {
+                       cip->serverType = kServerTypeNcFTPd;
+                       srvr = "NcFTPd Server";
+               } else if (STRNEQ("ProFTPD", firstLine, 7)) {
+                       cip->serverType = kServerTypeProFTPD;
+                       srvr = "ProFTPD";
+               } else if (strstr(firstLine, "Microsoft FTP Service") != NULL) {
+                       cip->serverType = kServerTypeMicrosoftFTP;
+                       srvr = "Microsoft FTP Service";
+               } else if (strstr(firstLine, "(NetWare ") != NULL) {
+                       cip->serverType = kServerTypeNetWareFTP;
+                       srvr = "NetWare FTP Service";
+               } else if (STRNEQ("WFTPD", firstLine, 5)) {
+                       cip->serverType = kServerTypeWFTPD;
+                       srvr = "WFTPD";
+               } else if (STRNEQ("Serv-U FTP", firstLine, 10)) {
+                       cip->serverType = kServerTypeServ_U;
+                       srvr = "Serv-U FTP-Server";
+               } else if (strstr(firstLine, "VFTPD") != NULL) {
+                       cip->serverType = kServerTypeVFTPD;
+                       srvr = "VFTPD";
+               } else if (STRNEQ("FTP-Max", firstLine, 7)) {
+                       cip->serverType = kServerTypeFTP_Max;
+                       srvr = "FTP-Max";
+               } else if (strstr(firstLine, "Roxen") != NULL) {
+                       cip->serverType = kServerTypeRoxen;
+                       srvr = "Roxen";
+               } else if (strstr(firstLine, "WS_FTP") != NULL) {
+                       cip->serverType = kServerTypeWS_FTP;
+                       srvr = "WS_FTP Server";
+               } else if ((secondLine != NULL) && (strstr(secondLine, "WarFTP") != NULL)) {
+                       cip->serverType = kServerTypeWarFTPd;
+                       srvr = "WarFTPd";
+               }
+
+               if (srvr != NULL)
+                       PrintF(cip, "Remote server is running %s.\n", srvr);
+
+               /* Do the application's connect message callback, if present. */
+               if ((cip->onConnectMsgProc != 0) && (rp->codeType < 4))
+                       (*cip->onConnectMsgProc)(cip, rp);
+       }
+
+       if (rp->codeType >= 4) {
+               /* They probably hung up on us right away.  That's too bad,
+                * but we can tell the caller that they can call back later
+                * and try again.
+                */
+               DoneWithResponse(cip, rp);
+               result = kErrConnectRetryableErr;
+               Error(cip, kDontPerror, "Server hungup immediately after connect.\n");
+               cip->errNo = kErrConnectRetryableErr;
+               goto fatal;
+       }
+       if (result < 0)         /* Some other error occurred during connect message */
+               goto fatal;
+       cip->connected = 1;
+       DoneWithResponse(cip, rp);
+       return (kNoErr);
+       
+fatal:
+       if (sockfd > 0)
+               (void) closesocket(sockfd);
+       if (sock2fd > 0)
+               (void) closesocket(sock2fd);            
+       CloseFile(&cip->cin);
+       CloseFile(&cip->cout);
+       cip->ctrlSocketR = kClosedFileDescriptor;
+       cip->ctrlSocketW = kClosedFileDescriptor;
+       return (result);
+}      /* OpenControlConnection */
+
+
+
+
+void
+CloseDataConnection(const FTPCIPtr cip)
+{
+       if (cip->dataSocket != kClosedFileDescriptor) {
+#ifdef NO_SIGNALS
+               SClose(cip->dataSocket, 3);
+#else  /* NO_SIGNALS */
+               if (cip->xferTimeout > 0)
+                       (void) alarm(cip->xferTimeout);
+               (void) closesocket(cip->dataSocket);
+               if (cip->xferTimeout > 0)
+                       (void) alarm(0);
+#endif /* NO_SIGNALS */
+               cip->dataSocket = kClosedFileDescriptor;
+       }
+       memset(&cip->ourDataAddr, 0, sizeof(cip->ourDataAddr));
+       memset(&cip->servDataAddr, 0, sizeof(cip->servDataAddr));
+}      /* CloseDataConnection */
+
+
+
+
+int
+SetStartOffset(const FTPCIPtr cip, longest_int restartPt)
+{
+       ResponsePtr rp;
+       int result;
+
+       if (restartPt != (longest_int) 0) {
+               rp = InitResponse();
+               if (rp == NULL) {
+                       Error(cip, kDontPerror, "Malloc failed.\n");
+                       cip->errNo = kErrMallocFailed;
+                       return (cip->errNo);
+               }
+
+               /* Force reset to offset zero. */
+               if (restartPt == (longest_int) -1)
+                       restartPt = (longest_int) 0;
+#ifdef PRINTF_LONG_LONG
+               result = RCmd(cip, rp,
+               "REST " PRINTF_LONG_LONG,
+               restartPt);
+#else
+               result = RCmd(cip, rp, "REST %ld", (long) restartPt);
+#endif
+
+               if (result < 0) {
+                       return (result);
+               } else if (result == 3) {
+                       cip->hasREST = kCommandAvailable;
+                       DoneWithResponse(cip, rp);
+               } else if (UNIMPLEMENTED_CMD(rp->code)) {
+                       cip->hasREST = kCommandNotAvailable;
+                       DoneWithResponse(cip, rp);
+                       cip->errNo = kErrSetStartPoint;
+                       return (kErrSetStartPoint);
+               } else {
+                       DoneWithResponse(cip, rp);
+                       cip->errNo = kErrSetStartPoint;
+                       return (kErrSetStartPoint);
+               }
+       }
+       return (0);
+}      /* SetStartOffset */
+
+
+
+static int
+SendPort(const FTPCIPtr cip, struct sockaddr_in *saddr)
+{
+       char *a, *p;
+       int result;
+       ResponsePtr rp;
+
+       rp = InitResponse();
+       if (rp == NULL) {
+               Error(cip, kDontPerror, "Malloc failed.\n");
+               cip->errNo = kErrMallocFailed;
+               return (cip->errNo);
+       }
+
+       /* These will point to data in network byte order. */
+       a = (char *) &saddr->sin_addr;
+       p = (char *) &saddr->sin_port;
+#define UC(x) (int) (((int) x) & 0xff)
+
+       /* Need to tell the other side which host (the address) and
+        * which process (port) on that host to send data to.
+        */
+       result = RCmd(cip, rp, "PORT %d,%d,%d,%d,%d,%d",
+               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+
+       if (result < 0) {
+               return (result);
+       } else if (result != 2) {
+               /* A 500'ish response code means the PORT command failed. */
+               DoneWithResponse(cip, rp);
+               cip->errNo = kErrPORTFailed;
+               return (cip->errNo);
+       }
+       DoneWithResponse(cip, rp);
+       return (kNoErr);
+}      /* SendPort */
+
+
+
+
+static int
+Passive(const FTPCIPtr cip, struct sockaddr_in *saddr, int *weird)
+{
+       ResponsePtr rp;
+       int i[6], j;
+       unsigned char n[6];
+       char *cp;
+       int result;
+
+       rp = InitResponse();
+       if (rp == NULL) {
+               Error(cip, kDontPerror, "Malloc failed.\n");
+               cip->errNo = kErrMallocFailed;
+               return (cip->errNo);
+       }
+
+       result = RCmd(cip, rp, "PASV");
+       if (result < 0)
+               goto done;
+
+       if (rp->codeType != 2) {
+               /* Didn't understand or didn't want passive port selection. */
+               cip->errNo = result = kErrPASVFailed;
+               goto done;
+       }
+
+       /* The other side returns a specification in the form of
+        * an internet address as the first four integers (each
+        * integer stands for 8-bits of the real 32-bit address),
+        * and two more integers for the port (16-bit port).
+        *
+        * It should give us something like:
+        * "Entering Passive Mode (129,93,33,1,10,187)", so look for
+        * digits with sscanf() starting 24 characters down the string.
+        */
+       for (cp = rp->msg.first->line; ; cp++) {
+               if (*cp == '\0') {
+                       Error(cip, kDontPerror, "Cannot parse PASV response: %s\n", rp->msg.first->line);
+                       goto done;
+               }
+               if (isdigit((int) *cp))
+                       break;
+       }
+
+       if (sscanf(cp, "%d,%d,%d,%d,%d,%d",
+                       &i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6) {
+               Error(cip, kDontPerror, "Cannot parse PASV response: %s\n", rp->msg.first->line);
+               goto done;
+       }
+
+       for (j=0, *weird = 0; j<6; j++) {
+               /* Some ftp servers return bogus port octets, such as
+                * boombox.micro.umn.edu.  Let the caller know if we got a
+                * weird looking octet.
+                */
+               if ((i[j] < 0) || (i[j] > 255))
+                       *weird = *weird + 1;
+               n[j] = (unsigned char) (i[j] & 0xff);
+       }
+
+       (void) memcpy(&saddr->sin_addr, &n[0], (size_t) 4);
+       (void) memcpy(&saddr->sin_port, &n[4], (size_t) 2);
+
+       result = kNoErr;
+done:
+       DoneWithResponse(cip, rp);
+       return (result);
+}      /* Passive */
+
+
+
+
+static int
+BindToEphemeralPortNumber(int sockfd, struct sockaddr_in *addrp, int ephemLo, int ephemHi)
+{
+       int i;
+       int result;
+       int rangesize;
+       unsigned short port;
+
+       addrp->sin_family = AF_INET;
+       if (((int) ephemLo == 0) || ((int) ephemLo >= (int) ephemHi)) {
+               /* Do it the normal way.  System will
+                * pick one, typically in the range
+                * of 1024-4999.
+                */
+               addrp->sin_port = 0;    /* Let system pick one. */
+
+               result = bind(sockfd, (struct sockaddr *) addrp, sizeof(struct sockaddr_in));
+       } else {
+               rangesize = (int) ((int) ephemHi - (int) ephemLo);
+               result = 0;
+               for (i=0; i<10; i++) {
+                       port = (unsigned short) (((int) rand() % rangesize) + (int) ephemLo);
+                       addrp->sin_port = port;
+
+                       result = bind(sockfd, (struct sockaddr *) addrp, sizeof(struct sockaddr_in));
+                       if (result == 0)
+                               break;
+                       if ((errno != 999)
+                               /* This next line is just fodder to
+                                * shut the compiler up about variable
+                                * not being used.
+                                */
+                               && (gCopyright[0] != '\0'))
+                               break;
+               }
+       }
+       return (result);
+}      /* BindToEphemeralPortNumber */
+
+
+
+
+int
+OpenDataConnection(const FTPCIPtr cip, int mode)
+{
+       int dataSocket;
+       int weirdPort;
+       int result;
+
+       /* Before we can transfer any data, and before we even ask the
+        * remote server to start transferring via RETR/NLST/etc, we have
+        * to setup the connection.
+        */
+
+tryPort2:
+       weirdPort = 0;
+       result = 0;
+       CloseDataConnection(cip);       /* In case we didn't before... */
+
+       dataSocket = socket(AF_INET, SOCK_STREAM, 0);
+       if (dataSocket < 0) {
+               Error(cip, kDoPerror, "Could not get a data socket.\n");
+               result = kErrNewStreamSocket;
+               cip->errNo = kErrNewStreamSocket;
+               return result;
+       }
+
+       /* This doesn't do anything if you left these
+        * at their defaults (zero).  Otherwise it
+        * tries to set the buffer size to the
+        * size specified.
+        */
+       (void) SetSockBufSize(dataSocket, cip->dataSocketRBufSize, cip->dataSocketSBufSize);
+
+       if ((cip->hasPASV == kCommandNotAvailable) || (mode == kSendPortMode)) {
+tryPort:
+               cip->ourDataAddr = cip->ourCtlAddr;
+               cip->ourDataAddr.sin_family = AF_INET;
+
+#ifdef HAVE_LIBSOCKS
+               cip->ourDataAddr.sin_port = 0;
+               if (Rbind(dataSocket, (struct sockaddr *) &cip->ourDataAddr,
+                       (int) sizeof (cip->ourDataAddr),
+                       cip->servCtlAddr.sin_addr.s_addr) < 0) 
+#else
+               if (BindToEphemeralPortNumber(dataSocket, &cip->ourDataAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0)
+#endif
+               {
+                       Error(cip, kDoPerror, "Could not bind the data socket");
+                       result = kErrBindDataSocket;
+                       cip->errNo = kErrBindDataSocket;
+                       goto bad;
+               }
+       
+               /* Need to do this so we can figure out which port the system
+                * gave to us.
+                */
+               if ((result = GetSocketAddress(cip, dataSocket, &cip->ourDataAddr)) < 0)
+                       goto bad;
+       
+               if (listen(dataSocket, 1) < 0) {
+                       Error(cip, kDoPerror, "listen failed");
+                       result = kErrListenDataSocket;
+                       cip->errNo = kErrListenDataSocket;
+                       goto bad;
+               }
+       
+               if ((result = SendPort(cip, &cip->ourDataAddr)) < 0)
+                       goto bad;
+       
+               cip->dataPortMode = kSendPortMode;
+       } else {
+               /* Passive mode.  Let the other side decide where to send. */
+               
+               cip->servDataAddr = cip->servCtlAddr;
+               cip->servDataAddr.sin_family = AF_INET;
+               cip->ourDataAddr = cip->ourCtlAddr;
+               cip->ourDataAddr.sin_family = AF_INET;
+
+               if (Passive(cip, &cip->servDataAddr, &weirdPort) < 0) {
+                       Error(cip, kDontPerror, "Passive mode refused.\n");
+                       cip->hasPASV = kCommandNotAvailable;
+                       
+                       /* We can try using regular PORT commands, which are required
+                        * by all FTP protocol compliant programs, if you said so.
+                        *
+                        * We don't do this automatically, because if your host
+                        * is running a firewall you (probably) do not want SendPort
+                        * FTP for security reasons.
+                        */
+                       if (mode == kFallBackToSendPortMode)
+                               goto tryPort;
+                       result = kErrPassiveModeFailed;
+                       cip->errNo = kErrPassiveModeFailed;
+                       goto bad;
+               }
+
+#ifdef HAVE_LIBSOCKS
+               cip->ourDataAddr.sin_port = 0;
+               if (Rbind(dataSocket, (struct sockaddr *) &cip->ourDataAddr,
+                       (int) sizeof (cip->ourDataAddr),
+                       cip->servCtlAddr.sin_addr.s_addr) < 0) 
+#else
+               if (BindToEphemeralPortNumber(dataSocket, &cip->ourDataAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0)
+#endif
+               {
+                       Error(cip, kDoPerror, "Could not bind the data socket");
+                       result = kErrBindDataSocket;
+                       cip->errNo = kErrBindDataSocket;
+                       goto bad;
+               }
+
+#ifdef NO_SIGNALS
+               result = SConnect(dataSocket, &cip->servDataAddr, (int) cip->connTimeout);
+#else  /* NO_SIGNALS */
+               if (cip->connTimeout > 0)
+                       (void) alarm(cip->connTimeout);
+
+               result = connect(dataSocket, (struct sockaddr *) &cip->servDataAddr, (int) sizeof(cip->servDataAddr));
+               if (cip->connTimeout > 0)
+                       (void) alarm(0);
+#endif /* NO_SIGNALS */
+
+#ifdef NO_SIGNALS
+               if (result == kTimeoutErr) {
+                       if (mode == kFallBackToSendPortMode) {
+                               Error(cip, kDontPerror, "Data connection timed out.\n");
+                               Error(cip, kDontPerror, "Falling back to PORT instead of PASV mode.\n");
+                               (void) closesocket(dataSocket);
+                               cip->hasPASV = kCommandNotAvailable;
+                               goto tryPort2;
+                       }
+                       Error(cip, kDontPerror, "Data connection timed out.\n");
+                       result = kErrConnectDataSocket;
+                       cip->errNo = kErrConnectDataSocket;
+               } else
+#endif /* NO_SIGNALS */
+
+               if (result < 0) {
+#ifdef ECONNREFUSED
+                       if ((weirdPort > 0) && (errno == ECONNREFUSED)) {
+#elif defined(WSAECONNREFUSED)
+                       if ((weirdPort > 0) && (errno == WSAECONNREFUSED)) {
+#endif
+                               Error(cip, kDontPerror, "Server sent back a bogus port number.\nI will fall back to PORT instead of PASV mode.\n");
+                               if (mode == kFallBackToSendPortMode) {
+                                       (void) closesocket(dataSocket);
+                                       cip->hasPASV = kCommandNotAvailable;
+                                       goto tryPort2;
+                               }
+                               result = kErrServerSentBogusPortNumber;
+                               cip->errNo = kErrServerSentBogusPortNumber;
+                               goto bad;
+                       }
+                       if (mode == kFallBackToSendPortMode) {
+                               Error(cip, kDoPerror, "connect failed.\n");
+                               Error(cip, kDontPerror, "Falling back to PORT instead of PASV mode.\n");
+                               (void) closesocket(dataSocket);
+                               cip->hasPASV = kCommandNotAvailable;
+                               goto tryPort2;
+                       }
+                       Error(cip, kDoPerror, "connect failed.\n");
+                       result = kErrConnectDataSocket;
+                       cip->errNo = kErrConnectDataSocket;
+                       goto bad;
+               }
+       
+               /* Need to do this so we can figure out which port the system
+                * gave to us.
+                */
+               if ((result = GetSocketAddress(cip, dataSocket, &cip->ourDataAddr)) < 0)
+                       goto bad;
+
+               cip->dataPortMode = kPassiveMode;
+               cip->hasPASV = kCommandAvailable;
+       }
+
+       (void) SetLinger(cip, dataSocket, 1);
+       (void) SetKeepAlive(cip, dataSocket);
+
+#if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
+       /* Data connection is a non-interactive data stream, so
+        * high throughput is desired, at the expense of low
+        * response time.
+        */
+       (void) SetTypeOfService(cip, dataSocket, IPTOS_THROUGHPUT);
+#endif
+
+       cip->dataSocket = dataSocket;
+       return (0);
+bad:
+       (void) closesocket(dataSocket);
+       return (result);
+}      /* OpenDataConnection */
+
+
+
+
+int
+AcceptDataConnection(const FTPCIPtr cip)
+{
+       int newSocket;
+#ifndef NO_SIGNALS
+       int len;
+#endif
+       unsigned short remoteDataPort;
+       unsigned short remoteCtrlPort;
+
+       /* If we did a PORT, we have some things to finish up.
+        * If we did a PASV, we're ready to go.
+        */
+       if (cip->dataPortMode == kSendPortMode) {
+               /* Accept will give us back the server's data address;  at the
+                * moment we don't do anything with it though.
+                */
+               memset(&cip->servDataAddr, 0, sizeof(cip->servDataAddr));
+
+#ifdef NO_SIGNALS
+               newSocket = SAccept(cip->dataSocket, &cip->servDataAddr, (int) cip->connTimeout);
+#else  /* NO_SIGNALS */
+               len = (int) sizeof(cip->servDataAddr);
+               if (cip->connTimeout > 0)
+                       (void) alarm(cip->connTimeout);
+               newSocket = accept(cip->dataSocket, (struct sockaddr *) &cip->servDataAddr, &len);
+               if (cip->connTimeout > 0)
+                       (void) alarm(0);
+#endif /* NO_SIGNALS */
+
+               (void) closesocket(cip->dataSocket);
+               if (newSocket < 0) {
+                       Error(cip, kDoPerror, "Could not accept a data connection.\n");
+                       cip->dataSocket = kClosedFileDescriptor;
+                       cip->errNo = kErrAcceptDataSocket;
+                       return (kErrAcceptDataSocket);
+               }
+
+               if (cip->require20 != 0) {
+                       remoteDataPort = ntohs(cip->servDataAddr.sin_port);
+                       remoteCtrlPort = ntohs(cip->servCtlAddr.sin_port);
+                       if ((int) remoteDataPort != ((int) remoteCtrlPort - 1)) {
+                               Error(cip, kDontPerror, "Data connection did not originate on correct port!\n");
+                               (void) closesocket(newSocket);
+                               cip->dataSocket = kClosedFileDescriptor;
+                               cip->errNo = kErrAcceptDataSocket;
+                               return (kErrAcceptDataSocket);
+                       } else if (memcmp(&cip->servDataAddr.sin_addr.s_addr, &cip->servCtlAddr.sin_addr.s_addr, sizeof(cip->servDataAddr.sin_addr.s_addr)) != 0) {
+                               Error(cip, kDontPerror, "Data connection did not originate from remote server!\n");
+                               (void) closesocket(newSocket);
+                               cip->dataSocket = kClosedFileDescriptor;
+                               cip->errNo = kErrAcceptDataSocket;
+                               return (kErrAcceptDataSocket);
+                       }
+               }
+               
+               cip->dataSocket = newSocket;
+       }
+
+       return (0);
+}      /* AcceptDataConnection */
+
+
+
+
+void
+HangupOnServer(const FTPCIPtr cip)
+{
+       /* Since we want to close both sides of the connection for each
+        * socket, we can just have them closed with close() instead of
+        * using shutdown().
+        */
+       CloseControlConnection(cip);
+       CloseDataConnection(cip);
+}      /* HangupOnServer */
+
+
+
+
+void
+SendTelnetInterrupt(const FTPCIPtr cip)
+{
+       char msg[4];
+
+       /* 1. User system inserts the Telnet "Interrupt Process" (IP) signal
+        *    in the Telnet stream.
+        */
+
+       if (cip->cout != NULL)
+               (void) fflush(cip->cout);
+       
+       msg[0] = (char) (unsigned char) IAC;
+       msg[1] = (char) (unsigned char) IP;
+       (void) send(cip->ctrlSocketW, msg, 2, 0);
+
+       /* 2. User system sends the Telnet "Sync" signal. */
+#if 1
+       msg[0] = (char) (unsigned char) IAC;
+       msg[1] = (char) (unsigned char) DM;
+       if (send(cip->ctrlSocketW, msg, 2, MSG_OOB) != 2)
+               Error(cip, kDoPerror, "Could not send an urgent message.\n");
+#else
+       /* "Send IAC in urgent mode instead of DM because UNIX places oob mark
+        * after urgent byte rather than before as now is protocol," says
+        * the BSD ftp code.
+        */
+       msg[0] = (char) (unsigned char) IAC;
+       if (send(cip->ctrlSocketW, msg, 1, MSG_OOB) != 1)
+               Error(cip, kDoPerror, "Could not send an urgent message.\n");
+       (void) fprintf(cip->cout, "%c", DM);
+       (void) fflush(cip->cout);
+#endif
+}      /* SendTelnetInterrupt */
+
+/* eof FTP.c */
diff --git a/rosapps/net/ncftp/libncftp/ftp.h b/rosapps/net/ncftp/libncftp/ftp.h
new file mode 100644 (file)
index 0000000..f91d950
--- /dev/null
@@ -0,0 +1,22 @@
+/* FTP.h
+ *
+ * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
+ * All rights reserved.
+ *
+ */
+
+/* FTP.c */
+void MyInetAddr(char *, size_t, char **, int);
+int GetOurHostName(char *, size_t);
+void CloseControlConnection(const FTPCIPtr);
+int SetKeepAlive(const FTPCIPtr, int);
+int SetLinger(const FTPCIPtr, int, int);
+int SetTypeOfService(const FTPCIPtr, int, int);
+int SetInlineOutOfBandData(const FTPCIPtr, int);
+int OpenControlConnection(const FTPCIPtr, char *, unsigned int);
+void CloseDataConnection(const FTPCIPtr);
+int SetStartOffset(const FTPCIPtr, longest_int);
+int OpenDataConnection(const FTPCIPtr, int);
+int AcceptDataConnection(const FTPCIPtr);
+void HangupOnServer(const FTPCIPtr);
+void SendTelnetInterrupt(const FTPCIPtr);
diff --git a/rosapps/net/ncftp/libncftp/glob.c b/rosapps/net/ncftp/libncftp/glob.c
new file mode 100644 (file)
index 0000000..4b6f7b5
--- /dev/null
@@ -0,0 +1,1760 @@
+/* glob.c
+ *
+ * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
+ * All rights reserved.
+ *
+ */
+
+#include "syshdrs.h"
+
+static const char *rwx[9] = { "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx", NULL };
+
+
+
+/* We need to use this because using NLST gives us more stuff than
+ * we want back sometimes.  For example, say we have:
+ *
+ * /a          (directory)
+ * /a/b                (directory)
+ * /a/b/b1
+ * /a/b/b2
+ * /a/b/b3
+ * /a/c                (directory)
+ * /a/c/c1
+ * /a/c/c2
+ * /a/c/c3
+ * /a/file
+ *
+ * If you did an "echo /a/<star>" in a normal unix shell, you would expect
+ * to get back /a/b /a/c /a/file.  But NLST gives back:
+ *
+ * /a/b/b1
+ * /a/b/b2
+ * /a/b/b3
+ * /a/c/c1
+ * /a/c/c2
+ * /a/c/c3
+ * /a/file
+ *
+ * So we use the following routine to convert into the format I expect.
+ */
+
+static void
+RemoteGlobCollapse(const char *pattern, LineListPtr fileList)
+{
+       LinePtr lp, nextLine;
+       string patPrefix;
+       string cur, prev;
+       char *endp, *cp, *dp;
+       const char *pp;
+       int wasGlobChar;
+       size_t plen;
+
+       /* Copy all characters before the first glob-char. */
+       dp = patPrefix;
+       endp = dp + sizeof(patPrefix) - 1;
+       wasGlobChar = 0;
+       for (cp = (char *) pattern; dp < endp; ) {
+               for (pp=kGlobChars; *pp != '\0'; pp++) {
+                       if (*pp == *cp) {
+                               wasGlobChar = 1;
+                               break;
+                       }
+               }
+               if (wasGlobChar)
+                       break;
+               *dp++ = *cp++;
+       }
+       *dp = '\0';
+       plen = (size_t) (dp - patPrefix);
+
+       *prev = '\0';
+       for (lp=fileList->first; lp != NULL; lp = nextLine) {
+               nextLine = lp->next;
+               if (strncmp(lp->line, patPrefix, plen) == 0) {
+                       (void) STRNCPY(cur, lp->line + plen);
+                       cp = strchr(cur, '/');
+                       if (cp == NULL)
+                               cp = strchr(cur, '\\');
+                       if (cp != NULL)
+                               *cp = '\0';
+                       if ((*prev != '\0') && (STREQ(cur, prev))) {
+                               nextLine = RemoveLine(fileList, lp);
+                       } else {
+                               (void) STRNCPY(prev, cur);
+                               /* We are playing with a dynamically
+                                * allocated string, but since the
+                                * following expression is guaranteed
+                                * to be the same or shorter, we won't
+                                * overwrite the bounds.
+                                */
+                               (void) sprintf(lp->line, "%s%s", patPrefix, cur);
+                       }
+               }
+       }
+}      /* RemoteGlobCollapse */
+
+
+
+
+#if 0
+/* May need this later. */
+static void
+CheckForLS_d(FTPCIPtr cip)
+{
+       LineList lines;
+       char *cp;
+
+       if (cip->hasNLST_d == kCommandAvailabilityUnknown) {
+               if (FTPListToMemory2(cip, ".", &lines, "-d ", 0, (int *) 0) == kNoErr) {
+                       if ((lines.first != NULL) && (lines.first == lines.last)) {
+                               /* If we have only one item in the list, see if it really was
+                                * an error message we would recognize.
+                                */
+                               cp = strchr(lines.first->line, ':');
+                               if ((cp != NULL) && STREQ(cp, ": No such file or directory")) {
+                                       cip->hasNLST_d = kCommandNotAvailable;
+                               } else {
+                                       cip->hasNLST_d = kCommandAvailable;
+                               }
+                       } else {
+                               cip->hasNLST_d = kCommandNotAvailable;
+                       }
+               } else {
+                       cip->hasNLST_d = kCommandNotAvailable;
+               }
+               DisposeLineListContents(&lines);
+       }
+}      /* CheckForLS_d */
+#endif
+
+
+
+
+static int
+LsMonthNameToNum(char *cp)
+{
+       int mon;  &nb