Merge branch 'vendor/TNFTP'
authorPeter Avalos <pavalos@dragonflybsd.org>
Wed, 15 Dec 2010 05:54:39 +0000 (19:54 -1000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Wed, 15 Dec 2010 05:54:39 +0000 (19:54 -1000)
1  2 
contrib/tnftp/cmds.c
contrib/tnftp/fetch.c
contrib/tnftp/ftp_var.h
contrib/tnftp/util.c

diff --combined contrib/tnftp/cmds.c
@@@ -1,7 -1,7 +1,7 @@@
- /*    $NetBSD: cmds.c,v 1.125 2008/05/10 00:05:31 skd Exp $   */
+ /*    $NetBSD: cmds.c,v 1.131 2010/01/12 06:50:04 lukem Exp $ */
  
  /*-
-  * Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
+  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
   * All rights reserved.
   *
   * This code is derived from software contributed to The NetBSD Foundation
@@@ -96,7 -96,7 +96,7 @@@
  #if 0
  static char sccsid[] = "@(#)cmds.c    8.6 (Berkeley) 10/9/94";
  #else
- __RCSID("$NetBSD: cmds.c,v 1.125 2008/05/10 00:05:31 skd Exp $");
+ __RCSID("$NetBSD: cmds.c,v 1.131 2010/01/12 06:50:04 lukem Exp $");
  #endif
  #endif /* not lint */
  
  #include <limits.h>
  #include <netdb.h>
  #include <paths.h>
+ #include <stddef.h>
  #include <stdio.h>
 +#include <libutil.h>
  #include <stdlib.h>
  #include <string.h>
  #include <time.h>
  #include "version.h"
  
  static struct types {
-       char    *t_name;
-       char    *t_mode;
-       int     t_type;
-       char    *t_arg;
+       const char      *t_name;
+       const char      *t_mode;
+       int             t_type;
+       const char      *t_arg;
  } types[] = {
        { "ascii",      "A",    TYPE_A, 0 },
        { "binary",     "I",    TYPE_I, 0 },
        { "image",      "I",    TYPE_I, 0 },
        { "ebcdic",     "E",    TYPE_E, 0 },
        { "tenex",      "L",    TYPE_L, bytename },
-       { NULL }
+       { NULL,         NULL,   0, NULL }
  };
  
  static sigjmp_buf      jabort;
  static int    confirm(const char *, const char *);
  static void   mintr(int);
  static void   mabort(const char *);
+ static void   set_type(const char *);
  
  static const char *doprocess(char *, size_t, const char *, int, int, int);
  static const char *domap(char *, size_t, const char *);
@@@ -158,7 -159,7 +160,7 @@@ static in
  confirm(const char *cmd, const char *file)
  {
        const char *errormsg;
-       char line[BUFSIZ];
+       char cline[BUFSIZ];
        const char *promptleft, *promptright;
  
        if (!interactive || confirmrest)
        while (1) {
                fprintf(ttyout, "%s %s [anpqy?]? ", promptleft, promptright);
                (void)fflush(ttyout);
-               if (getline(stdin, line, sizeof(line), &errormsg) < 0) {
+               if (get_line(stdin, cline, sizeof(cline), &errormsg) < 0) {
                        mflag = 0;
                        fprintf(ttyout, "%s; %s aborted\n", errormsg, cmd);
                        return (0);
                }
-               switch (tolower((unsigned char)*line)) {
+               switch (tolower((unsigned char)*cline)) {
                        case 'a':
                                confirmrest = 1;
                                fprintf(ttyout,
@@@ -218,10 -219,9 +220,9 @@@ voi
  settype(int argc, char *argv[])
  {
        struct types *p;
-       int comret;
  
        if (argc == 0 || argc > 2) {
-               char *sep;
+               const char *sep;
  
                UPRINTF("usage: %s [", argv[0]);
                sep = " ";
                code = 0;
                return;
        }
+       set_type(argv[1]);
+ }
+ void
+ set_type(const char *ttype)
+ {
+       struct types *p;
+       int comret;
        for (p = types; p->t_name; p++)
-               if (strcmp(argv[1], p->t_name) == 0)
+               if (strcmp(ttype, p->t_name) == 0)
                        break;
        if (p->t_name == 0) {
-               fprintf(ttyout, "%s: unknown mode.\n", argv[1]);
+               fprintf(ttyout, "%s: unknown mode.\n", ttype);
                code = -1;
                return;
        }
@@@ -288,12 -297,6 +298,6 @@@ changetype(int newtype, int show
        verbose = oldverbose;
  }
  
- char *stype[] = {
-       "type",
-       "",
-       0
- };
  /*
   * Set binary transfer type.
   */
@@@ -307,8 -310,7 +311,7 @@@ setbinary(int argc, char *argv[]
                code = -1;
                return;
        }
-       stype[1] = "binary";
-       settype(2, stype);
+       set_type("binary");
  }
  
  /*
@@@ -324,8 -326,7 +327,7 @@@ setascii(int argc, char *argv[]
                code = -1;
                return;
        }
-       stype[1] = "ascii";
-       settype(2, stype);
+       set_type("ascii");
  }
  
  /*
@@@ -341,8 -342,7 +343,7 @@@ settenex(int argc, char *argv[]
                code = -1;
                return;
        }
-       stype[1] = "tenex";
-       settype(2, stype);
+       set_type("tenex");
  }
  
  /*
@@@ -403,7 -403,7 +404,7 @@@ voi
  put(int argc, char *argv[])
  {
        char buf[MAXPATHLEN];
-       char *cmd;
+       const char *cmd;
        int loc = 0;
        char *locfile;
        const char *remfile;
@@@ -572,7 -572,7 +573,7 @@@ get(int argc, char *argv[]
   * If restartit is -1, restart the xfer only if the remote file is newer.
   */
  int
- getit(int argc, char *argv[], int restartit, const char *mode)
+ getit(int argc, char *argv[], int restartit, const char *gmode)
  {
        int     loc, rval;
        char    *remfile, *olocfile;
                }
        }
  
-       recvrequest("RETR", locfile, remfile, mode,
+       recvrequest("RETR", locfile, remfile, gmode,
            remfile != argv[1] || locfile != argv[2], loc);
        restart_point = 0;
   freegetit:
@@@ -681,7 -681,7 +682,7 @@@ mget(int argc, char *argv[]
        int ointer;
        char *cp;
        const char *tp;
-       int restartit;
+       int volatile restartit;
  
        if (argc == 0 ||
            (argc == 1 && !another(&argc, &argv, "remote-files"))) {
  void
  fget(int argc, char *argv[])
  {
-       char    *mode;
+       const char *gmode;
        FILE    *fp;
-       char    buf[MAXPATHLEN];
+       char    buf[MAXPATHLEN], cmdbuf[MAX_C_NAME];
  
        if (argc != 2) {
                UPRINTF("usage: %s localfile\n", argv[0]);
                return;
        }
  
-       argv[0] = "get";
-       mode = restart_point ? "r+" : "w";
+       (void)strlcpy(cmdbuf, "get", sizeof(cmdbuf));
+       argv[0] = cmdbuf;
+       gmode = restart_point ? "r+" : "w";
  
-       while (getline(fp, buf, sizeof(buf), NULL) >= 0) {
+       while (get_line(fp, buf, sizeof(buf), NULL) >= 0) {
                if (buf[0] == '\0')
                        continue;
                argv[1] = buf;
-               (void)getit(argc, argv, 0, mode);
+               (void)getit(argc, argv, 0, gmode);
        }
        fclose(fp);
  }
  
  const char *
- onoff(int bool)
+ onoff(int val)
  {
  
-       return (bool ? "on" : "off");
+       return (val ? "on" : "off");
  }
  
  /*
@@@ -1277,18 -1278,20 +1279,20 @@@ renamefile(int argc, char *argv[]
   *    mlsd            MLSD
   *    nlist           NLST
   *    pdir, pls       LIST |$PAGER
-  *    mmlsd           MLSD |$PAGER
+  *    pmlsd           MLSD |$PAGER
   */
  void
  ls(int argc, char *argv[])
  {
        const char *cmd;
-       char *remdir, *locfile;
-       int freelocfile, pagecmd, mlsdcmd;
+       char *remdir, *locbuf;
+       const char *locfile;
+       int pagecmd, mlsdcmd;
  
        remdir = NULL;
+       locbuf = NULL;
        locfile = "-";
-       freelocfile = pagecmd = mlsdcmd = 0;
+       pagecmd = mlsdcmd = 0;
                        /*
                         * the only commands that start with `p' are
                         * the `pager' versions.
        }
  
        if (pagecmd) {
-               char *p;
+               const char *p;
                size_t len;
  
                p = getoptionvalue("pager");
                if (EMPTYSTRING(p))
                        p = DEFAULTPAGER;
                len = strlen(p) + 2;
-               locfile = ftp_malloc(len);
-               locfile[0] = '|';
-               (void)strlcpy(locfile + 1, p, len - 1);
-               freelocfile = 1;
+               locbuf = ftp_malloc(len);
+               locbuf[0] = '|';
+               (void)strlcpy(locbuf + 1, p, len - 1);
+               locfile = locbuf;
        } else if ((strcmp(locfile, "-") != 0) && *locfile != '|') {
-               if ((locfile = globulize(locfile)) == NULL ||
-                   !confirm("output to local-file:", locfile)) {
+               if ((locbuf = globulize(locfile)) == NULL ||
+                   !confirm("output to local-file:", locbuf)) {
                        code = -1;
                        goto freels;
                }
-               freelocfile = 1;
+               locfile = locbuf;
        }
        recvrequest(cmd, locfile, remdir, "w", 0, 0);
   freels:
-       if (freelocfile && locfile)
-               (void)free(locfile);
+       if (locbuf)
+               (void)free(locbuf);
  }
  
  /*
@@@ -1362,8 -1365,9 +1366,9 @@@ mls(int argc, char *argv[]
  {
        sigfunc oldintr;
        int ointer, i;
-       int dolist;
-       char *mode, *dest, *odest;
+       int volatile dolist;
+       char * volatile dest, *odest;
+       const char *lmode;
  
        if (argc == 0)
                goto usage;
        if (sigsetjmp(jabort, 1))
                mabort(argv[0]);
        for (i = 1; mflag && i < argc-1 && connected; i++) {
-               mode = (i == 1) ? "w" : "a";
-               recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], mode,
+               lmode = (i == 1) ? "w" : "a";
+               recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], lmode,
                    0, 0);
                if (!mflag && fromatty) {
                        ointer = interactive;
@@@ -1416,7 -1420,8 +1421,8 @@@ shell(int argc, char *argv[]
  {
        pid_t pid;
        sigfunc oldintr;
-       char shellnam[MAXPATHLEN], *shell, *namep;
+       char shellnam[MAXPATHLEN];
+       const char *shellp, *namep;
        int wait_status;
  
        if (argc == 0) {
                for (pid = 3; pid < 20; pid++)
                        (void)close(pid);
                (void)xsignal(SIGINT, SIG_DFL);
-               shell = getenv("SHELL");
-               if (shell == NULL)
-                       shell = _PATH_BSHELL;
-               namep = strrchr(shell, '/');
+               shellp = getenv("SHELL");
+               if (shellp == NULL)
+                       shellp = _PATH_BSHELL;
+               namep = strrchr(shellp, '/');
                if (namep == NULL)
-                       namep = shell;
+                       namep = shellp;
                else
                        namep++;
                (void)strlcpy(shellnam, namep, sizeof(shellnam));
                if (ftp_debug) {
-                       fputs(shell, ttyout);
+                       fputs(shellp, ttyout);
                        putc('\n', ttyout);
                }
                if (argc > 1) {
-                       execl(shell, shellnam, "-c", altarg, (char *)0);
+                       execl(shellp, shellnam, "-c", altarg, (char *)0);
                }
                else {
-                       execl(shell, shellnam, (char *)0);
+                       execl(shellp, shellnam, (char *)0);
                }
-               warn("Can't execute `%s'", shell);
+               warn("Can't execute `%s'", shellp);
                code = -1;
                exit(1);
        }
@@@ -1834,6 -1839,7 +1840,7 @@@ doproxy(int argc, char *argv[]
        struct cmd *c;
        int cmdpos;
        sigfunc oldintr;
+       char cmdbuf[MAX_C_NAME];
  
        if (argc == 0 || (argc == 1 && !another(&argc, &argv, "command"))) {
                UPRINTF("usage: %s command\n", argv[0]);
        cmdpos = strcspn(line, " \t");
        if (cmdpos > 0)         /* remove leading "proxy " from input buffer */
                memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
-       argv[1] = c->c_name;
+       (void)strlcpy(cmdbuf, c->c_name, sizeof(cmdbuf));
+       argv[1] = cmdbuf;
        (*c->c_handler)(argc-1, argv+1);
        if (connected) {
                proxflag = 1;
@@@ -1964,7 -1971,7 +1972,7 @@@ dotrans(char *dst, size_t dlen, const c
                                found++;
                                if (i < ostop) {
                                        *cp2++ = *(ntout + i);
-                                       if (cp2 - dst >= dlen - 1)
+                                       if (cp2 - dst >= (ptrdiff_t)(dlen - 1))
                                                goto out;
                                }
                                break;
@@@ -2546,7 -2553,8 +2554,8 @@@ voi
  lpage(int argc, char *argv[])
  {
        size_t len;
-       char *p, *pager, *locfile;
+       const char *p;
+       char *pager, *locfile;
  
        if (argc == 0 || argc > 2 ||
            (argc == 1 && !another(&argc, &argv, "local-file"))) {
@@@ -2580,7 -2588,8 +2589,8 @@@ page(int argc, char *argv[]
  {
        int ohash, orestart_point, overbose;
        size_t len;
-       char *p, *pager;
+       const char *p;
+       char *pager;
  
        if (argc == 0 || argc > 2 ||
            (argc == 1 && !another(&argc, &argv, "remote-file"))) {
@@@ -2668,20 -2677,28 +2678,28 @@@ setoption(int argc, char *argv[]
                            o->name, o->value ? o->value : "");
                }
        } else {
-               o = getoption(argv[1]);
-               if (o == NULL) {
-                       fprintf(ttyout, "No such option `%s'.\n", argv[1]);
-                       return;
-               }
-               FREEPTR(o->value);
-               o->value = ftp_strdup(argv[2]);
-               if (verbose)
-                       fprintf(ttyout, "Setting `%s' to `%s'.\n",
-                           o->name, o->value);
+               set_option(argv[1], argv[2], 1);
        }
        code = 0;
  }
  
+ void
+ set_option(const char * option, const char * value, int doverbose)
+ {
+       struct option *o;
+       o = getoption(option);
+       if (o == NULL) {
+               fprintf(ttyout, "No such option `%s'.\n", option);
+               return;
+       }
+       FREEPTR(o->value);
+       o->value = ftp_strdup(value);
+       if (verbose && doverbose)
+               fprintf(ttyout, "Setting `%s' to `%s'.\n",
+                   o->name, o->value);
+ }
  /*
   * Unset an option
   */
diff --combined contrib/tnftp/fetch.c
@@@ -1,7 -1,7 +1,7 @@@
- /*    $NetBSD: fetch.c,v 1.185 2008/04/28 20:24:13 martin Exp $       */
+ /*    $NetBSD: fetch.c,v 1.193 2010/03/05 07:41:10 lukem Exp $        */
  
  /*-
-  * Copyright (c) 1997-2008 The NetBSD Foundation, Inc.
+  * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
   * All rights reserved.
   *
   * This code is derived from software contributed to The NetBSD Foundation
@@@ -34,7 -34,7 +34,7 @@@
  
  #include <sys/cdefs.h>
  #ifndef lint
- __RCSID("$NetBSD: fetch.c,v 1.185 2008/04/28 20:24:13 martin Exp $");
+ __RCSID("$NetBSD: fetch.c,v 1.193 2010/03/05 07:41:10 lukem Exp $");
  #endif /* not lint */
  
  /*
@@@ -58,7 -58,6 +58,7 @@@
  #include <netdb.h>
  #include <fcntl.h>
  #include <stdio.h>
 +#include <libutil.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
@@@ -142,7 -141,8 +142,8 @@@ auth_url(const char *challenge, char **
  {
        const char      *cp, *scheme, *errormsg;
        char            *ep, *clear, *realm;
-       char             user[BUFSIZ], *pass;
+       char             uuser[BUFSIZ], *gotpass;
+       const char      *upass;
        int              rval;
        size_t           len, clen, rlen;
  
        rval = -1;
        cp = challenge;
        scheme = "Basic";       /* only support Basic authentication */
+       gotpass = NULL;
  
        DPRINTF("auth_url: challenge `%s'\n", challenge);
  
        }
  /* XXX: need to improve quoted-string parsing to support \ quoting, etc. */
        if ((ep = strchr(cp, '\"')) != NULL) {
-               size_t len = ep - cp;
+               len = ep - cp;
                realm = (char *)ftp_malloc(len + 1);
                (void)strlcpy(realm, cp, len + 1);
        } else {
  
        fprintf(ttyout, "Username for `%s': ", realm);
        if (guser != NULL) {
-               (void)strlcpy(user, guser, sizeof(user));
-               fprintf(ttyout, "%s\n", user);
+               (void)strlcpy(uuser, guser, sizeof(uuser));
+               fprintf(ttyout, "%s\n", uuser);
        } else {
                (void)fflush(ttyout);
-               if (getline(stdin, user, sizeof(user), &errormsg) < 0) {
+               if (get_line(stdin, uuser, sizeof(uuser), &errormsg) < 0) {
                        warnx("%s; can't authenticate", errormsg);
                        goto cleanup_auth_url;
                }
        }
        if (gpass != NULL)
-               pass = (char *)gpass;
+               upass = gpass;
        else {
-               pass = getpass("Password: ");
-               if (pass == NULL) {
+               gotpass = getpass("Password: ");
+               if (gotpass == NULL) {
                        warnx("Can't read password");
                        goto cleanup_auth_url;
                }
+               upass = gotpass;
        }
  
-       clen = strlen(user) + strlen(pass) + 2; /* user + ":" + pass + "\0" */
+       clen = strlen(uuser) + strlen(upass) + 2;       /* user + ":" + pass + "\0" */
        clear = (char *)ftp_malloc(clen);
-       (void)strlcpy(clear, user, clen);
+       (void)strlcpy(clear, uuser, clen);
        (void)strlcat(clear, ":", clen);
-       (void)strlcat(clear, pass, clen);
-       if (gpass == NULL)
-               memset(pass, 0, strlen(pass));
+       (void)strlcat(clear, upass, clen);
+       if (gotpass)
+               memset(gotpass, 0, strlen(gotpass));
  
                                                /* scheme + " " + enc + "\0" */
        rlen = strlen(scheme) + 1 + (clen + 2) * 4 / 3 + 1;
@@@ -236,7 -237,7 +238,7 @@@ base64_encode(const unsigned char *clea
        static const unsigned char enc[] =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        unsigned char   *cp;
-       int      i;
+       size_t   i;
  
        cp = encoded;
        for (i = 0; i < len; i += 3) {
@@@ -280,7 -281,7 +282,7 @@@ url_decode(char *url
  
  
  /*
-  * Parse URL of form (per RFC3986):
+  * Parse URL of form (per RFC 3986):
   *    <type>://[<user>[:<password>]@]<host>[:<port>][/<path>]
   * Returns -1 if a parse error occurred, otherwise 0.
   * It's the caller's responsibility to url_decode() the returned
   * malloc(3)ed strings of the relevant section, and port to
   * the number given, or ftpport if ftp://, or httpport if http://.
   *
-  * XXX: this is not totally RFC3986 compliant; <path> will have the
+  * XXX: this is not totally RFC 3986 compliant; <path> will have the
   * leading `/' unless it's an ftp:// URL, as this makes things easier
   * for file:// and http:// URLs.  ftp:// URLs have the `/' between the
   * host and the URL-path removed, but any additional leading slashes
   *    "ftp://host//dir/file"          "/dir/file"
   */
  static int
- parse_url(const char *url, const char *desc, url_t *type,
-               char **user, char **pass, char **host, char **port,
+ parse_url(const char *url, const char *desc, url_t *utype,
+               char **uuser, char **pass, char **host, char **port,
                in_port_t *portnum, char **path)
  {
-       const char      *origurl;
-       char            *cp, *ep, *thost, *tport;
+       const char      *origurl, *tport;
+       char            *cp, *ep, *thost;
        size_t           len;
  
-       if (url == NULL || desc == NULL || type == NULL || user == NULL
+       if (url == NULL || desc == NULL || utype == NULL || uuser == NULL
            || pass == NULL || host == NULL || port == NULL || portnum == NULL
            || path == NULL)
                errx(1, "parse_url: invoked with NULL argument!");
        DPRINTF("parse_url: %s `%s'\n", desc, url);
  
        origurl = url;
-       *type = UNKNOWN_URL_T;
-       *user = *pass = *host = *port = *path = NULL;
+       *utype = UNKNOWN_URL_T;
+       *uuser = *pass = *host = *port = *path = NULL;
        *portnum = 0;
        tport = NULL;
  
        if (STRNEQUAL(url, HTTP_URL)) {
                url += sizeof(HTTP_URL) - 1;
-               *type = HTTP_URL_T;
+               *utype = HTTP_URL_T;
                *portnum = HTTP_PORT;
                tport = httpport;
        } else if (STRNEQUAL(url, FTP_URL)) {
                url += sizeof(FTP_URL) - 1;
-               *type = FTP_URL_T;
+               *utype = FTP_URL_T;
                *portnum = FTP_PORT;
                tport = ftpport;
        } else if (STRNEQUAL(url, FILE_URL)) {
                url += sizeof(FILE_URL) - 1;
-               *type = FILE_URL_T;
+               *utype = FILE_URL_T;
        } else {
                warnx("Invalid %s `%s'", desc, url);
   cleanup_parse_url:
-               FREEPTR(*user);
+               FREEPTR(*uuser);
                if (*pass != NULL)
                        memset(*pass, 0, strlen(*pass));
                FREEPTR(*pass);
                len = ep - url;
                thost = (char *)ftp_malloc(len + 1);
                (void)strlcpy(thost, url, len + 1);
-               if (*type == FTP_URL_T) /* skip first / for ftp URLs */
+               if (*utype == FTP_URL_T)        /* skip first / for ftp URLs */
                        ep++;
                *path = ftp_strdup(ep);
        }
  
        cp = strchr(thost, '@');        /* look for user[:pass]@ in URLs */
        if (cp != NULL) {
-               if (*type == FTP_URL_T)
+               if (*utype == FTP_URL_T)
                        anonftp = 0;    /* disable anonftp */
-               *user = thost;
+               *uuser = thost;
                *cp = '\0';
                thost = ftp_strdup(cp + 1);
-               cp = strchr(*user, ':');
+               cp = strchr(*uuser, ':');
                if (cp != NULL) {
                        *cp = '\0';
                        *pass = ftp_strdup(cp + 1);
                }
-               url_decode(*user);
+               url_decode(*uuser);
                if (*pass)
                        url_decode(*pass);
        }
  #ifdef INET6
                        /*
                         * Check if thost is an encoded IPv6 address, as per
-                        * RFC3986:
+                        * RFC 3986:
                         *      `[' ipv6-address ']'
                         */
        if (*thost == '[') {
                *port = ftp_strdup(tport);
        if (*path == NULL) {
                const char *emptypath = "/";
-               if (*type == FTP_URL_T) /* skip first / for ftp URLs */
+               if (*utype == FTP_URL_T)        /* skip first / for ftp URLs */
                        emptypath++;
                *path = ftp_strdup(emptypath);
        }
  
        DPRINTF("parse_url: user `%s' pass `%s' host %s port %s(%d) "
            "path `%s'\n",
-           STRorNULL(*user), STRorNULL(*pass),
+           STRorNULL(*uuser), STRorNULL(*pass),
            STRorNULL(*host), STRorNULL(*port),
            *portnum ? *portnum : -1, STRorNULL(*path));
  
@@@ -479,7 -480,8 +481,8 @@@ fetch_url(const char *url, const char *
        int volatile            isproxy;
        int volatile            rval;
        int volatile            hcode;
-       size_t                  len;
+       int                     len;
+       size_t                  flen;
        static size_t           bufsize;
        static char             *xferbuf;
        const char              *cp, *token;
        char                    *volatile auth;
        char                    *volatile location;
        char                    *volatile message;
-       char                    *user, *pass, *host, *port, *path;
+       char                    *uuser, *pass, *host, *port, *path;
        char                    *volatile decodedpath;
        char                    *puser, *ppass, *useragent;
        off_t                   hashbytes, rangestart, rangeend, entitylen;
        auth = location = message = NULL;
        ischunked = isproxy = hcode = 0;
        rval = 1;
-       user = pass = host = path = decodedpath = puser = ppass = NULL;
+       uuser = pass = host = path = decodedpath = puser = ppass = NULL;
  
-       if (parse_url(url, "URL", &urltype, &user, &pass, &host, &port,
+       if (parse_url(url, "URL", &urltype, &uuser, &pass, &host, &port,
            &portnum, &path) == -1)
                goto cleanup_fetch_url;
  
                        fputs("\n", ttyout);
                }
        } else {                                /* ftp:// or http:// URLs */
-               char *leading;
+               const char *leading;
                int hasleading;
  
                if (proxyenv == NULL) {
                }
  
                                /* Read the response */
-               len = getline(fin, buf, sizeof(buf), &errormsg);
+               len = get_line(fin, buf, sizeof(buf), &errormsg);
                if (len < 0) {
                        if (*errormsg == '\n')
                                errormsg++;
  
                                /* Read the rest of the header. */
                while (1) {
-                       len = getline(fin, buf, sizeof(buf), &errormsg);
+                       len = get_line(fin, buf, sizeof(buf), &errormsg);
                        if (len < 0) {
                                if (*errormsg == '\n')
                                        errormsg++;
  
                        } else if (match_token(&cp, "Last-Modified:")) {
                                struct tm parsed;
-                               char *t;
+                               const char *t;
  
                                memset(&parsed, 0, sizeof(parsed));
-                                                       /* RFC1123 */
-                               if ((t = strptime(cp,
-                                               "%a, %d %b %Y %H:%M:%S GMT",
-                                               &parsed))
-                                                       /* RFC0850 */
-                                   || (t = strptime(cp,
-                                               "%a, %d-%b-%y %H:%M:%S GMT",
-                                               &parsed))
-                                                       /* asctime */
-                                   || (t = strptime(cp,
-                                               "%a, %b %d %H:%M:%S %Y",
-                                               &parsed))) {
+                               t = parse_rfc2616time(&parsed, cp);
+                               if (t != NULL) {
                                        parsed.tm_isdst = -1;
                                        if (*t == '\0')
                                                mtime = timegm(&parsed);
  #ifndef NO_DEBUG
                                        if (ftp_debug && mtime != -1) {
                                                fprintf(ttyout,
-                                                   "parsed date as: %s",
+                                                   "parsed time as: %s",
                                                rfc2822time(localtime(&mtime)));
                                        }
  #endif
  
                        if (hcode == 401) {
                                authp = &wwwauth;
-                               auser = user;
+                               auser = uuser;
                                apass = pass;
                        } else {
                                authp = &proxyauth;
  
                                fprintf(ttyout,
                                    "Authorization failed. Retry (y/n)? ");
-                               if (getline(stdin, reply, sizeof(reply), NULL)
+                               if (get_line(stdin, reply, sizeof(reply), NULL)
                                    < 0) {
                                        goto cleanup_fetch_url;
                                }
        (void)xsignal(SIGQUIT, psummary);
        oldintr = xsignal(SIGINT, aborthttp);
  
-       if (rcvbuf_size > bufsize) {
+       if ((size_t)rcvbuf_size > bufsize) {
                if (xferbuf)
                        (void)free(xferbuf);
                bufsize = rcvbuf_size;
  
                        if (rate_get)
                                (void)gettimeofday(&then, NULL);
-                       bufrem = rate_get ? rate_get : bufsize;
+                       bufrem = rate_get ? rate_get : (off_t)bufsize;
                        if (ischunked)
                                bufrem = MIN(chunksize, bufrem);
                        while (bufrem > 0) {
-                               len = fread(xferbuf, sizeof(char),
-                                   MIN(bufsize, bufrem), fin);
-                               if (len <= 0)
+                               flen = fread(xferbuf, sizeof(char),
+                                   MIN((off_t)bufsize, bufrem), fin);
+                               if (flen <= 0)
                                        goto chunkdone;
-                               bytes += len;
-                               bufrem -= len;
-                               if (fwrite(xferbuf, sizeof(char), len, fout)
-                                   != len) {
+                               bytes += flen;
+                               bufrem -= flen;
+                               if (fwrite(xferbuf, sizeof(char), flen, fout)
+                                   != flen) {
                                        warn("Writing `%s'", savefile);
                                        goto cleanup_fetch_url;
                                }
                                        (void)fflush(ttyout);
                                }
                                if (ischunked) {
-                                       chunksize -= len;
+                                       chunksize -= flen;
                                        if (chunksize <= 0)
                                                break;
                                }
        if (res0)
                freeaddrinfo(res0);
        FREEPTR(savefile);
-       FREEPTR(user);
+       FREEPTR(uuser);
        if (pass != NULL)
                memset(pass, 0, strlen(pass));
        FREEPTR(pass);
@@@ -1353,23 -1345,25 +1346,25 @@@ static in
  fetch_ftp(const char *url)
  {
        char            *cp, *xargv[5], rempath[MAXPATHLEN];
-       char            *host, *path, *dir, *file, *user, *pass;
+       char            *host, *path, *dir, *file, *uuser, *pass;
        char            *port;
-       int              dirhasglob, filehasglob, rval, type, xargc;
+       char             cmdbuf[MAXPATHLEN];
+       char             dirbuf[4];
+       int              dirhasglob, filehasglob, rval, transtype, xargc;
        int              oanonftp, oautologin;
        in_port_t        portnum;
        url_t            urltype;
  
        DPRINTF("fetch_ftp: `%s'\n", url);
-       host = path = dir = file = user = pass = NULL;
+       host = path = dir = file = uuser = pass = NULL;
        port = NULL;
        rval = 1;
-       type = TYPE_I;
+       transtype = TYPE_I;
  
        if (STRNEQUAL(url, FTP_URL)) {
-               if ((parse_url(url, "URL", &urltype, &user, &pass,
+               if ((parse_url(url, "URL", &urltype, &uuser, &pass,
                    &host, &port, &portnum, &path) == -1) ||
-                   (user != NULL && *user == '\0') ||
+                   (uuser != NULL && *uuser == '\0') ||
                    EMPTYSTRING(host)) {
                        warnx("Invalid URL `%s'", url);
                        goto cleanup_fetch_ftp;
                                        /* check for trailing ';type=[aid]' */
                if (! EMPTYSTRING(path) && (cp = strrchr(path, ';')) != NULL) {
                        if (strcasecmp(cp, ";type=a") == 0)
-                               type = TYPE_A;
+                               transtype = TYPE_A;
                        else if (strcasecmp(cp, ";type=i") == 0)
-                               type = TYPE_I;
+                               transtype = TYPE_I;
                        else if (strcasecmp(cp, ";type=d") == 0) {
                                warnx(
                            "Directory listing via a URL is not supported");
                cp = strchr(host, '@');
                if (cp != NULL) {
                        *cp = '\0';
-                       user = host;
+                       uuser = host;
                        anonftp = 0;    /* disable anonftp */
                        host = ftp_strdup(cp + 1);
                }
                cp = strrchr(dir, '/');
                if (cp == dir && urltype == CLASSIC_URL_T) {
                        file = cp + 1;
-                       dir = "/";
+                       (void)strlcpy(dirbuf, "/", sizeof(dirbuf));
+                       dir = dirbuf;
                } else if (cp != NULL) {
                        *cp++ = '\0';
                        file = cp;
        }
        DPRINTF("fetch_ftp: user `%s' pass `%s' host %s port %s "
            "path `%s' dir `%s' file `%s'\n",
-           STRorNULL(user), STRorNULL(pass),
+           STRorNULL(uuser), STRorNULL(pass),
            STRorNULL(host), STRorNULL(port),
            STRorNULL(path), STRorNULL(dir), STRorNULL(file));
  
        if (connected)
                disconnect(0, NULL);
        anonftp = oanonftp;
-       xargv[0] = (char *)getprogname();       /* XXX discards const */
+       (void)strlcpy(cmdbuf, getprogname(), sizeof(cmdbuf));
+       xargv[0] = cmdbuf;
        xargv[1] = host;
        xargv[2] = NULL;
        xargc = 2;
        setpeer(xargc, xargv);
        autologin = oautologin;
        if ((connected == 0) ||
-           (connected == 1 && !ftp_login(host, user, pass))) {
-               warnx("Can't connect or login to host `%s:%s'", host, port);
+           (connected == 1 && !ftp_login(host, uuser, pass))) {
+               warnx("Can't connect or login to host `%s:%s'",
+                       host, port ? port : "?");
                goto cleanup_fetch_ftp;
        }
  
-       switch (type) {
+       switch (transtype) {
        case TYPE_A:
                setascii(1, xargv);
                break;
                setbinary(1, xargv);
                break;
        default:
-               errx(1, "fetch_ftp: unknown transfer type %d", type);
+               errx(1, "fetch_ftp: unknown transfer type %d", transtype);
        }
  
                /*
                 * directories in one step.
                 *
                 * If we are dealing with an `ftp://host/path' URL
-                * (urltype is FTP_URL_T), then RFC3986 says we need to
+                * (urltype is FTP_URL_T), then RFC 3986 says we need to
                 * send a separate CWD command for each unescaped "/"
                 * in the path, and we have to interpret %hex escaping
                 * *after* we find the slashes.  It's possible to get
                 * empty components here, (from multiple adjacent
-                * slashes in the path) and RFC3986 says that we should
+                * slashes in the path) and RFC 3986 says that we should
                 * still do `CWD ' (with a null argument) in such cases.
                 *
                 * Many ftp servers don't support `CWD ', so if there's an
                        DPRINTF("fetch_ftp: dir `%s', nextpart `%s'\n",
                            STRorNULL(dir), STRorNULL(nextpart));
                        if (urltype == FTP_URL_T || *dir != '\0') {
-                               xargv[0] = "cd";
+                               (void)strlcpy(cmdbuf, "cd", sizeof(cmdbuf));
+                               xargv[0] = cmdbuf;
                                xargv[1] = dir;
                                xargv[2] = NULL;
                                dirchange = 0;
                                                fprintf(stderr,
  "\n"
  "ftp: The `CWD ' command (without a directory), which is required by\n"
- "     RFC3986 to support the empty directory in the URL pathname (`//'),\n"
- "     conflicts with the server's conformance to RFC0959.\n"
+ "     RFC 3986 to support the empty directory in the URL pathname (`//'),\n"
+ "     conflicts with the server's conformance to RFC 959.\n"
  "     Try the same URL without the `//' in the URL pathname.\n"
  "\n");
                                        goto cleanup_fetch_ftp;
  
                        /* Fetch the file(s). */
        xargc = 2;
-       xargv[0] = "get";
+       (void)strlcpy(cmdbuf, "get", sizeof(cmdbuf));
+       xargv[0] = cmdbuf;
        xargv[1] = file;
        xargv[2] = NULL;
        if (dirhasglob || filehasglob) {
                ointeractive = interactive;
                interactive = 0;
                if (restartautofetch)
-                       xargv[0] = "mreget";
+                       (void)strlcpy(cmdbuf, "mreget", sizeof(cmdbuf));
                else
-                       xargv[0] = "mget";
+                       (void)strlcpy(cmdbuf, "mget", sizeof(cmdbuf));
+               xargv[0] = cmdbuf;
                mget(xargc, xargv);
                interactive = ointeractive;
        } else {
        FREEPTR(port);
        FREEPTR(host);
        FREEPTR(path);
-       FREEPTR(user);
+       FREEPTR(uuser);
        if (pass)
                memset(pass, 0, strlen(pass));
        FREEPTR(pass);
  static int
  go_fetch(const char *url)
  {
-       char *proxy;
+       char *proxyenv;
  
  #ifndef NO_ABOUT
        /*
         * If ftpproxy is set with an FTP URL, use fetch_url()
         * Othewise, use fetch_ftp().
         */
-       proxy = getoptionvalue("ftp_proxy");
-       if (!EMPTYSTRING(proxy) && STRNEQUAL(url, FTP_URL))
+       proxyenv = getoptionvalue("ftp_proxy");
+       if (!EMPTYSTRING(proxyenv) && STRNEQUAL(url, FTP_URL))
                return (fetch_url(url, NULL, NULL, NULL));
  
        return (fetch_ftp(url));
@@@ -1806,10 -1806,12 +1807,12 @@@ auto_put(int argc, char **argv, const c
        char    *uargv[4], *path, *pathsep;
        int      uargc, rval, argpos;
        size_t   len;
+       char     cmdbuf[MAX_C_NAME];
  
-       uargc = 0;
-       uargv[uargc++] = "mput";
-       uargv[uargc++] = argv[0];
+       (void)strlcpy(cmdbuf, "mput", sizeof(cmdbuf));
+       uargv[0] = cmdbuf;
+       uargv[1] = argv[0];
+       uargc = 2;
        uargv[2] = uargv[3] = NULL;
        pathsep = NULL;
        rval = 1;
                        (void)strlcpy(path, uploadserver, len);
                        (void)strlcat(path, "/", len);
                } else {                /* single file to upload */
-                       uargv[0] = "put";
+                       (void)strlcpy(cmdbuf, "put", sizeof(cmdbuf));
+                       uargv[0] = cmdbuf;
                        pathsep = strrchr(path, '/');
                        if (pathsep == NULL) {
                                pathsep = strrchr(path, ':');
diff --combined contrib/tnftp/ftp_var.h
@@@ -1,7 -1,7 +1,7 @@@
- /*    $NetBSD: ftp_var.h,v 1.79 2008/05/10 00:05:31 skd Exp $ */
+ /*    $NetBSD: ftp_var.h,v 1.81 2009/04/12 10:18:52 lukem Exp $       */
  
  /*-
-  * Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
+  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
   * All rights reserved.
   *
   * This code is derived from software contributed to The NetBSD Foundation
  #endif
  
  #include <sys/param.h>
 +#include <sys/socket.h>
  
  #include <netinet/in.h>
  #include <arpa/inet.h>
   * Format of command table.
   */
  struct cmd {
-       char            *c_name;        /* name of command */
+       const char      *c_name;        /* name of command */
        const char      *c_help;        /* help string */
        char            c_bell;         /* give bell when command completes */
        char            c_conn;         /* must be connected to use command */
        void            (*c_handler)(int, char **); /* function to call */
  };
  
+ #define MAX_C_NAME    12              /* maximum length of cmd.c_name */
  /*
   * Format of macro table
   */
@@@ -146,8 -147,8 +148,8 @@@ struct macel 
   * Format of option table
   */
  struct option {
-       char    *name;
-       char    *value;
+       const char      *name;
+       char            *value;
  };
  
  /*
@@@ -211,7 -212,7 +213,7 @@@ GLOBAL     int     autologin;      /* establish use
  GLOBAL        int     proxy;          /* proxy server connection active */
  GLOBAL        int     proxflag;       /* proxy connection exists */
  GLOBAL        int     gatemode;       /* use gate-ftp */
- GLOBAL        char   *gateserver;     /* server to use for gate-ftp */
+ GLOBAL        const char *gateserver; /* server to use for gate-ftp */
  GLOBAL        int     sunique;        /* store files on server with unique name */
  GLOBAL        int     runique;        /* store local files with unique name */
  GLOBAL        int     mcase;          /* map upper to lower case for mget names */
@@@ -246,7 -247,7 +248,7 @@@ GLOBAL     int     rate_get_incr;  /* increment 
  GLOBAL        int     rate_put;       /* maximum put xfer rate */
  GLOBAL        int     rate_put_incr;  /* increment for put xfer rate */
  GLOBAL        int     retry_connect;  /* seconds between retrying connection */
- GLOBAL        char   *tmpdir;         /* temporary directory */
+ GLOBAL        const char *tmpdir;     /* temporary directory */
  GLOBAL        int     epsv4;          /* use EPSV/EPRT on IPv4 connections */
  GLOBAL        int     epsv4bad;       /* EPSV doesn't work on the current server */
  GLOBAL        int     epsv6;          /* use EPSV/EPRT on IPv6 connections */
@@@ -262,8 -263,6 +264,6 @@@ GLOBAL     size_t    cursor_argc;  /* locatio
  GLOBAL        size_t    cursor_argo;  /* offset of cursor in margv[cursor_argc] */
  #endif /* !NO_EDITCOMPLETE */
  
- GLOBAL        char   *direction;      /* direction transfer is occurring */
  GLOBAL        char   *hostname;       /* name of host connected to */
  GLOBAL        int     unix_server;    /* server is unix, can use binary for ascii */
  GLOBAL        int     unix_proxy;     /* proxy is unix, can use binary for ascii */
@@@ -272,9 -271,9 +272,9 @@@ GLOBAL     char    remotecwd[MAXPATHLEN];  /* r
  GLOBAL        char   *username;       /* name of user logged in as. (dynamic) */
  
  GLOBAL        sa_family_t family;     /* address family to use for connections */
- GLOBAL        char    *ftpport;       /* port number to use for FTP connections */
- GLOBAL        char    *httpport;      /* port number to use for HTTP connections */
- GLOBAL        char    *gateport;      /* port number to use for gateftp connections */
+ GLOBAL        const char *ftpport;    /* port number to use for FTP connections */
+ GLOBAL        const char *httpport;   /* port number to use for HTTP connections */
+ GLOBAL        const char *gateport;   /* port number to use for gateftp connections */
  GLOBAL        struct addrinfo *bindai; /* local address to bind as */
  
  GLOBAL        char   *outfile;        /* filename to output URLs to */
diff --combined contrib/tnftp/util.c
@@@ -1,7 -1,7 +1,7 @@@
- /*    $NetBSD: util.c,v 1.147 2008/05/10 00:05:31 skd Exp $   */
+ /*    $NetBSD: util.c,v 1.155 2010/06/05 13:59:39 lukem Exp $ */
  
  /*-
-  * Copyright (c) 1997-2008 The NetBSD Foundation, Inc.
+  * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
   * All rights reserved.
   *
   * This code is derived from software contributed to The NetBSD Foundation
@@@ -64,7 -64,7 +64,7 @@@
  
  #include <sys/cdefs.h>
  #ifndef lint
- __RCSID("$NetBSD: util.c,v 1.147 2008/05/10 00:05:31 skd Exp $");
+ __RCSID("$NetBSD: util.c,v 1.155 2010/06/05 13:59:39 lukem Exp $");
  #endif /* not lint */
  
  /*
@@@ -85,6 -85,7 +85,7 @@@
  #include <signal.h>
  #include <libgen.h>
  #include <limits.h>
+ #include <locale.h>
  #include <netdb.h>
  #include <stdio.h>
  #include <stdlib.h>
@@@ -103,7 -104,7 +104,7 @@@ voi
  setpeer(int argc, char *argv[])
  {
        char *host;
-       char *port;
+       const char *port;
  
        if (argc == 0)
                goto usage;
  }
  
  static void
- parse_feat(const char *line)
+ parse_feat(const char *fline)
  {
  
                        /*
                         * work-around broken ProFTPd servers that can't
-                        * even obey RFC2389.
+                        * even obey RFC 2389.
                         */
-       while (*line && isspace((int)*line))
-               line++;
+       while (*fline && isspace((int)*fline))
+               fline++;
  
-       if (strcasecmp(line, "MDTM") == 0)
+       if (strcasecmp(fline, "MDTM") == 0)
                features[FEAT_MDTM] = 1;
-       else if (strncasecmp(line, "MLST", sizeof("MLST") - 1) == 0) {
+       else if (strncasecmp(fline, "MLST", sizeof("MLST") - 1) == 0) {
                features[FEAT_MLST] = 1;
-       } else if (strcasecmp(line, "REST STREAM") == 0)
+       } else if (strcasecmp(fline, "REST STREAM") == 0)
                features[FEAT_REST_STREAM] = 1;
-       else if (strcasecmp(line, "SIZE") == 0)
+       else if (strcasecmp(fline, "SIZE") == 0)
                features[FEAT_SIZE] = 1;
-       else if (strcasecmp(line, "TVFS") == 0)
+       else if (strcasecmp(fline, "TVFS") == 0)
                features[FEAT_TVFS] = 1;
  }
  
@@@ -372,51 -373,51 +373,51 @@@ in
  ftp_login(const char *host, const char *luser, const char *lpass)
  {
        char tmp[80];
-       char *user, *pass, *acct, *p;
+       char *fuser, *pass, *facct, *p;
        char emptypass[] = "";
        const char *errormsg;
        int n, aflag, rval, nlen;
  
        aflag = rval = 0;
-       user = pass = acct = NULL;
+       fuser = pass = facct = NULL;
        if (luser)
-               user = ftp_strdup(luser);
+               fuser = ftp_strdup(luser);
        if (lpass)
                pass = ftp_strdup(lpass);
  
        DPRINTF("ftp_login: user `%s' pass `%s' host `%s'\n",
-           STRorNULL(user), STRorNULL(pass), STRorNULL(host));
+           STRorNULL(fuser), STRorNULL(pass), STRorNULL(host));
  
        /*
         * Set up arguments for an anonymous FTP session, if necessary.
         */
        if (anonftp) {
-               FREEPTR(user);
-               user = ftp_strdup("anonymous"); /* as per RFC1635 */
+               FREEPTR(fuser);
+               fuser = ftp_strdup("anonymous");        /* as per RFC 1635 */
                FREEPTR(pass);
                pass = ftp_strdup(getoptionvalue("anonpass"));
        }
  
-       if (ruserpass(host, &user, &pass, &acct) < 0) {
+       if (ruserpass(host, &fuser, &pass, &facct) < 0) {
                code = -1;
                goto cleanup_ftp_login;
        }
  
-       while (user == NULL) {
+       while (fuser == NULL) {
                if (localname)
                        fprintf(ttyout, "Name (%s:%s): ", host, localname);
                else
                        fprintf(ttyout, "Name (%s): ", host);
                errormsg = NULL;
-               nlen = getline(stdin, tmp, sizeof(tmp), &errormsg);
+               nlen = get_line(stdin, tmp, sizeof(tmp), &errormsg);
                if (nlen < 0) {
                        fprintf(ttyout, "%s; %s aborted.\n", errormsg, "login");
                        code = -1;
                        goto cleanup_ftp_login;
                } else if (nlen == 0) {
-                       user = ftp_strdup(localname);
+                       fuser = ftp_strdup(localname);
                } else {
-                       user = ftp_strdup(tmp);
+                       fuser = ftp_strdup(tmp);
                }
        }
  
                char *nuser;
                size_t len;
  
-               len = strlen(user) + 1 + strlen(host) + 1;
+               len = strlen(fuser) + 1 + strlen(host) + 1;
                nuser = ftp_malloc(len);
-               (void)strlcpy(nuser, user, len);
+               (void)strlcpy(nuser, fuser, len);
                (void)strlcat(nuser, "@",  len);
                (void)strlcat(nuser, host, len);
-               FREEPTR(user);
-               user = nuser;
+               FREEPTR(fuser);
+               fuser = nuser;
        }
  
-       n = command("USER %s", user);
+       n = command("USER %s", fuser);
        if (n == CONTINUE) {
                if (pass == NULL) {
                        p = getpass("Password: ");
        }
        if (n == CONTINUE) {
                aflag++;
-               if (acct == NULL) {
+               if (facct == NULL) {
                        p = getpass("Account: ");
                        if (p == NULL)
                                p = emptypass;
-                       acct = ftp_strdup(p);
+                       facct = ftp_strdup(p);
                        memset(p, 0, strlen(p));
                }
-               if (acct[0] == '\0') {
+               if (facct[0] == '\0') {
                        warnx("Login failed");
                        goto cleanup_ftp_login;
                }
-               n = command("ACCT %s", acct);
-               memset(acct, 0, strlen(acct));
+               n = command("ACCT %s", facct);
+               memset(facct, 0, strlen(facct));
        }
        if ((n != COMPLETE) ||
-           (!aflag && acct != NULL && command("ACCT %s", acct) != COMPLETE)) {
+           (!aflag && facct != NULL && command("ACCT %s", facct) != COMPLETE)) {
                warnx("Login failed");
                goto cleanup_ftp_login;
        }
        rval = 1;
-       username = ftp_strdup(user);
+       username = ftp_strdup(fuser);
        if (proxy)
                goto cleanup_ftp_login;
  
        updateremotecwd();
  
   cleanup_ftp_login:
-       FREEPTR(user);
+       FREEPTR(fuser);
        if (pass != NULL)
                memset(pass, 0, strlen(pass));
        FREEPTR(pass);
-       if (acct != NULL)
-               memset(acct, 0, strlen(acct));
-       FREEPTR(acct);
+       if (facct != NULL)
+               memset(facct, 0, strlen(facct));
+       FREEPTR(facct);
        return (rval);
  }
  
   * Returns false if no new arguments have been added.
   */
  int
- another(int *pargc, char ***pargv, const char *prompt)
+ another(int *pargc, char ***pargv, const char *aprompt)
  {
        const char      *errormsg;
        int             ret, nlen;
                fputs("Sorry, arguments too long.\n", ttyout);
                intr(0);
        }
-       fprintf(ttyout, "(%s) ", prompt);
+       fprintf(ttyout, "(%s) ", aprompt);
        line[len++] = ' ';
        errormsg = NULL;
-       nlen = getline(stdin, line + len, sizeof(line)-len, &errormsg);
+       nlen = get_line(stdin, line + len, sizeof(line)-len, &errormsg);
        if (nlen < 0) {
                fprintf(ttyout, "%s; %s aborted.\n", errormsg, "operation");
                intr(0);
@@@ -543,7 -544,7 +544,7 @@@ remglob(char *argv[], int doswitch, con
        char temp[MAXPATHLEN];
        int oldverbose, oldhash, oldprogress, fd;
        char *cp;
-       const char *mode;
+       const char *rmode;
        size_t len;
  
        if (!mflag || !connected) {
                progress = 0;
                if (doswitch)
                        pswitch(!proxy);
-               for (mode = "w"; *++argv != NULL; mode = "a")
-                       recvrequest("NLST", temp, *argv, mode, 0, 0);
+               for (rmode = "w"; *++argv != NULL; rmode = "a")
+                       recvrequest("NLST", temp, *argv, rmode, 0, 0);
                if ((code / 100) != COMPLETE) {
                        if (errbuf != NULL)
                                *errbuf = reply_string;
@@@ -755,11 -756,12 +756,12 @@@ remotemodtime(const char *file, int noi
                                goto bad_parse_time;
                        else
                                goto cleanup_parse_time;
-               } else
-                       DPRINTF("remotemodtime: parsed date `%s' as " LLF
+               } else {
+                       DPRINTF("remotemodtime: parsed time `%s' as " LLF
                            ", %s",
                            timestr, (LLT)rtime,
                            rfc2822time(localtime(&rtime)));
+               }
        } else {
                if (r == ERROR && code == 500 && features[FEAT_MDTM] == -1)
                        features[FEAT_MDTM] = 0;
  }
  
  /*
-  * Format tm in an RFC2822 compatible manner, with a trailing \n.
+  * Format tm in an RFC 2822 compatible manner, with a trailing \n.
   * Returns a pointer to a static string containing the result.
   */
  const char *
@@@ -786,11 -788,37 +788,37 @@@ rfc2822time(const struct tm *tm
  
        if (strftime(result, sizeof(result),
            "%a, %d %b %Y %H:%M:%S %z\n", tm) == 0)
-               errx(1, "Can't convert RFC2822 time: buffer too small");
+               errx(1, "Can't convert RFC 2822 time: buffer too small");
        return result;
  }
  
  /*
+  * Parse HTTP-date as per RFC 2616.
+  * Return a pointer to the next character of the consumed date string,
+  * or NULL if failed.
+  */
+ const char *
+ parse_rfc2616time(struct tm *parsed, const char *httpdate)
+ {
+       const char *t;
+       const char *curlocale;
+       /* The representation of %a depends on the current locale. */
+       curlocale = setlocale(LC_TIME, NULL);
+       (void)setlocale(LC_TIME, "C");
+                                                               /* RFC 1123 */
+       if ((t = strptime(httpdate, "%a, %d %b %Y %H:%M:%S GMT", parsed)) ||
+                                                               /* RFC 850 */
+           (t = strptime(httpdate, "%a, %d-%b-%y %H:%M:%S GMT", parsed)) ||
+                                                               /* asctime */
+           (t = strptime(httpdate, "%a, %b %d %H:%M:%S %Y", parsed))) {
+               ;                       /* do nothing */
+       }
+       (void)setlocale(LC_TIME, curlocale);
+       return t;
+ }
+ /*
   * Update global `localcwd', which contains the state of the local cwd
   */
  void
@@@ -808,7 -836,8 +836,8 @@@ updatelocalcwd(void
  void
  updateremotecwd(void)
  {
-       int      overbose, ocode, i;
+       int      overbose, ocode;
+       size_t   i;
        char    *cp;
  
        overbose = verbose;
@@@ -877,8 -906,8 +906,8 @@@ fileindir(const char *file, const char 
  void
  list_vertical(StringList *sl)
  {
-       int i, j;
-       int columns, lines;
+       size_t i, j;
+       size_t columns, lines;
        char *p;
        size_t w, width;
  
@@@ -1067,11 -1096,10 +1096,10 @@@ setupsockbufsize(int sock
  void
  ftpvis(char *dst, size_t dstlen, const char *src, size_t srclen)
  {
-       int     di, si;
+       size_t  di, si;
  
-       for (di = si = 0;
-           src[si] != '\0' && di < dstlen && si < srclen;
-           di++, si++) {
+       di = si = 0;
+       while (src[si] != '\0' && di < dstlen && si < srclen) {
                switch (src[si]) {
                case '\\':
                case ' ':
                case '\r':
                case '\n':
                case '"':
-                       dst[di++] = '\\';
-                       if (di >= dstlen)
+                       /*
+                        * Need room for two characters and NUL, avoiding
+                        * incomplete escape sequences at end of dst.
+                        */
+                       if (di >= dstlen - 3)
                                break;
+                       dst[di++] = '\\';
                        /* FALLTHROUGH */
                default:
-                       dst[di] = src[si];
+                       dst[di] = src[si++];
+                       if (di < dstlen)
+                               di++;
                }
        }
        dst[di] = '\0';
@@@ -1097,7 -1131,8 +1131,8 @@@ voi
  formatbuf(char *buf, size_t len, const char *src)
  {
        const char      *p, *p2, *q;
-       int              i, op, updirs, pdirs;
+       size_t           i;
+       int              op, updirs, pdirs;
  
  #define ADDBUF(x) do { \
                if (i >= len - 1) \
@@@ -1215,7 -1250,7 +1250,7 @@@ isipv6addr(const char *addr
        struct addrinfo hints, *res;
  
        memset(&hints, 0, sizeof(hints));
-       hints.ai_family = PF_INET6;
+       hints.ai_family = AF_INET6;
        hints.ai_socktype = SOCK_DGRAM; /*dummy*/
        hints.ai_flags = AI_NUMERICHOST;
        if (getaddrinfo(addr, "0", &hints, &res) != 0)
   *    -3      line was too long
   */
  int
- getline(FILE *stream, char *buf, size_t buflen, const char **errormsg)
+ get_line(FILE *stream, char *buf, size_t buflen, const char **errormsg)
  {
        int     rv, ch;
        size_t  len;
@@@ -1465,7 -1500,8 +1500,7 @@@ voi
  ftp_sl_add(StringList *sl, char *i)
  {
  
 -      if (sl_add(sl, i) == -1)
 -              err(1, "Unable to add `%s' to stringlist", i);
 +      sl_add(sl, i);
  }
  
  /*