⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c_ksh.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * built-in Korn commands: c_* */#include "sh.h"#include "ksh_stat.h"#include <ctype.h>#ifdef __CYGWIN__#include <sys/cygwin.h>#endif /* __CYGWIN__ */intc_cd(wp)	char	**wp;{	int optc;	int physical = Flag(FPHYSICAL);	int cdnode;			/* was a node from cdpath added in? */	int printpath = 0;		/* print where we cd'd? */	int rval;	struct tbl *pwd_s, *oldpwd_s;	XString xs;	char *xp;	char *dir, *try, *pwd;	int phys_path;	char *cdpath;	while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != EOF)		switch (optc) {		case 'L':			physical = 0;			break;		case 'P':			physical = 1;			break;		case '?':			return 1;		}	wp += builtin_opt.optind;	if (Flag(FRESTRICTED)) {		bi_errorf("restricted shell - can't cd");		return 1;	}	pwd_s = global("PWD");	oldpwd_s = global("OLDPWD");	if (!wp[0]) {		/* No arguments - go home */		if ((dir = str_val(global("HOME"))) == null) {			bi_errorf("no home directory (HOME not set)");			return 1;		}	} else if (!wp[1]) {		/* One argument: - or dir */		dir = wp[0];		if (strcmp(dir, "-") == 0) {			dir = str_val(oldpwd_s);			if (dir == null) {				bi_errorf("no OLDPWD");				return 1;			}			printpath++;		}	} else if (!wp[2]) {		/* Two arguments - substitute arg1 in PWD for arg2 */		int ilen, olen, nlen, elen;		char *cp;		if (!current_wd[0]) {			bi_errorf("don't know current directory");			return 1;		}		/* substitue arg1 for arg2 in current path.		 * if the first substitution fails because the cd fails		 * we could try to find another substitution. For now		 * we don't		 */		if ((cp = strstr(current_wd, wp[0])) == (char *) 0) {			bi_errorf("bad substitution");			return 1;		}		ilen = cp - current_wd;		olen = strlen(wp[0]);		nlen = strlen(wp[1]);		elen = strlen(current_wd + ilen + olen) + 1;		dir = alloc(ilen + nlen + elen, ATEMP);		memcpy(dir, current_wd, ilen);		memcpy(dir + ilen, wp[1], nlen);		memcpy(dir + ilen + nlen, current_wd + ilen + olen, elen);		printpath++;	} else {		bi_errorf("too many arguments");		return 1;	}	Xinit(xs, xp, PATH, ATEMP);	/* xp will have a bogus value after make_path() - set it to 0	 * so that if it's used, it will cause a dump	 */	xp = (char *) 0;	cdpath = str_val(global("CDPATH"));	do {		cdnode = make_path(current_wd, dir, &cdpath, &xs, &phys_path);#ifdef S_ISLNK		if (physical)			rval = chdir(try = Xstring(xs, xp) + phys_path);		else#endif /* S_ISLNK */		{			simplify_path(Xstring(xs, xp));			rval = chdir(try = Xstring(xs, xp));		}	} while (rval < 0 && cdpath != (char *) 0);	if (rval < 0) {		if (cdnode)			bi_errorf("%s: bad directory", dir);		else			bi_errorf("%s - %s", try, strerror(errno));		return 1;	}	/* Clear out tracked aliases with relative paths */	flushcom(0);	/* Set OLDPWD (note: unsetting OLDPWD does not disable this	 * setting in at&t ksh)	 */	if (current_wd[0])		/* Ignore failure (happens if readonly or integer) */		setstr(oldpwd_s, current_wd, KSH_RETURN_ERROR);	if (!ISABSPATH(Xstring(xs, xp))) {#ifdef OS2		/* simplify_path() doesn't know about os/2's drive contexts,		 * so it can't set current_wd when changing to a:foo.		 * Handle this by calling getcwd()...		 */		pwd = ksh_get_wd((char *) 0, 0);#else /* OS2 */		pwd = (char *) 0;#endif /* OS2 */	} else#ifdef S_ISLNK	if (!physical || !(pwd = get_phys_path(Xstring(xs, xp))))#endif /* S_ISLNK */		pwd = Xstring(xs, xp);	/* Set PWD */	if (pwd) {#ifdef __CYGWIN__		char ptmp[PATH];  /* larger than MAX_PATH */		cygwin_conv_to_full_posix_path(pwd, ptmp);#else /* __CYGWIN__ */		char *ptmp = pwd;#endif /* __CYGWIN__ */		set_current_wd(ptmp);		/* Ignore failure (happens if readonly or integer) */		setstr(pwd_s, ptmp, KSH_RETURN_ERROR);	} else {		set_current_wd(null);		pwd = Xstring(xs, xp);		/* XXX unset $PWD? */	}	if (printpath || cdnode)		shprintf("%s\n", pwd);	return 0;}intc_pwd(wp)	char	**wp;{	int optc;	int physical = Flag(FPHYSICAL);	char *p;	while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != EOF)		switch (optc) {		case 'L':			physical = 0;			break;		case 'P':			physical = 1;			break;		case '?':			return 1;		}	wp += builtin_opt.optind;	if (wp[0]) {		bi_errorf("too many arguments");		return 1;	}#ifdef S_ISLNK	p = current_wd[0] ? (physical ? get_phys_path(current_wd) : current_wd)			  : (char *) 0;#else /* S_ISLNK */	p = current_wd[0] ? current_wd : (char *) 0;#endif /* S_ISLNK */	if (p && eaccess(p, R_OK) < 0)		p = (char *) 0;	if (!p) {		p = ksh_get_wd((char *) 0, 0);		if (!p) {			bi_errorf("can't get current directory - %s",				strerror(errno));			return 1;		}	}	shprintf("%s\n", p);	return 0;}intc_print(wp)	char **wp;{#define PO_NL		BIT(0)	/* print newline */#define PO_EXPAND	BIT(1)	/* expand backslash sequences */#define PO_PMINUSMINUS	BIT(2)	/* print a -- argument */#define PO_HIST		BIT(3)	/* print to history instead of stdout */#define PO_COPROC	BIT(4)	/* printing to coprocess: block SIGPIPE */#define PO_FSLASH	BIT(5)  /* swap slash for backslash (for os2 ) */	int fd = 1;	int flags = PO_EXPAND|PO_NL;	char *s;	const char *emsg;	XString xs;	char *xp;	if (wp[0][0] == 'e') {	/* echo command */		int nflags = flags;		/* A compromise between sysV and BSD echo commands:		 * escape sequences are enabled by default, and		 * -n, -e and -E are recognized if they appear		 * in arguments with no illegal options (ie, echo -nq		 * will print -nq).		 * Different from sysV echo since options are recognized,		 * different from BSD echo since escape sequences are enabled		 * by default.		 */		wp += 1;		while ((s = *wp) && *s == '-' && s[1]) {			while (*++s)				if (*s == 'n')					nflags &= ~PO_NL;				else if (*s == 'e')					nflags |= PO_EXPAND;				else if (*s == 'E')					nflags &= ~PO_EXPAND;				else					/* bad option: don't use nflags, print					 * argument					 */					break;			if (*s)				break;			wp++;			flags = nflags;		}	} else {		int optc;#if OS2		const char *options = "Rnpfrsu,"; /* added f flag */#else		const char *options = "Rnprsu,";#endif		while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)			switch (optc) {			  case 'R': /* fake BSD echo command */				flags |= PO_PMINUSMINUS;				flags &= ~PO_EXPAND;				options = "ne";				break;			  case 'e':				flags |= PO_EXPAND;				break;#ifdef OS2			  case 'f':				flags |= PO_FSLASH;				break;#endif			  case 'n':				flags &= ~PO_NL;				break;#ifdef KSH			  case 'p':				if ((fd = coproc_getfd(W_OK, &emsg)) < 0) {					bi_errorf("-p: %s", emsg);					return 1;				}				break;#endif /* KSH */			  case 'r':				flags &= ~PO_EXPAND;				break;			  case 's':				flags |= PO_HIST;				break;			  case 'u':				if (!*(s = builtin_opt.optarg))					fd = 0;				else if ((fd = check_fd(s, W_OK, &emsg)) < 0) {					bi_errorf("-u: %s: %s", s, emsg);					return 1;				}				break;			  case '?':				return 1;			}		if (!(builtin_opt.info & GI_MINUSMINUS)) {			/* treat a lone - like -- */			if (wp[builtin_opt.optind]			    && strcmp(wp[builtin_opt.optind], "-") == 0)				builtin_opt.optind++;		} else if (flags & PO_PMINUSMINUS)			builtin_opt.optind--;		wp += builtin_opt.optind;	}	Xinit(xs, xp, 128, ATEMP);	while (*wp != NULL) {		register int c;		s = *wp;		while ((c = *s++) != '\0') {			Xcheck(xs, xp);#ifdef OS2			if ((flags & PO_FSLASH) && c == '\\') 				if (*s == '\\')					*s++;				else					c = '/';#endif /* OS2 */			if ((flags & PO_EXPAND) && c == '\\') {				int i;				switch ((c = *s++)) {				/* Oddly enough, \007 seems more portable than				 * \a (due to HP-UX cc, Ultrix cc, old pcc's,				 * etc.).				 */				case 'a': c = '\007'; break;				case 'b': c = '\b'; break;				case 'c': flags &= ~PO_NL;					  continue; /* AT&T brain damage */				case 'f': c = '\f'; break;				case 'n': c = '\n'; break;				case 'r': c = '\r'; break;				case 't': c = '\t'; break;				case 'v': c = 0x0B; break;				case '0':					/* Look for an octal number: can have					 * three digits (not counting the					 * leading 0).  Truely burnt.					 */					c = 0;					for (i = 0; i < 3; i++) {						if (*s >= '0' && *s <= '7')							c = c*8 + *s++ - '0';						else							break;					}					break;				case '\0': s--; c = '\\'; break;				case '\\': break;				default:					Xput(xs, xp, '\\');				}			}			Xput(xs, xp, c);		}		if (*++wp != NULL)			Xput(xs, xp, ' ');	}	if (flags & PO_NL)		Xput(xs, xp, '\n');	if (flags & PO_HIST) {		Xput(xs, xp, '\0');		source->line++;		histsave(source->line, Xstring(xs, xp), 1);		Xfree(xs, xp);	} else {		int n, len = Xlength(xs, xp);#ifdef KSH		int UNINITIALIZED(opipe);		/* Ensure we aren't killed by a SIGPIPE while writing to		 * a coprocess.  at&t ksh doesn't seem to do this (seems		 * to just check that the co-process is alive, which is		 * not enough).		 */		if (coproc.write >= 0 && coproc.write == fd) {			flags |= PO_COPROC;			opipe = block_pipe();		}#endif /* KSH */		for (s = Xstring(xs, xp); len > 0; ) {			n = write(fd, s, len);			if (n < 0) {#ifdef KSH				if (flags & PO_COPROC)					restore_pipe(opipe);#endif /* KSH */				if (errno == EINTR) {					/* allow user to ^C out */					intrcheck();#ifdef KSH					if (flags & PO_COPROC)						opipe = block_pipe();#endif /* KSH */					continue;				}#ifdef KSH				/* This doesn't really make sense - could				 * break scripts (print -p generates				 * error message).				*if (errno == EPIPE)				*	coproc_write_close(fd);				 */#endif /* KSH */				return 1;			}			s += n;			len -= n;		}#ifdef KSH		if (flags & PO_COPROC)			restore_pipe(opipe);#endif /* KSH */	}	return 0;}intc_whence(wp)	char **wp;{	struct tbl *tp;	char *id;	int pflag = 0, vflag = 0, Vflag = 0;	int ret = 0;	int optc;	int iam_whence = wp[0][0] == 'w';	int fcflags;	const char *options = iam_whence ? "pv" : "pvV";	while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)		switch (optc) {		case 'p':			pflag = 1;			break;		case 'v':			vflag = 1;			break;		case 'V':			Vflag = 1;			break;		case '?':			return 1;		}	wp += builtin_opt.optind;	fcflags = FC_BI | FC_PATH | FC_FUNC;	if (!iam_whence) {		/* Note that -p on its own is deal with in comexec() */		if (pflag)			fcflags |= FC_DEFPATH;		/* Convert command options to whence options - note that		 * command -pV uses a different path search than whence -v		 * or whence -pv.  This should be considered a feature.		 */		vflag = Vflag;	}	if (pflag)		fcflags &= ~(FC_BI | FC_FUNC);	while ((vflag || ret == 0) && (id = *wp++) != NULL) {		tp = NULL;		if ((iam_whence || vflag) && !pflag)			tp = tsearch(&keywords, id, hash(id));

⌨️ 快捷键说明

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