- add support for recursive transfers (but not for floppies), e.g.
authormartynas <martynas@openbsd.org>
Tue, 8 Jul 2008 21:07:57 +0000 (21:07 +0000)
committermartynas <martynas@openbsd.org>
Tue, 8 Jul 2008 21:07:57 +0000 (21:07 +0000)
'mget -cr 4.*' would recursively fetch (-r), and resume the previous
transfers (-c) of 4.X release directories
uses local matching (fnmatch), but only for recursive transfers.
current behavior is not changed in any way.
- while here, ifndef SMALL debugging stuff, this saves some space,
for floppies
- some debugging code was enabled for non-debugging mode, checks
assume debug is set to zero, but it's not initially set
- all "Confirm with" prompts are forced, remove redundant argument
- fix usage: -C and -c are not available for SMALL

discussed a year ago w/ pyr@
looks good to millert@
previous version looked good to pyr@
man page tweaks & ok jmc@

12 files changed:
usr.bin/ftp/Makefile
usr.bin/ftp/cmds.c
usr.bin/ftp/cmdtab.c
usr.bin/ftp/complete.c
usr.bin/ftp/extern.h
usr.bin/ftp/fetch.c
usr.bin/ftp/ftp.1
usr.bin/ftp/ftp.c
usr.bin/ftp/ftp_var.h
usr.bin/ftp/list.c [new file with mode: 0644]
usr.bin/ftp/main.c
usr.bin/ftp/util.c

index b2e4e80..bcdc8ee 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.22 2007/06/13 13:52:26 pyr Exp $
+#      $OpenBSD: Makefile,v 1.23 2008/07/08 21:07:57 martynas Exp $
 
 # Define SMALL to disable command line editing and https support
 #CFLAGS+=-DSMALL
@@ -12,8 +12,8 @@ LDADD += -lsocks5
 .endif
 
 PROG=  ftp
-SRCS=  cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c ruserpass.c \
-       cookie.c stringlist.c util.c
+SRCS=  cmds.c cmdtab.c complete.c cookie.c domacro.c fetch.c ftp.c list.c \
+       main.c ruserpass.c stringlist.c util.c
 
 CPPFLAGS+= -DINET6
 
index d04ab8c..b97454c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cmds.c,v 1.62 2008/06/25 18:07:00 martynas Exp $      */
+/*     $OpenBSD: cmds.c,v 1.63 2008/07/08 21:07:57 martynas Exp $      */
 /*     $NetBSD: cmds.c,v 1.27 1997/08/18 10:20:15 lukem Exp $  */
 
 /*
@@ -60,7 +60,7 @@
  */
 
 #if !defined(lint) && !defined(SMALL)
-static const char rcsid[] = "$OpenBSD: cmds.c,v 1.62 2008/06/25 18:07:00 martynas Exp $";
+static const char rcsid[] = "$OpenBSD: cmds.c,v 1.63 2008/07/08 21:07:57 martynas Exp $";
 #endif /* not lint and not SMALL */
 
 /*
@@ -74,6 +74,9 @@ static const char rcsid[] = "$OpenBSD: cmds.c,v 1.62 2008/06/25 18:07:00 martyna
 
 #include <ctype.h>
 #include <err.h>
+#ifndef SMALL
+#include <fnmatch.h>
+#endif /* !SMALL */
 #include <glob.h>
 #include <netdb.h>
 #include <stdio.h>
@@ -162,7 +165,11 @@ changetype(int newtype, int show)
                newtype = TYPE_I;
        if (newtype == curtype)
                return;
-       if (debug == 0 && show == 0)
+       if (
+#ifndef SMALL
+           !debug &&
+#endif /* !SMALL */
+           show == 0)
                verbose = 0;
        for (p = types; p->t_name; p++)
                if (newtype == p->t_type)
@@ -372,10 +379,9 @@ usage:
        }
 
 #ifndef SMALL
-       optind--;
-       argv[optind] = argv[0];
-       argc -= optind;
-       argv += optind;
+       argv[optind - 1] = argv[0];
+       argc -= optind - 1;
+       argv += optind - 1;
 #endif /* !SMALL */
 
        mname = argv[0];
@@ -391,7 +397,7 @@ usage:
                                mflag = 0;
                                continue;
                        }
-                       if (mflag && confirm(argv[0], cp, 0)) {
+                       if (mflag && confirm(argv[0], cp)) {
                                tp = cp;
                                if (mcase) {
                                        while (*tp && !islower(*tp)) {
@@ -433,8 +439,7 @@ usage:
                                    cp != tp || !interactive);
                                restart_point = 0;
                                if (!mflag && fromatty) {
-                                       if (confirm("Continue with",
-                                           argv[0], 1))
+                                       if (confirm(argv[0], NULL))
                                                mflag = 1;
                                }
                        }
@@ -449,7 +454,7 @@ usage:
                int flags;
 
                if (!doglob) {
-                       if (mflag && confirm(argv[0], argv[i], 0)) {
+                       if (mflag && confirm(argv[0], argv[i])) {
                                tp = (ntflag) ? dotrans(argv[i]) : argv[i];
                                tp = (mapflag) ? domap(tp) : tp;
 #ifndef SMALL
@@ -468,8 +473,7 @@ usage:
                                    tp != argv[i] || !interactive);
                                restart_point = 0;
                                if (!mflag && fromatty) {
-                                       if (confirm("Continue with",
-                                           argv[0], 1))
+                                       if (confirm(argv[0], NULL))
                                                mflag = 1;
                                }
                        }
@@ -484,7 +488,7 @@ usage:
                        continue;
                }
                for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
-                       if (mflag && confirm(argv[0], *cpp, 0)) {
+                       if (mflag && confirm(argv[0], *cpp)) {
                                tp = (ntflag) ? dotrans(*cpp) : *cpp;
                                tp = (mapflag) ? domap(tp) : tp;
 #ifndef SMALL
@@ -503,8 +507,7 @@ usage:
                                    *cpp != tp || !interactive);
                                restart_point = 0;
                                if (!mflag && fromatty) {
-                                       if (confirm("Continue with",
-                                           argv[0], 1))
+                                       if (confirm(argv[0], NULL))
                                                mflag = 1;
                                }
                        }
@@ -630,7 +633,7 @@ mabort(int signo)
        putc('\n', ttyout);
        (void)fflush(ttyout);
        if (mflag && fromatty)
-               if (confirm("Continue with", mname, 1))
+               if (confirm(mname, NULL))
                        longjmp(jabort, 1);
        mflag = 0;
        longjmp(jabort, 1);
@@ -644,17 +647,26 @@ mget(int argc, char *argv[])
 {
        extern int optind, optreset;
        sig_t oldintr;
-       int ch, restartit = 0;
+       int ch;
        char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN], localcwd[MAXPATHLEN];
+#ifndef SMALL
+       int i = 1, restartit = 0, xargc = 2;
+       char type = NULL, *xargv[] = {argv[0], ".", NULL, NULL};
+       FILE *ftemp = NULL;
+       static int depth = 0;
+#endif /* !SMALL */
 
        optind = optreset = 1;
 
 #ifndef SMALL
-       while ((ch = getopt(argc, argv, "c")) != -1) {
+       while ((ch = getopt(argc, argv, "cr")) != -1) {
                switch(ch) {
                case 'c':
                        restartit = 1;
                        break;
+               case 'r':
+                       depth++;
+                       break;
                default:
                        goto usage;
                }
@@ -663,16 +675,15 @@ mget(int argc, char *argv[])
 
        if (argc - optind < 1 && !another(&argc, &argv, "remote-files")) {
 usage:
-               fprintf(ttyout, "usage: %s [-c] remote-files\n", argv[0]);
+               fprintf(ttyout, "usage: %s [-cr] remote-files\n", argv[0]);
                code = -1;
                return;
        }
 
 #ifndef SMALL
-       optind--;
-       argv[optind] = argv[0];
-       argc -= optind;
-       argv += optind;
+       argv[optind - 1] = argv[0];
+       argc -= optind - 1;
+       argv += optind - 1;
 #endif /* !SMALL */
 
        mname = argv[0];
@@ -682,19 +693,80 @@ usage:
 
        oldintr = signal(SIGINT, mabort);
        (void)setjmp(jabort);
-       while ((cp = remglob(argv, proxy, NULL)) != NULL) {
+       while ((cp =
+#ifndef SMALL
+           depth ? remglob2(xargv, proxy, NULL, &ftemp, &type) :
+#endif /* !SMALL */
+           remglob(argv, proxy, NULL)) != NULL
+#ifndef SMALL
+           || (mflag && depth && ++i < argc)
+#endif /* !SMALL */
+           ) {
+#ifndef SMALL
+               if (cp == NULL)
+                       continue;
+#endif /* !SMALL */
                if (*cp == '\0') {
                        mflag = 0;
                        continue;
                }
                if (!mflag)
                        continue;
+#ifndef SMALL
+               if (depth && fnmatch(argv[i], cp, FNM_PATHNAME) != 0)
+                       continue;
+#endif /* !SMALL */
                if (!fileindir(cp, localcwd)) {
                        fprintf(ttyout, "Skipping non-relative filename `%s'\n",
                            cp);
                        continue;
                }
-               if (confirm(argv[0], cp, 0)) {
+               if (confirm(argv[0], cp)) {
+#ifndef SMALL
+                       if (type == 'd') {
+                               mkdir(cp, 0755);
+                               if (chdir(cp) != 0) {
+                                       warn("local: %s", cp);
+                                       continue;
+                               }
+
+                               xargv[1] = cp;
+                               xargv[2] = NULL;
+                               xargc = 2;
+                               cd(xargc, xargv);
+                               if (dirchange != 1)
+                                       goto out;
+
+                               xargv[1] = (restartit == 1) ? "-cr" : "-r";
+                               xargv[2] = "*";
+                               xargv[3] = NULL;
+                               xargc = 3;
+                               mget(xargc, xargv);
+
+                               xargv[1] = "..";
+                               xargv[2] = NULL;
+                               xargc = 2;
+                               cd(xargc, xargv);
+                               if (dirchange != 1) {
+                                       mflag = 0;
+                                       goto out;
+                               }
+
+out:
+                               if (chdir("..") != 0) {
+                                       warn("local: %s", cp);
+                                       mflag = 0;
+                               }
+
+                               xargv[1] = ".";
+                               xargv[2] = NULL;
+                               xargc = 2;
+                               continue;
+                       }
+                       if (type == 's')
+                               /* Currently ignored. */
+                               continue;
+#endif /* !SMALL */
                        tp = cp;
                        if (mcase) {
                                for (tp2 = tmpbuf; (ch = *tp++) != 0; )
@@ -719,13 +791,20 @@ usage:
                            tp != cp || !interactive, 1);
                        restart_point = 0;
                        if (!mflag && fromatty) {
-                               if (confirm("Continue with", argv[0], 1))
+                               if (confirm(argv[0], NULL))
                                        mflag = 1;
                        }
                }
        }
        (void)signal(SIGINT, oldintr);
+#ifndef SMALL
+       if (depth)
+               depth--;
+       if (depth == 0 || mflag == 0)
+               depth = mflag = 0;
+#else /* !SMALL */
        mflag = 0;
+#endif /* !SMALL */
 }
 
 char *
@@ -833,10 +912,10 @@ setbell(int argc, char *argv[])
        code = togglevar(argc, argv, &bell, "Bell mode");
 }
 
-#ifndef SMALL
 /*
  * Set command line editing
  */
+#ifndef SMALL
 /*ARGSUSED*/
 void
 setedit(int argc, char *argv[])
@@ -1021,6 +1100,7 @@ setpreserve(int argc, char *argv[])
 /*
  * Set debugging mode on/off and/or set level of debugging.
  */
+#ifndef SMALL
 /*ARGSUSED*/
 void
 setdebug(int argc, char *argv[])
@@ -1056,6 +1136,7 @@ setdebug(int argc, char *argv[])
        fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug);
        code = debug > 0;
 }
+#endif /* !SMALL */
 
 /*
  * Set current working directory on remote machine.
@@ -1158,10 +1239,10 @@ mdelete(int argc, char *argv[])
                        mflag = 0;
                        continue;
                }
-               if (mflag && confirm(argv[0], cp, 0)) {
+               if (mflag && confirm(argv[0], cp)) {
                        (void)command("DELE %s", cp);
                        if (!mflag && fromatty) {
-                               if (confirm("Continue with", argv[0], 1))
+                               if (confirm(argv[0], NULL))
                                        mflag = 1;
                        }
                }
@@ -1215,7 +1296,7 @@ ls(int argc, char *argv[])
        }
        globargv2 = argv[2];
        if (strcmp(argv[2], "-") && *argv[2] != '|' && (!globulize(&argv[2]) ||
-           !confirm("output to local-file:", argv[2], 0))) {
+           !confirm("output to local-file:", argv[2]))) {
                code = -1;
                goto freels;
        }
@@ -1252,7 +1333,7 @@ usage:
        argv[argc - 1] = NULL;
        if (strcmp(dest, "-") && *dest != '|')
                if (!globulize(&dest) ||
-                   !confirm("output to local-file:", dest, 0)) {
+                   !confirm("output to local-file:", dest)) {
                        code = -1;
                        return;
        }
@@ -1264,7 +1345,7 @@ usage:
                *lmode = (i == 1) ? 'w' : 'a';
                recvrequest("LIST", dest, argv[i], lmode, 0, 0);
                if (!mflag && fromatty) {
-                       if (confirm("Continue with", argv[0], 1))
+                       if (confirm(argv[0], NULL))
                                mflag ++;
                }
        }
@@ -1303,11 +1384,13 @@ shell(int argc, char *argv[])
                (void)strlcpy(shellnam + 1, ++namep, sizeof(shellnam) - 1);
                if (strcmp(namep, "sh") != 0)
                        shellnam[0] = '+';
+#ifndef SMALL
                if (debug) {
                        fputs(shellp, ttyout);
                        fputc('\n', ttyout);
                        (void)fflush(ttyout);
                }
+#endif /* !SMALL */
                if (argc > 1) {
                        execl(shellp, shellnam, "-c", altarg, (char *)0);
                }
index 07744ae..bc84d93 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cmdtab.c,v 1.22 2008/06/25 21:15:19 martynas Exp $    */
+/*     $OpenBSD: cmdtab.c,v 1.23 2008/07/08 21:07:57 martynas Exp $    */
 /*     $NetBSD: cmdtab.c,v 1.17 1997/08/18 10:20:17 lukem Exp $        */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #if !defined(lint) && !defined(SMALL)
-static const char rcsid[] = "$OpenBSD: cmdtab.c,v 1.22 2008/06/25 21:15:19 martynas Exp $";
+static const char rcsid[] = "$OpenBSD: cmdtab.c,v 1.23 2008/07/08 21:07:57 martynas Exp $";
 #endif /* not lint and not SMALL */
 
 #include <stdio.h>
@@ -148,7 +148,9 @@ struct cmd cmdtab[] = {
        { "chmod",      H(chmodhelp),   0, 1, 1, CMPL(nr)       do_chmod },
        { "close",      H(disconhelp),  0, 1, 1, CMPL0          disconnect },
        { "cr",         H(crhelp),      0, 0, 0, CMPL0          setcr },
+#ifndef SMALL
        { "debug",      H(debughelp),   0, 0, 0, CMPL0          setdebug },
+#endif /* !SMALL */
        { "delete",     H(deletehelp),  0, 1, 1, CMPL(r)        deletecmd },
        { "dir",        H(dirhelp),     1, 1, 1, CMPL(rl)       ls },
        { "disconnect", H(disconhelp),  0, 1, 1, CMPL0          disconnect },
index 147f4bf..c2224af 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: complete.c,v 1.20 2008/06/26 05:42:20 ray Exp $       */
+/*     $OpenBSD: complete.c,v 1.21 2008/07/08 21:07:57 martynas Exp $  */
 /*     $NetBSD: complete.c,v 1.10 1997/08/18 10:20:18 lukem Exp $      */
 
 /*-
@@ -32,7 +32,7 @@
 
 #ifndef SMALL
 #ifndef lint
-static const char rcsid[] = "$OpenBSD: complete.c,v 1.20 2008/06/26 05:42:20 ray Exp $";
+static const char rcsid[] = "$OpenBSD: complete.c,v 1.21 2008/07/08 21:07:57 martynas Exp $";
 #endif /* not lint */
 
 /*
@@ -234,8 +234,10 @@ complete_remote(char *word, int list)
 
                mflag = 1;
                emesg = NULL;
+#ifndef SMALL
                if (debug)
                        (void)putc('\n', ttyout);
+#endif /* !SMALL */
                while ((cp = remglob(dummyargv, 0, &emesg)) != NULL) {
                        char *tcp;
 
index 7d3c323..5afc887 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.34 2008/06/25 21:15:19 martynas Exp $    */
+/*     $OpenBSD: extern.h,v 1.35 2008/07/08 21:07:57 martynas Exp $    */
 /*     $NetBSD: extern.h,v 1.17 1997/08/18 10:20:19 lukem Exp $        */
 
 /*
@@ -82,7 +82,7 @@ int   command(const char *, ...);
 unsigned char complete(EditLine *, int);
 void   controlediting(void);
 #endif /* !SMALL */
-int    confirm(const char *, const char *, int);
+int    confirm(const char *, const char *);
 FILE   *dataconn(const char *);
 void   deletecmd(int, char **);
 void   disconnect(int, char **);
@@ -142,6 +142,9 @@ void    recvrequest(const char *, const char *, const char *,
            const char *, int, int);
 void   reget(int, char **);
 char   *remglob(char **, int, char **);
+#ifndef SMALL
+char   *remglob2(char **, int, char **, FILE **ftemp, char *type);
+#endif /* !SMALL */
 off_t  remotesize(const char *, int);
 time_t remotemodtime(const char *, int);
 void   removedir(int, char **);
@@ -157,7 +160,9 @@ void        setbell(int, char **);
 void   setbinary(int, char **);
 void   setcase(int, char **);
 void   setcr(int, char **);
+#ifndef SMALL
 void   setdebug(int, char **);
+#endif /* !SMALL */
 void   setedit(int, char **);
 void   setepsv4(int, char **);
 void   setform(int, char **);
@@ -195,6 +200,7 @@ void        user(int, char **);
 int    ruserpass(const char *, char **, char **, char **);
 void   cookie_load(void);
 void   cookie_get(const char *, const char *, int, char **);
+void   parse_list(char **, char *);
 #endif /* !SMALL */
 
 
index dffed5d..e0afe8d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fetch.c,v 1.79 2008/06/26 05:42:20 ray Exp $  */
+/*     $OpenBSD: fetch.c,v 1.80 2008/07/08 21:07:57 martynas Exp $     */
 /*     $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */
 
 /*-
@@ -31,7 +31,7 @@
  */
 
 #if !defined(lint) && !defined(SMALL)
-static const char rcsid[] = "$OpenBSD: fetch.c,v 1.79 2008/06/26 05:42:20 ray Exp $";
+static const char rcsid[] = "$OpenBSD: fetch.c,v 1.80 2008/07/08 21:07:57 martynas Exp $";
 #endif /* not lint and not SMALL */
 
 /*
@@ -353,9 +353,11 @@ url_get(const char *origline, const char *proxyenv, const char *outfile)
        if (portnum != NULL)
                *portnum++ = '\0';
 
+#ifndef SMALL
        if (debug)
                fprintf(ttyout, "host %s, port %s, path %s, save as %s.\n",
                    host, portnum, path, savefile);
+#endif /* !SMALL */
 
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = family;
@@ -558,8 +560,10 @@ again:
 
        while (len > 0 && (buf[len-1] == '\r' || buf[len-1] == '\n'))
                buf[--len] = '\0';
+#ifndef SMALL
        if (debug)
                fprintf(ttyout, "received '%s'\n", buf);
+#endif /* !SMALL */
 
        cp = strchr(buf, ' ');
        if (cp == NULL)
@@ -616,8 +620,10 @@ again:
                        buf[--len] = '\0';
                if (len == 0)
                        break;
+#ifndef SMALL
                if (debug)
                        fprintf(ttyout, "received '%s'\n", buf);
+#endif /* !SMALL */
 
                /* Look for some headers */
                cp = buf;
@@ -974,11 +980,13 @@ bad_ftp_url:
                                dir = NULL;
                        }
                }
+#ifndef SMALL
                if (debug)
                        fprintf(ttyout,
                            "user %s:%s host %s port %s dir %s file %s\n",
                            username, pass ? "XXXX" : NULL, host, portnum,
                            dir, file);
+#endif /* !SMALL */
 
                /*
                 * Set up the connection.
@@ -1276,8 +1284,10 @@ proxy_connect(int socket, char *host)
        l = asprintf(&connstr, "CONNECT %s:%s HTTP/1.1\n\n", host, port);
        if (l == -1)
                errx(1, "Could not allocate memory to assemble connect string!");
+#ifndef SMALL
        if (debug)
                printf("%s", connstr);
+#endif /* !SMALL */
        if (write(socket, connstr, l) != l)
                err(1, "Could not send connect string");
        read(socket, &buf, sizeof(buf)); /* only proxy header XXX: error handling? */
index 7471497..f817cf1 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ftp.1,v 1.70 2008/06/25 18:07:00 martynas Exp $
+.\"    $OpenBSD: ftp.1,v 1.71 2008/07/08 21:07:57 martynas Exp $
 .\"    $NetBSD: ftp.1,v 1.22 1997/08/18 10:20:22 lukem Exp $
 .\"
 .\" Copyright (c) 1985, 1989, 1990, 1993
@@ -30,7 +30,7 @@
 .\"
 .\"    @(#)ftp.1       8.3 (Berkeley) 10/9/94
 .\"
-.Dd $Mdocdate: June 25 2008 $
+.Dd $Mdocdate: July 8 2008 $
 .Dt FTP 1
 .Os
 .Sh NAME
@@ -557,7 +557,7 @@ on the remote machine.
 A synonym for
 .Ic mls .
 .It Xo Ic mget
-.Op Fl c
+.Op Fl cr
 .Ar remote-files
 .Xc
 Expand the
@@ -566,11 +566,6 @@ on the remote machine
 and do a
 .Ic get
 for each file name thus produced.
-If the
-.Fl c
-flag is specified, then
-.Ic reget
-is used instead for the partially transferred files.
 See
 .Ic glob
 for details on the filename expansion.
@@ -585,6 +580,19 @@ which can be changed with
 .Ql lcd directory ;
 new local directories can be created with
 .Ql "\&! mkdir directory" .
+.Pp
+If the
+.Fl c
+flag is specified then
+.Ic reget
+is used instead of
+.Ic get .
+If the
+.Fl r
+flag is specified,
+.Nm
+recursively descends the directory tree,
+transferring all files and directories.
 .It Ic mkdir Ar directory-name
 Make a directory on the remote machine.
 .It Ic mls Ar remote-files local-file
@@ -621,11 +629,6 @@ Expand wild cards in the list of local files given as arguments
 and do a
 .Ic put
 for each file in the resulting list.
-If the
-.Fl c
-flag is specified, then
-.Ic reput
-is used instead for the partially transferred files.
 See
 .Ic glob
 for details of filename expansion.
@@ -634,6 +637,13 @@ Resulting file names will then be processed according to
 and
 .Ic nmap
 settings.
+.Pp
+If the
+.Fl c
+flag is specified then
+.Ic reput
+is used instead of
+.Ic put .
 .It Ic msend Ar local-files
 A synonym for
 .Ic mput .
@@ -1638,3 +1648,8 @@ to and from
 .Bx 4.2
 servers using the ASCII type.
 Avoid this problem by using the binary image type.
+.Pp
+In the recursive mode of
+.Ic mget ,
+files and directories starting with whitespace are ignored
+because the list cannot be parsed any other way.
index 4055b6a..44f4297 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ftp.c,v 1.72 2008/06/25 21:15:19 martynas Exp $       */
+/*     $OpenBSD: ftp.c,v 1.73 2008/07/08 21:07:57 martynas Exp $       */
 /*     $NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $   */
 
 /*
@@ -60,7 +60,7 @@
  */
 
 #if !defined(lint) && !defined(SMALL)
-static const char rcsid[] = "$OpenBSD: ftp.c,v 1.72 2008/06/25 21:15:19 martynas Exp $";
+static const char rcsid[] = "$OpenBSD: ftp.c,v 1.73 2008/07/08 21:07:57 martynas Exp $";
 #endif /* not lint and not SMALL */
 
 #include <sys/types.h>
@@ -257,12 +257,13 @@ hookup(char *host, char *port)
        }
 #ifdef SO_OOBINLINE
        {
-       int on = 1;
+       int ret, on = 1;
 
-       if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
-               < 0 && debug) {
-                       warn("setsockopt");
-               }
+       ret = setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on));
+#ifndef SMALL
+       if (ret < 0 && debug)
+               warn("setsockopt");
+#endif /* !SMALL */
        }
 #endif /* SO_OOBINLINE */
 
@@ -294,6 +295,7 @@ command(const char *fmt, ...)
        sig_t oldintr;
 
        abrtflag = 0;
+#ifndef SMALL
        if (debug) {
                fputs("---> ", ttyout);
                va_start(ap, fmt);
@@ -307,6 +309,7 @@ command(const char *fmt, ...)
                putc('\n', ttyout);
                (void)fflush(ttyout);
        }
+#endif /* !SMALL */
        if (cout == NULL) {
                warnx("No control connection for command.");
                code = -1;
@@ -338,8 +341,10 @@ static int current_nop_pos = 0;            /* 0 -> no noop started */
 void 
 send_noop_char()
 {
+#ifndef SMALL
        if (debug)
                fprintf(ttyout, "---> %c\n", noop[current_nop_pos]);
+#endif /* !SMALL */
        fputc(noop[current_nop_pos++], cout);
        (void)fflush(cout);
        if (current_nop_pos >= NOOP_LENGTH) {
@@ -363,8 +368,10 @@ may_receive_noop_ack()
        /* finish sending last incomplete noop */
        if (current_nop_pos != 0) {
                fputs(&(noop[current_nop_pos]), cout);
+#ifndef SMALL
                if (debug)
                        fprintf(ttyout, "---> %s\n", &(noop[current_nop_pos]));
+#endif /* !SMALL */
                (void)fflush(cout);
                current_nop_pos = 0;
                full_noops_sent++;
@@ -1245,10 +1252,12 @@ reinit:
                        warn("socket");
                        return (1);
                }
+#ifndef SMALL
                if ((options & SO_DEBUG) &&
                    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
                               sizeof(on)) < 0)
                        warn("setsockopt (ignored)");
+#endif /* !SMALL */
                switch (data_addr.su_family) {
                case AF_INET:
                        if (epsv4 && !epsv4bad) {
@@ -1270,11 +1279,13 @@ reinit:
                                }
                                if (result != COMPLETE) {
                                        epsv4bad = 1;
+#ifndef SMALL
                                        if (debug) {
                                                fputs(
 "disabling epsv4 for this connection\n",
                                                    ttyout);
                                        }
+#endif /* !SMALL */
                                }
                        }
                        if (result != COMPLETE)
@@ -1513,10 +1524,12 @@ noport:
                warn("bind");
                goto bad;
        }
+#ifndef SMALL
        if (options & SO_DEBUG &&
            setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
                        sizeof(on)) < 0)
                warn("setsockopt (ignored)");
+#endif /* !SMALL */
        namelen = sizeof(data_addr);
        if (getsockname(data, (struct sockaddr *)&data_addr, &namelen) < 0) {
                warn("getsockname");
@@ -1553,11 +1566,13 @@ noport:
                                    af_tmp, hname, pbuf);
                                if (result != COMPLETE) {
                                        epsv4bad = 1;
+#ifndef SMALL
                                        if (debug) {
                                                fputs(
 "disabling epsv4 for this connection\n",
                                                    ttyout);
                                        }
+#endif /* !SMALL */
                                }
                        }
                        break;
index 8a2e976..0599078 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ftp_var.h,v 1.26 2008/06/25 21:15:19 martynas Exp $   */
+/*     $OpenBSD: ftp_var.h,v 1.27 2008/07/08 21:07:57 martynas Exp $   */
 /*     $NetBSD: ftp_var.h,v 1.18 1997/08/18 10:20:25 lukem Exp $       */
 
 /*
@@ -110,7 +110,9 @@ int connected;              /* 1 = connected to server, -1 = logged in */
 int    fromatty;               /* input is from a terminal */
 int    interactive;            /* interactively prompt on m* cmds */
 int    confirmrest;            /* confirm rest of current m* cmd */
+#ifndef SMALL
 int    debug;                  /* debugging level */
+#endif /* !SMALL */
 int    bell;                   /* ring bell on cmd completion */
 int    doglob;                 /* glob local file names */
 int    autologin;              /* establish user account on connection */
diff --git a/usr.bin/ftp/list.c b/usr.bin/ftp/list.c
new file mode 100644 (file)
index 0000000..909b759
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2008 Martynas Venckus <martynas@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SMALL
+#include <string.h>
+
+void
+parse_unix(char **line, char *type)
+{
+       char *tok;
+       int field = 0;
+
+       while ((tok = strsep(line, " \t")) != NULL) {
+               if (*tok == '\0')
+                       continue;
+
+               if (field == 0)
+                       *type = *tok;
+
+               if (field == 7) {
+                       while (**line == ' ' || **line == '\t')
+                               (*line)++;
+                       break;
+               }
+
+               field++;
+       }
+}
+
+void
+parse_windows(char **line, char *type)
+{
+       char *tok;
+       int field = 0;
+
+       *type = '-';
+       while ((tok = strsep(line, " \t")) != NULL) {
+               if (*tok == '\0')
+                       continue;
+
+               if (field == 2 && strcmp(tok, "<DIR>") == 0)
+                       *type = 'd';
+
+               if (field == 2) {
+                       while (**line == ' ' || **line == '\t')
+                               (*line)++;
+                       break;
+               }
+
+               field++;
+       }
+}
+
+void
+parse_list(char **line, char *type)
+{
+       if (**line >= '0' && **line <= '9')
+               return parse_windows(line, type);
+
+       return parse_unix(line, type);
+}
+
+#endif /* !SMALL */
index 02b96f1..90e247f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: main.c,v 1.69 2008/06/25 21:15:19 martynas Exp $      */
+/*     $OpenBSD: main.c,v 1.70 2008/07/08 21:07:57 martynas Exp $      */
 /*     $NetBSD: main.c,v 1.24 1997/08/18 10:20:26 lukem Exp $  */
 
 /*
@@ -66,7 +66,7 @@ static const char copyright[] =
 #endif /* not lint */
 
 #if !defined(lint) && !defined(SMALL)
-static const char rcsid[] = "$OpenBSD: main.c,v 1.69 2008/06/25 21:15:19 martynas Exp $";
+static const char rcsid[] = "$OpenBSD: main.c,v 1.70 2008/07/08 21:07:57 martynas Exp $";
 #endif /* not lint and not SMALL */
 
 /*
@@ -212,8 +212,10 @@ main(volatile int argc, char *argv[])
                        break;
 
                case 'd':
+#ifndef SMALL
                        options |= SO_DEBUG;
                        debug++;
+#endif /* !SMALL */
                        break;
 
                case 'E':
@@ -764,17 +766,33 @@ void
 usage(void)
 {
        (void)fprintf(stderr,
-           "usage: %s [-46AadEegimnptVv] [-k seconds] "
+           "usage: %s [-46Aa"
+#ifndef SMALL
+           "d"
+#endif /* !SMALL */
+           "EegimnptVv] [-k seconds] "
            "[-P port] [-r seconds] [host [port]]\n"
-           "       %s [-C] [-o output] "
+           "       %s "
+#ifndef SMALL
+           "[-C] "
+#endif /* !SMALL */
+           "[-o output] "
            "ftp://[user:password@]host[:port]/file[/]\n"
-           "       %s [-C] [-c cookie] [-o output] "
+           "       %s "
+#ifndef SMALL
+           "[-C] [-c cookie] "
+#endif /* !SMALL */
+           "[-o output] "
            "http://host[:port]/file\n"
 #ifndef SMALL
            "       %s [-C] [-c cookie] [-o output] "
            "https://host[:port]/file\n"
 #endif /* !SMALL */
-           "       %s [-C] [-o output] host:[/path/]file[/]\n",
+           "       %s "
+#ifndef SMALL
+           "[-C] "
+#endif /* !SMALL */
+           "[-o output] host:[/path/]file[/]\n",
 #ifndef SMALL
            __progname, __progname, __progname, __progname, __progname);
 #else /* !SMALL */
index 95a9821..9bed927 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: util.c,v 1.53 2008/06/26 05:42:20 ray Exp $   */
+/*     $OpenBSD: util.c,v 1.54 2008/07/08 21:07:57 martynas Exp $      */
 /*     $NetBSD: util.c,v 1.12 1997/08/18 10:20:27 lukem Exp $  */
 
 /*-
@@ -64,7 +64,7 @@
  */
 
 #if !defined(lint) && !defined(SMALL)
-static const char rcsid[] = "$OpenBSD: util.c,v 1.53 2008/06/26 05:42:20 ray Exp $";
+static const char rcsid[] = "$OpenBSD: util.c,v 1.54 2008/07/08 21:07:57 martynas Exp $";
 #endif /* not lint and not SMALL */
 
 /*
@@ -174,7 +174,9 @@ setpeer(int argc, char *argv[])
  * system and not checking this out. This way they have to think about it.
  */
                overbose = verbose;
-               if (debug == 0)
+#ifndef SMALL
+               if (!debug)
+#endif /* !SMALL */
                        verbose = -1;
                if (command("SYST") == COMPLETE && overbose) {
                        char *cp, c;
@@ -364,22 +366,24 @@ another(int *pargc, char ***pargv, const char *prompt)
  * glob files given in argv[] from the remote server.
  * if errbuf isn't NULL, store error messages there instead
  * of writing to the screen.
+ * if type isn't NULL, use LIST instead of NLST, and store filetype.
+ * 'd' means directory, 's' means symbolic link, '-' means plain
+ * file.
  */
 char *
-remglob(char *argv[], int doswitch, char **errbuf)
+remglob2(char *argv[], int doswitch, char **errbuf, FILE **ftemp, char *type)
 {
-       char temp[MAXPATHLEN], *cp, *lmode;
+       char temp[MAXPATHLEN], *bufp, *cp, *lmode;
        static char buf[MAXPATHLEN], **args;
-       static FILE *ftemp = NULL;
        int oldverbose, oldhash, fd;
 
        if (!mflag) {
                if (!doglob)
                        args = NULL;
                else {
-                       if (ftemp) {
-                               (void)fclose(ftemp);
-                               ftemp = NULL;
+                       if (*ftemp) {
+                               (void)fclose(*ftemp);
+                               *ftemp = NULL;
                        }
                }
                return (NULL);
@@ -391,7 +395,7 @@ remglob(char *argv[], int doswitch, char **errbuf)
                        args = NULL;
                return (cp);
        }
-       if (ftemp == NULL) {
+       if (*ftemp == NULL) {
                int len;
 
                if ((cp = getenv("TMPDIR")) == NULL || *cp == '\0')
@@ -419,7 +423,8 @@ remglob(char *argv[], int doswitch, char **errbuf)
                if (doswitch)
                        pswitch(!proxy);
                for (lmode = "w"; *++argv != NULL; lmode = "a")
-                       recvrequest("NLST", temp, *argv, lmode, 0, 0);
+                       recvrequest(type ? "LIST" : "NLST", temp, *argv, lmode,
+                           0, 0);
                if ((code / 100) != COMPLETE) {
                        if (errbuf != NULL)
                                *errbuf = reply_string;
@@ -428,9 +433,9 @@ remglob(char *argv[], int doswitch, char **errbuf)
                        pswitch(!proxy);
                verbose = oldverbose;
                hash = oldhash;
-               ftemp = fopen(temp, "r");
+               *ftemp = fopen(temp, "r");
                (void)unlink(temp);
-               if (ftemp == NULL) {
+               if (*ftemp == NULL) {
                        if (errbuf == NULL)
                                fputs("can't find list of remote files, oops.\n",
                                    ttyout);
@@ -440,26 +445,50 @@ remglob(char *argv[], int doswitch, char **errbuf)
                        return (NULL);
                }
        }
-       if (fgets(buf, sizeof(buf), ftemp) == NULL) {
-               (void)fclose(ftemp);
-               ftemp = NULL;
+again:
+       if (fgets(buf, sizeof(buf), *ftemp) == NULL) {
+               (void)fclose(*ftemp);
+               *ftemp = NULL;
                return (NULL);
        }
 
        buf[strcspn(buf, "\n")] = '\0';
+       bufp = buf;
+
+#ifndef SMALL
+       if (type) {
+               parse_list(&bufp, type);
+               if (!bufp)
+                       goto again;
+       }
+#endif /* !SMALL */
+
+       return (bufp);
+}
+
+/*
+ * wrapper for remglob2
+ */
+char *
+remglob(char *argv[], int doswitch, char **errbuf)
+{
+       static FILE *ftemp = NULL;
 
-       return (buf);
+       return remglob2(argv, doswitch, errbuf, &ftemp, NULL);
 }
 
 int
-confirm(const char *cmd, const char *file, int force)
+confirm(const char *cmd, const char *file)
 {
        char str[BUFSIZ];
 
-       if (!force && (confirmrest || !interactive))
+       if (file && (confirmrest || !interactive))
                return (1);
 top:
-       fprintf(ttyout, "%s %s? ", cmd, file);
+       if (file)
+               fprintf(ttyout, "%s %s? ", cmd, file);
+       else
+               fprintf(ttyout, "Continue with %s? ", cmd);
        (void)fflush(ttyout);
        if (fgets(str, sizeof(str), stdin) == NULL)
                goto quit;
@@ -545,7 +574,9 @@ remotesize(const char *file, int noisy)
 
        overbose = verbose;
        size = -1;
-       if (debug == 0)
+#ifndef SMALL
+       if (!debug)
+#endif /* !SMALL */
                verbose = -1;
        if (command("SIZE %s", file) == COMPLETE) {
                char *cp, *ep;
@@ -557,7 +588,11 @@ remotesize(const char *file, int noisy)
                        if (*ep != '\0' && !isspace(*ep))
                                size = -1;
                }
-       } else if (noisy && debug == 0) {
+       } else if (noisy
+#ifndef SMALL
+           && !debug
+#endif /* !SMALL */
+           ) {
                fputs(reply_string, ttyout);
                fputc('\n', ttyout);
        }
@@ -578,7 +613,9 @@ remotemodtime(const char *file, int noisy)
        overbose = verbose;
        ocode = code;
        rtime = -1;
-       if (debug == 0)
+#ifndef SMALL
+       if (!debug)
+#endif /* !SMALL */
                verbose = -1;
        if (command("MDTM %s", file) == COMPLETE) {
                struct tm timebuf;
@@ -614,11 +651,19 @@ remotemodtime(const char *file, int noisy)
                timebuf.tm_year = yy - TM_YEAR_BASE;
                timebuf.tm_isdst = -1;
                rtime = mktime(&timebuf);
-               if (rtime == -1 && (noisy || debug != 0))
+               if (rtime == -1 && (noisy
+#ifndef SMALL
+                   || debug
+#endif /* !SMALL */
+                   ))
                        fprintf(ttyout, "Can't convert %s to a time.\n", reply_string);
                else
                        rtime += timebuf.tm_gmtoff;     /* conv. local -> GMT */
-       } else if (noisy && debug == 0) {
+       } else if (noisy
+#ifndef SMALL
+           && !debug
+#endif /* !SMALL */
+           ) {
                fputs(reply_string, ttyout);
                fputc('\n', ttyout);
        }