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