Builtin 'which' command for csh

Tony Birnseth tonyb at tektools.UUCP
Fri Dec 12 14:36:30 AEST 1986


Index: /bin/csh 4.3BSD

Description:
	/usr/ucb/which does not handle builtin csh commands and is slower than
	a slug!  The following is an internal which command for csh.  
	We had a long argument about the functionality of this command.  Should
	it be useful and fast?  Or should it be compatible with /usr/ucb/which?
	Unfortunately, the compatibility argument won out.  However it should
	be easy enough for a site to remove the -u option stuff and get a
	reasonably fast useful, which command.

Fix:
	Apply the following diffs to sh.func.c and sh.init.c.

*** /tmp/,RCSt1027852	Thu Dec 11 17:03:03 1986
--- sh.func.c	Thu Dec 11 16:58:59 1986
***************
*** 1149,1151
  	if (reenter >= 2)
  		error(NOSTR);
  }

--- 1170,1325 -----
  	if (reenter >= 2)
  		error(NOSTR);
  }
+ 
+ 
+ #ifdef TEK_MODS
+ 
+ /*
+  * After much disucussion, it was decided to have this fast clean internal
+  * version of 'which' produce the same ugly output as it slower counterpart
+  * /usr/ucb/which.  A -u (useful) flag was added to allow a user to alias
+  * which to which -u for a cleaner more useful form of the command.
+  * tonyb at tek
+  */
+ dowhich(vec)
+ 	char **vec;
+ {
+ 	register struct biltins *bp;
+ 	register char *word, **pp, *func;
+ 	struct varent *vp, *pth;
+ 	char dir[MAXPATHLEN+1];
+ 	int cmp, hit, outty, uflag;
+ 	
+ 
+ 	/*
+ 	 * Glob it up
+ 	 */
+ 	uflag = gflag = 0;
+ 	tglob(++vec);
+ 	if(gflag) { 			/* has globbing chars */
+ 		vec = glob(vec);	/* glob it */
+ 		if(vec == 0)
+ 			bferr("No match");
+ 	} else
+ 		trim( vec );
+ 	
+ 	pth = adrof("path");
+ 
+ 	/*
+ 	 * Find out if we're writting to a tty.  If not, use "command type"
+ 	 * output, else use "user" type output.
+ 	 * command type output is used to do things like 'echo `which foobar`'
+ 	 */
+ 	outty = isatty(1);
+ 
+ 	/*
+ 	 * If no -u, go into useless mode, else provide useable,
+ 	 * coherent output.
+ 	 */
+ 	if(eq(*vec,"-u")) {
+ 		uflag++;
+ 		vec++;
+ 	}
+ 
+ 	while(word = *vec++) {
+ 
+ 		/*
+ 		 * check aliases first.  
+ 		 */
+ 		vp = adrof1(word, &aliases);
+ 		if(vp) {
+ 			if(!uflag) {
+ 				printf("%s: \t aliased to '", word);
+ 				blkpr(vp->vec);printf("'\n");
+ 			} else if(outty) {
+ 				printf("alias/%s '", word);
+ 				blkpr(vp->vec); printf("'\n");
+ 			} else
+ 				printf("%s\n",word);
+ 			continue;
+ 		}
+ 
+ 		/*
+ 		 * If a hard path, just return it if it is executable, else
+ 		 * return nothing.
+ 		 */
+ 		if(index(word, '/') ) {
+ 			if(executable(word)) {
+ 				printf("%s\n",word);
+ 				continue;
+ 			}
+ 			else if( !uflag ) {
+ 				printf("%s not found\n", word);
+ 				continue;
+ 			}
+ 		}
+ 	
+ 		/*
+ 		 * Check builtins
+ 		 * "standard" /usr/ucb/which does not support the concept
+ 		 * of builtin commands. YUK!!!
+ 		 */
+ 		if(uflag) {
+ 			hit = 0;
+ 			for(bp=bfunc; func = bp->bname; bp++) {
+ 				cmp = strcmp(func, word);
+ 				if(cmp == 0) {
+ 					if(outty)
+ 						printf("builtin/%s\n",word);
+ 					else
+ 						printf("%s\n",word);
+ 					hit++;
+ 				}
+ 				else if(cmp > 0)
+ 					break;
+ 			}
+ 			if(hit) 
+ 				continue;
+ 		}
+ 
+ 
+ 		/*
+ 		 * Check the paths
+ 		 * No need to read 'em, just check if it is executable.
+ 		 */
+ 		if(pth) {
+ 			register char *ep;
+ 	
+ 			hit = 0;
+ 			for(pp = pth->vec; pp && *pp && **pp; pp++) {
+ 				ep = strcpy(dir,*pp);
+ 				while(*ep)
+ 					ep++;
+ 				*ep++ = '/';
+ 				strcpy(ep,word);
+ 				if(executable(dir)) {
+ 					printf("%s\n",dir);
+ 					hit++;
+ 					break;
+ 				}
+ 			}
+ 		}
+ 
+ 		/*
+ 		 * If not found and in useless mode
+ 		 */
+ 		if(!hit && !uflag) {
+ 			printf("no %s in ", word); 
+ 			blkpr(pth->vec);
+ 			printf("\n");
+ 		}
+ 	} /* end while */
+ }
+ 
+ 
+ executable(path)
+ 	register char *path;
+ {
+ 	struct stat st;
+ 
+ 	if(access(path,1) || stat(path, &st) )
+ 		st.st_mode = 0;
+ 	return( (st.st_mode & S_IFMT) == S_IFREG);
+ }
+ #endif /* TEK_MODS */
+ 
*** /tmp/,RCSt1027862	Thu Dec 11 17:03:14 1986
--- sh.init.c	Thu Dec 11 12:47:00 1986
***************
*** 77,82
  extern	int dounhash();
  extern	int unset();
  extern	int dounsetenv();
  
  #define	INF	1000
  

--- 77,85 -----
  extern	int dounhash();
  extern	int unset();
  extern	int dounsetenv();
+ #ifdef TEK_MODS
+ extern	int dowhich();
+ #endif /* TEK_MODS */
  
  #define	INF	1000
  
***************
*** 153,158
  	"unlimit",	dounlimit,	0,	INF,
  	"unset",	unset,		1,	INF,
  	"unsetenv",	dounsetenv,	1,	INF,
  	"wait",		dowait,		0,	0,
  	"while",	dowhile,	1,	INF,
  };

--- 160,168 -----
  	"unlimit",	dounlimit,	0,	INF,
  	"unset",	unset,		1,	INF,
  	"unsetenv",	dounsetenv,	1,	INF,
+ #ifdef TEK_MODS
+ 	"which",	dowhich,	1,	INF,
+ #endif /* TEK_MODS */
  	"wait",		dowait,		0,	0,
  	"while",	dowhile,	1,	INF,
  };



More information about the Comp.bugs.4bsd.ucb-fixes mailing list