--- /dev/null
+#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 */
--- /dev/null
+#
+# 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
--- /dev/null
+/* 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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+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)
--- /dev/null
+/* 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
--- /dev/null
+#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);
+}
--- /dev/null
+char gStrnLibVersion[20] = "@(#) Strn 2.2.0";
--- /dev/null
+/* 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). */
--- /dev/null
+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)
+])
--- /dev/null
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+ PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", RES_STR_COMPANY_NAME
+ VALUE "FileDescription", "Ncftp for Win32\0"
+ VALUE "FileVersion", RES_STR_FILE_VERSION
+ VALUE "InternalName", "ncftp\0"
+ VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
+ VALUE "OriginalCopyright", "Anonymous sources found at http://www.ncftp.org/\0"
+ VALUE "OriginalFilename", "ncftp.exe\0"
+ VALUE "ProductName", RES_STR_PRODUCT_NAME
+ VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
--- /dev/null
+#-----------------------------------------------------------------------------
+#
+# 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
--- /dev/null
+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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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
--- /dev/null
+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])
--- /dev/null
+#!/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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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);
--- /dev/null
+/* 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++;