tenex.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,873 行 · 第 1/3 页

C
1,873
字号
#ifdef TENEX#ifndef lintstatic char *sccsid = "@(#)tenex.c	4.3  (ULTRIX)        12/20/90";#endif/************************************************************************ *                                                                      * *                      Copyright (c) 1988 by                           * *              Digital Equipment Corporation, Maynard, MA              * *                      All rights reserved.                            * *                                                                      * *   This software is furnished under a license and may be used and     * *   copied  only  in accordance with the terms of such license and     * *   with the  inclusion  of  the  above  copyright  notice.   This     * *   software  or  any  other copies thereof may not be provided or     * *   otherwise made available to any other person.  No title to and     * *   ownership of the software is hereby transferred.                   * *                                                                      * *   The information in this software is subject to change  without     * *   notice  and should not be construed as a commitment by Digital     * *   Equipment Corporation.                                             * *                                                                      * *   Digital assumes no responsibility for the use  or  reliability     * *   of its software on equipment which is not supplied by Digital.     * *                                                                      * ************************************************************************//* * Tenex style file name recognition, .. and more. * * Author: Ken Greer, Sept. 1975, Carnegie-Mellon University. * * Modification History * * 014  Bob Fontaine - Mon Oct 22 10:51:40 EDT 1990 *      Change octal 210s to a quoted backspaces so that tabs settings will *      not be changed when terminal is in vt300 and 8 bit MultiNational *      Characters modes set.  Thanks to AKira Tanaka (JRD).  Fixes QARS *      #5853 and #6041. * * 013  Bob Fontaine - Mon Oct 22 10:51:40 EDT 1990 *      Allow users to set tty characteristics to raw or cbreak. *      Thanks to Arika Tanaka (JRD).  Fixes QAR 5290. * * 012	Bob Fontaine - Fri Jun 22 09:53:01 EDT 1990 *	Changed call to internal printf function to csh_printf to avoid *	confusion with stdio library routine. *	 * 011  Bob Fontaine - Thu May 24 10:48:21 EDT 1990 *	Don't force ECHO on in tty setup.  If user has turned it off *	leave it that way. * * 010	Gary A. Gaudet - Wed Dec 20 16:51:55 EST 1989 * 	Increased bp[] in termchars to BUFSIZ *	Added return value test from ioctl() *	removed unused variable ep *	added some (castings) * * * 09	Al Delorey (afd), 11-Nov-88. *	Fix null ptr references and uninitialized variables. *	Also skip trying to recognize aliases and shell variables; *	these are now stored as a binary tree in the "varent struct". *	Expanding them is not very usefull anyway. * * 08	Al Delorey (afd), 20-Sep-88. *	Ported to PMAX: *	sigignore(SIGxxx) => omask = sigblock(sigmask(SIGxxx) *	sigirelse(SIGxxx) => sigsetmask(omask) * * 07	Al Delorey, 08-Feb-88. *	Made ESC invoke command "!!:v" (command line edit) *	when the ESC is the first character of the line. * * 06	Greg Tarsa, 10-Feb-84. *	Changed so that information for builtins comes from csh's *	internal tables, not dummy directory.  Also added aliases to *	the list of command names. * * 05	Greg Tarsa, 4-Feb-84. *	Changed package to ignore duplicate entries and to print the *	contents of the history entry when listing history entries. * * 04	Greg Tarsa, 19-Jan-84. *	Removed Gotos and refs to curses package.  Added recognition of *	variables and history expansion strings. * * 03	Greg Tarsa, 13-Jan-1984. *	Fixed to translate ~ based on the USER environment variable and *	not the uid. * * 02	Mike Ellis, Fairchild A.I. Labs, September 1983. *	Search and recognition of command names (in addition to file *	names) added. * * 01	Ken Greer, Carnegie-Mellon University, December 1981. *	Finally got around to adding to the Cshell. */#include "sh.h"#include <sgtty.h>#include <sys/dir.h>#include <pwd.h>/* Don't include stdio.h  Csh doesn't like it!! */#define TRUE		1#define FALSE		0#define ON		1#define OFF		0#define SCREEN_WIDTH	80		/* reasonable screen width */#define FILSIZ		512		/* Max reasonable file name length */#define ESC		'\033'#define is_set(var)	adrof(var)extern short SHIN, SHOUT;extern char *getenv();extern putchar();typedef enum {LIST, RECOGNIZE} COMMAND;static char	*BELL = "\07";/*	Command source types (for dirctr)/	Values -1, -2 are special values,	values 0-n reflect the directory in	that position in the path variable.*/#define CMD_BUILTIN	-1	/* get from builtin command table */#define CMD_ALIAS	-2	/* get from alias list (this is NOT used) */#define MAXITEMS 2048	/* max items allowed in lists *//*	Definition for general context pointer	in getentry.*/union entry_context	{	DIR *dir_fd;		/* for directory lookups */	struct Hist *curhist;	/* for history lookups */	struct varent *curvar;	/* for variable  and alias lookups */	struct biltins *curbfunc;	/* for BUILTIN lookups */	};int bfuncnum;			/* count bfunc entries so we don't				   fall off end of list*//*	Search word types.*/#define DIR_WD		0	/* default case */#define CMD_WD		1	/* command word */#define LNAM_WD		2	/* login name */#define HIST_WD		3	/* history word */#define VAR_WD		4	/* variable name *//*	setup_tty	Set the terminal up to enable recognition features	or restore original terminal characteristics.	The shell makes sure that the tty is not in some	weird state and fixes it if it is.  This is a useful	feature in it's own right. . .But it should be noted	that the tenex routine will not work correctly in	CBREAK or RAW mode so this code below is, therefore,	mandatory.*/staticsetup_tty (on){	static struct sgttyb sgtty;	/* Save sg_flags in basic mode */	static short save_sg_flags;	static struct tchars  tchars;	/* INT, QUIT, XON, XOFF, EOF, BRK */	static char save_t_brkc = -1;	/* Save user's break character */	int omask;				/* old signal mask */	omask = sigblock(sigmask(SIGINT));	if (on)	{	/* Get and save current break character. */	if (ioctl (SHIN, TIOCGETC, &tchars) == -1) {	/* 010 - GAG */	/*	Perror ("ioctl")*/;	}	save_t_brkc = tchars.t_brkc;	/* Set to ESC, if necessary */	if (save_t_brkc != ESC)		{		tchars.t_brkc = ESC;		if (ioctl (SHIN, TIOCSETC, &tchars) == -1) {	/* 010 - GAG */			/*Perror ("ioctl")*/;			}		}	if (ioctl (SHIN, TIOCGETP, &sgtty) == -1) {	/* 010 - GAG */		/*Perror ("ioctl")*/;		}		/* ECHO is not mandatory, but is nice. */	/* Don't force ECHO on if it is already off */   			if ((sgtty.sg_flags & (RAW | CBREAK)))  /* 011 - rnf */		{		sgtty.sg_flags &= ~(RAW | CBREAK);		if (ioctl (SHIN, TIOCSETP, &sgtty) == -1) {	/* 010 - GAG */			/*Perror ("ioctl")*/;			}		}	}	else		/* turn special features off */	{	/* Reset break char, if necessary. */	if (save_t_brkc != tchars.t_brkc)		{		tchars.t_brkc = save_t_brkc;		if (ioctl (SHIN, TIOCSETC, &tchars) == -1) {	/* 010 - GAG */			/*Perror ("ioctl")*/;			}		}				/* 013 RNF */		if(save_sg_flags && save_sg_flags != sgtty.sg_flags)		{			sgtty.sg_flags = save_sg_flags;			if(ioctl(SHIN,TIOCSETP,&sgtty) == -1) {				Perror("ioctl");			}		}	}/* end if (on) */	(void) sigsetmask(omask);}/* end setup_tty() */#ifdef CURSES/*	termchars	Initialize any special terminal characters*/statictermchars (){	extern char *tgetstr ();	char bp[BUFSIZ];	/* 010 - GAG */	static char area[256];	static int been_here = 0;	char *ap = area;	register char *s;	/* Execute this code only once */	if (been_here)	return;	been_here = TRUE;	/*	 Get the terminal entry and determine whether	 there is a special bell character.	*/	if (tgetent (bp, getenv ("TERM")) != 1)		return;	if (s = tgetstr ("vb", &ap))		/* Visible Bell */	BELL = s;	return;}/* end termchars() */#endif CURSES/*	back_to_col_1	Move back to beginning of current line*/staticback_to_col_1 (){	struct sgttyb tty, tty_normal;	int omask;		/* old signal mask */	omask = sigblock(sigmask(SIGINT));	/*	  Get current terminal characteristics.	  Save them for later restoration, setup	  to allow CR output and output a CR.	  Restore original modes.	*/	if (ioctl (SHIN, TIOCGETP, &tty) == -1) {	/* 010 - GAG */		Perror ("ioctl");		}	tty_normal = tty;	tty.sg_flags &= ~CRMOD;	if (ioctl (SHIN, TIOCSETN, &tty) == -1) {	/* 010 - GAG */		Perror ("ioctl");		}	(void) write (SHOUT, "\r", 1);	if (ioctl (SHIN, TIOCSETN, &tty_normal) == -1) {	/* 010 - GAG */		Perror ("ioctl");		}	(void) sigsetmask(omask);}/* end back_to_col_1() *//*	pushback	Push string contents back into tty queue*/staticpushback (string)char  *string;{	extern char *malloc();	register char  *p;	struct sgttyb   tty, tty_normal;	int omask;		/* old signal mask */	omask = sigblock(sigmask(SIGINT));	/*	 Get current terminal parameters and save	 for later restoration.  Turn off terminal	 echo immediatly, without flushing input	 buffer.  	*/	if (ioctl (SHOUT, TIOCGETP, &tty) == -1) {	/* 010 - GAG */		Perror ("ioctl");		}	tty_normal = tty;	tty.sg_flags &= ~ECHO;	if (ioctl (SHOUT, TIOCSETN, &tty) == -1) {	/* 010 - GAG */		Perror ("ioctl");		}	/* Put the chars into the input buffer */	for (p = string; *p; p++)	if (ioctl (SHOUT, TIOCSTI, p) == -1) {	/* 010 - GAG */		Perror ("ioctl");		}	/* Restore tty params */	if (ioctl (SHOUT, TIOCSETN, &tty_normal) == -1) {	/* 010 - GAG */		Perror ("ioctl");		}	(void) sigsetmask(omask);}/* end pushback() *//*	catn	Concatenate src onto tail of des.	Des is a string whose maximum length is count.	Always null terminate.*/ catn (des, src, count)register char *des, *src;register count;{	while (--count >= 0 && *des)	des++;	while (--count >= 0)	if ((*des++ = *src++) == 0)		return;	*des = '\0';}/* end catn() *//*	max	return the maximum of two numbers.*/staticmax (a, b){	if (a > b)	return (a);	return (b);}/* end max() *//*	copyn	Like strncpy but always leave room for trailing \0	and always null terminate.*/copyn (des, src, count)register char *des, *src;register count;{	while (--count >= 0)	if ((*des++ = *src++) == 0)		return;	*des = '\0';}/* end copyn() *//*	fcompare	For qsort()*/staticfcompare (file1, file2)char  **file1, **file2;{	return (strcmp (*file1, *file2));}/* end fcompare() */static charfiletype (dir, file)char *dir, *file;{	if (dir)	{	char path[512];	struct stat statb;	strcpy (path, dir);	catn (path, file, sizeof path);	if (stat (path, &statb) >= 0)		{		if (statb.st_mode & S_IFDIR)		return ('/');		if (statb.st_mode & 0111)		return ('*');		}	}	return (' ');}/* end filetype() *//*	tilde	Expand "old" file name with possible tilde usage.	old = 	~person/mumble	expands to	new = home_directory_of_person/mumble	Return NULL if "person" is invalid, otherwise	return new.*/char *tilde (new, old)char *new, *old;{	extern struct passwd *getpwuid (), *getpwnam ();	register char *o, *p;	register struct passwd *pw;	static char person[40] = {0};	/* No leading tilde? No translation. Return orig string */	if (old[0] != '~')	{	strcpy (new, old);	return (new);	}	/*	 Copy everything after the tilde up to EOS or	 start of subdir name.	*/	for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++);	*p = '\0';	if (person[0] == '\0')		/* Use current uid if no name */	strcpy (new, value("home"));	/* translate from environment */	else	{	pw = getpwnam (person);		/* Else lookup on name */		if (pw == NULL)			/* Not found? Return Error. */		return (NULL);	strcpy (new, pw -> pw_dir);	/* Found: copy. */	}	/* place the translation into the old name */	(void) strcat (new, o);	return (new);}/* end tilde() *//*	retype	Cause pending line to be printed*/staticretype (){	int     pending_input = LPENDIN;	if (ioctl (SHOUT, TIOCLBIS, &pending_input) == -1) {	/* 010 - GAG */		Perror ("ioctl");		}}/*	beep	Ring the terminal bell*/staticbeep (){	(void) write (SHOUT, BELL, strlen(BELL));}/*	extract_dir_and_name	Parse full path in file into 2 parts: directory and file name	Leaves slash (/) at end of dir.*/staticextract_dir_and_name (path, dir, name)char   *path, *dir, *name;{	extern char *rindex ();	register char  *p;	if ((p = rindex(path, '/')))	/* Is there a dir? */	{	p++;				/* Yes: extract */	copyn (name, p, MAXNAMLEN);	/* copy name w/o '/' */	copyn (dir, path, p - path);	/* copy dir w/ '/' */	}	else	{			copyn (name, path, MAXNAMLEN);	/* No: copy name only */	dir[0] = '\0';			/* make dir null */	}}/* end extract_dir_and_name() *//*	getentry	Get a specified entry from the list of available ones.	Necessary initializations of files or structure pointers	has been done prior to getentry call.	Dirctr is examined when type is CMD_WD,	to determine the source from which to get the entry.	CMD_BUILTIN and CMD_ALIAS are currently special cases with	other cases defaulting to assume context to be a directory fd.*/char *getentry (type, context, dirctr)register union entry_context *context;int dirctr;{	switch (type)	{	case LNAM_WD:		/* get a login name */		{		struct passwd *getpwent ();		register struct passwd *pw;		/* Read a pw entry.  None: exit. */		if((pw = getpwent ()) == NULL)			return (NULL);		else			return (pw -> pw_name);		}	case CMD_WD:		/* get a command entry */		/*		 Process special sources.		 First, builtins from internal tables,		 then aliases from internal alias list.		*/		if (dirctr == CMD_BUILTIN)		{		context->curbfunc++;		/*		 afd fix 09:		 fix null ptr reference, bfunc array is NOT NULL terminated		*/		bfuncnum++;		if (bfuncnum > nbfunc)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?