On Mon, Jul 30, 2012 at 10:30:47AM +0200, Jan Klemkow wrote:
> Hopefully the final version.

Yes, I think this is OK now.  If anybody else could have a look at
it, I will commit it.

bluhm

> 
> 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