cspencer@bbncc5.UUCP (Clifford Spencer) (10/30/85)
Index: /usr/src/ucb/ftp/{cmds.c,glob.c} 4.2BSD (and Ultrix!) Description: When processing '!' shell escapes, Ftp globs meta characters on its own and does an execvp() instead of handing the command to a shell. If you give '!' more than one argument, you get garbage out. If you give it one arg, the glob still doesn't work. Repeat-By: % ftp ftp> !echo * <undefined junk> Fix: I think Guy Harris mentioned this about 7 months ago, but fixed it by removing the feature and always forking a shell. I you would rather make it work, here's how. These fixes are in suitable for handing to "patch", but are not difficult to apply by hand. -cliff =================================== CUT CUT CUT ========================== *** cmds.c.orig Wed Oct 30 09:03:45 1985 --- cmds.c Wed Oct 30 09:03:53 1985 *************** *** 265,271 sendrequest("STOR", argv[i], argv[i]); continue; } ! gargs = glob(argv[i]); if (globerr != NULL) { printf("%s\n", globerr); if (gargs) --- 265,271 ----- sendrequest("STOR", argv[i], argv[i]); continue; } ! gargs = glob(&argv[i]); if (globerr != NULL) { printf("%s\n", globerr); if (gargs) *************** *** 1005,1011 if (!doglob) return (1); ! globbed = glob(*cpp); if (globerr != NULL) { printf("%s: %s\n", *cpp, globerr); if (globbed) --- 1005,1011 ----- if (!doglob) return (1); ! globbed = glob(cpp); if (globerr != NULL) { printf("%s: %s\n", *cpp, globerr); if (globbed) *** glob.c.orig Wed Oct 30 09:03:40 1985 --- glob.c Wed Oct 30 09:03:49 1985 *************** *** 44,50 char ** glob(v) ! register char *v; { char agpath[BUFSIZ]; char *agargv[GAVSIZ]; --- 44,50 ----- char ** glob(v) ! register char **v; { char agpath[BUFSIZ]; char *agargv[GAVSIZ]; *************** *** 48,56 { char agpath[BUFSIZ]; char *agargv[GAVSIZ]; - char *vv[2]; - vv[0] = v; - vv[1] = 0; gflag = 0; rscan(vv, tglob); if (gflag == 0) --- 48,53 ----- { char agpath[BUFSIZ]; char *agargv[GAVSIZ]; gflag = 0; rscan(v, tglob); if (gflag == 0) *************** *** 52,58 vv[0] = v; vv[1] = 0; gflag = 0; ! rscan(vv, tglob); if (gflag == 0) return (copyblk(vv)); --- 49,55 ----- char agpath[BUFSIZ]; char *agargv[GAVSIZ]; gflag = 0; ! rscan(v, tglob); if (gflag == 0) return (copyblk(v)); *************** *** 54,60 gflag = 0; rscan(vv, tglob); if (gflag == 0) ! return (copyblk(vv)); globerr = 0; gpath = agpath; gpathp = gpath; *gpathp = 0; --- 51,57 ----- gflag = 0; rscan(v, tglob); if (gflag == 0) ! return (copyblk(v)); globerr = 0; gpath = agpath; gpathp = gpath; *gpathp = 0; *************** *** 60,66 gpath = agpath; gpathp = gpath; *gpathp = 0; lastgpathp = &gpath[sizeof agpath - 2]; ginit(agargv); globcnt = 0; ! collect(v); if (globcnt == 0 && (gflag&1)) { blkfree(gargv), gargv = 0; return (0); --- 57,64 ----- gpath = agpath; gpathp = gpath; *gpathp = 0; lastgpathp = &gpath[sizeof agpath - 2]; ginit(agargv); globcnt = 0; ! while(*v) ! collect(*v++); if (globcnt == 0 && (gflag&1)) { blkfree(gargv), gargv = 0; return (0); -- cliff spencer {harvard, ihnp4, decvax}!bbnccv!cspencer cspencer@bbncc5
guy@sun.uucp (Guy Harris) (11/11/85)
> Description: > When processing '!' shell escapes, Ftp globs meta characters > on its own and does an execvp() instead of handing the command > to a shell. If you give '!' more than one argument, you get > garbage out. If you give it one arg, the glob still doesn't work. > > Fix: > I think Guy Harris mentioned this about 7 months ago, but > fixed it by removing the feature and always forking a shell. > I you would rather make it work, here's how. Why should "ftp" duplicate the actions of the shell? Other UNIX programs handle shell escapes by doing an "sh -c" (except "ed", which uses the old "-t" crock), because that way they don't have to know anything about how the shell works. I don't think shell escapes are used enough to make the performance considerations of bypassing "sh" important. Also note that to really make shell escapes work right, you also have to recognize input/output redirection, pipelines, etc., etc. - none of which "ftp"'s built-in code does. I suspect the reason "ftp" does its own command parsing is that it's a halfassed piece of code; note all the bug reports that have been posted. (And, as the Good Book says, "There's bigger deals to come!"; you may notice a blank line produced after a command finishes when you use "ftp" on Suns. This is because, instead of returning from the command loop after executing a command, it jumps back by doing "longjmp(<whatever>, 0)", and Sun's "longjmp" converts a second argument of 0 into a second argument of 1, as the S5 "longjmp" does - thus, the caller of the command loop thinks it got an error. I'll fix it to work sanely at some point; there are also some other bugs found by somebody else here.) Guy Harris