Hopefully the final version.

Index: cmds.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/cmds.c,v
retrieving revision 1.70
diff -u -p -r1.70 cmds.c
--- cmds.c      5 May 2009 19:35:30 -0000       1.70
+++ cmds.c      30 Jul 2012 07:58:16 -0000
@@ -231,15 +231,32 @@ mput(int argc, char *argv[])
        extern int optind, optreset;
        int ch, i, restartit = 0;
        sig_t oldintr;
-       char *cmd, *tp;
+       char *cmd, *tp, *xargv[] = { argv[0], NULL, NULL };
+       const char *errstr;
+       static int depth = 0, max_depth = 0;
 
        optind = optreset = 1;
 
-       while ((ch = getopt(argc, argv, "c")) != -1) {
+       if (depth)
+               depth++;
+
+       while ((ch = getopt(argc, argv, "cd:r")) != -1) {
                switch(ch) {
                case 'c':
                        restartit = 1;
                        break;
+               case 'd':
+                       max_depth = strtonum(optarg, 0, INT_MAX, &errstr);
+                       if (errstr != NULL) {
+                               fprintf(ttyout, "bad depth value, %s: %s\n",
+                                   errstr, optarg);
+                               code = -1;
+                               return;
+                       }
+                       break;
+               case 'r':
+                       depth = 1;
+                       break;
                default:
                        goto usage;
                }
@@ -247,7 +264,8 @@ mput(int argc, char *argv[])
 
        if (argc - optind < 1 && !another(&argc, &argv, "local-files")) {
 usage:
-               fprintf(ttyout, "usage: %s [-c] local-files\n", argv[0]);
+               fprintf(ttyout, "usage: %s [-cr] [-d depth] local-files\n",
+                   argv[0]);
                code = -1;
                return;
        }
@@ -318,11 +336,13 @@ usage:
                mflag = 0;
                return;
        }
+
        for (i = 1; i < argc; i++) {
                char **cpp;
                glob_t gl;
                int flags;
 
+               /* Copy files without word expansion */
                if (!doglob) {
                        if (mflag && confirm(argv[0], argv[i])) {
                                tp = (ntflag) ? dotrans(argv[i]) : argv[i];
@@ -348,6 +368,7 @@ usage:
                        continue;
                }
 
+               /* expanding file names */
                memset(&gl, 0, sizeof(gl));
                flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
                if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
@@ -355,33 +376,89 @@ usage:
                        globfree(&gl);
                        continue;
                }
+
+               /* traverse all expanded file names */
                for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
-                       if (mflag && confirm(argv[0], *cpp)) {
-                               tp = (ntflag) ? dotrans(*cpp) : *cpp;
-                               tp = (mapflag) ? domap(tp) : tp;
-                               if (restartit == 1) {
-                                       off_t ret;
+                       struct stat filestat;
 
-                                       if (curtype != type)
-                                               changetype(type, 0);
-                                       ret = remotesize(tp, 0);
-                                       restart_point = (ret < 0) ? 0 : ret;
-                               }
-                               cmd = restartit ? "APPE" : ((sunique) ?
-                                   "STOU" : "STOR");
-                               sendrequest(cmd, *cpp, tp,
-                                   *cpp != tp || !interactive);
-                               restart_point = 0;
-                               if (!mflag && fromatty) {
-                                       if (confirm(argv[0], NULL))
-                                               mflag = 1;
+                       if (!mflag)
+                               continue;
+                       if (stat(*cpp, &filestat) != 0) {
+                               warn("local: %s", *cpp);
+                               continue;
+                       }
+                       if (S_ISDIR(filestat.st_mode) && depth == max_depth)
+                               continue;
+                       if (!confirm(argv[0], *cpp))
+                               continue;
+
+                       /*
+                        * If file is a directory then create a new one
+                        * at the remote machine.
+                        */
+                       if (S_ISDIR(filestat.st_mode)) {
+                               xargv[1] = *cpp;
+                               makedir(2, xargv);
+                               cd(2, xargv);
+                               if (dirchange != 1) {
+                                       warnx("remote: %s", *cpp);
+                                       continue;
+                               }
+
+                               if (chdir(*cpp) != 0) {
+                                       warn("local: %s", *cpp);
+                                       goto out;
+                               }
+
+                               /* Copy the whole directory recursively. */
+                               xargv[1] = "*";
+                               mput(2, xargv);
+
+                               if (chdir("..") != 0) {
+                                       mflag = 0;
+                                       warn("local: %s", *cpp);
+                                       goto out;
+                               }
+
+ out:
+                               xargv[1] = "..";
+                               cd(2, xargv);
+                               if (dirchange != 1) {
+                                       warnx("remote: %s", *cpp);
+                                       mflag = 0;
                                }
+                               continue;
+                       }
+
+                       tp = (ntflag) ? dotrans(*cpp) : *cpp;
+                       tp = (mapflag) ? domap(tp) : tp;
+                       if (restartit == 1) {
+                               off_t ret;
+
+                               if (curtype != type)
+                                       changetype(type, 0);
+                               ret = remotesize(tp, 0);
+                               restart_point = (ret < 0) ? 0 : ret;
+                       }
+                       cmd = restartit ? "APPE" : ((sunique) ?
+                           "STOU" : "STOR");
+                       sendrequest(cmd, *cpp, tp,
+                           *cpp != tp || !interactive);
+                       restart_point = 0;
+                       if (!mflag && fromatty) {
+                               if (confirm(argv[0], NULL))
+                                       mflag = 1;
                        }
                }
                globfree(&gl);
        }
+
        (void)signal(SIGINT, oldintr);
-       mflag = 0;
+
+       if (depth)
+               depth--;
+       if (depth == 0 || mflag == 0)
+               depth = max_depth = mflag = 0;
 }
 
 void
Index: ftp.1
===================================================================
RCS file: /cvs/src/usr.bin/ftp/ftp.1,v
retrieving revision 1.82
diff -u -p -r1.82 ftp.1
--- ftp.1       30 Apr 2012 13:41:26 -0000      1.82
+++ ftp.1       30 Jul 2012 07:58:16 -0000
@@ -664,7 +664,8 @@ on the remote machine.
 A synonym for
 .Ic page .
 .It Xo Ic mput
-.Op Fl c
+.Op Fl cr
+.Op Fl d Ar depth
 .Ar local-files
 .Xc
 Expand wild cards in the list of local files given as arguments
@@ -683,9 +684,21 @@ settings.
 If the
 .Fl c
 flag is specified then
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl c
+Use
 .Ic reput
-is used instead of
+instead of
 .Ic put .
+.It Fl d Ar depth
+Specify the maximum recursion level
+.Ar depth .
+The default is 0, which means unlimited.
+.It Fl r
+Recursively descend the directory tree, transferring all files and
+directories.
+.El
 .It Xo Ic msend
 .Op Fl c
 .Ar local-files

Reply via email to