[net.bugs.4bsd] ftp won't always glob

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