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

📄 expand.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct strlist *sp;	char *start;	register char *p;	char *q;	char *ifs;	start = string;	if (ifslastp != NULL) {		ifsp = &ifsfirst;		do {			p = string + ifsp->begoff;			ifs = ifsp->nulonly? nullstr : ifsval();			while (p < string + ifsp->endoff) {				q = p;				if (*p == CTLESC)					p++;				if (strchr(ifs, *p++)) {					if (q > start || *ifs != ' ') {						*q = '\0';						sp = (struct strlist *)stalloc(sizeof *sp);						sp->text = start;						*arglist->lastp = sp;						arglist->lastp = &sp->next;					}					if (*ifs == ' ') {						for (;;) {							if (p >= string + ifsp->endoff)								break;							q = p;							if (*p == CTLESC)								p++;							if (strchr(ifs, *p++) == NULL) {								p = q;								break;							}						}					}					start = p;				}			}		} while ((ifsp = ifsp->next) != NULL);		if (*start || (*ifs != ' ' && start > string)) {			sp = (struct strlist *)stalloc(sizeof *sp);			sp->text = start;			*arglist->lastp = sp;			arglist->lastp = &sp->next;		}	} else {		sp = (struct strlist *)stalloc(sizeof *sp);		sp->text = start;		*arglist->lastp = sp;		arglist->lastp = &sp->next;	}}/* * Expand shell metacharacters.  At this point, the only control characters * should be escapes.  The results are stored in the list exparg. */char *expdir;STATIC voidexpandmeta(str)	struct strlist *str;	{	char *p;	struct strlist **savelastp;	struct strlist *sp;	char c;	while (str) {		if (fflag)			goto nometa;		p = str->text;#if UDIR		if (p[0] == '/' && p[1] == 'u' && p[2] == '/')			str->text = p = expudir(p);#endif#if TILDE		if (p[0] == '~')			str->text = p = expudir(p);#endif		for (;;) {			/* fast check for meta chars */			if ((c = *p++) == '\0')				goto nometa;			if (c == '*' || c == '?' || c == '[' || c == '!')				break;		}		savelastp = exparg.lastp;		INTOFF;		if (expdir == NULL)			expdir = ckmalloc(1024); /* I hope this is big enough */		expmeta(expdir, str->text);		ckfree(expdir);		expdir = NULL;		INTON;		if (exparg.lastp == savelastp) {			if (! zflag) {nometa:				*exparg.lastp = str;				rmescapes(str->text);				exparg.lastp = &str->next;			}		} else {			*exparg.lastp = NULL;			*savelastp = sp = expsort(*savelastp);			while (sp->next != NULL)				sp = sp->next;			exparg.lastp = &sp->next;		}		str = str->next;	}}#if UDIR || TILDE/* * UDIR: Expand /u/username into the home directory for the specified user. * TILDE: Expand ~username into the home directory for the specified user. * We hope not to use the getpw stuff here, because then we would have to load * in stdio and who knows what else.  With networked password files there is * no choice alas. */#define MAXLOGNAME 32#define MAXPWLINE 128char *pfgets();STATIC char *expudir(path)	char *path;	{	register char *p, *q, *r;	char name[MAXLOGNAME];	char line[MAXPWLINE];	int i;#if USEGETPW	struct passwd *pw;#endif	r = path;				/* result on failure */	p = r + (*r == '~' ? 1 : 3);	/* the 1 skips "~", 3 skips "/u/" */	q = name;	while (*p && *p != '/') {		if (q >= name + MAXLOGNAME - 1)			return r;		/* fail, name too long */		*q++ = *p++;	}	*q = '\0';#if TILDE	if (*name == 0 && *r == '~') {		/* null name, use $HOME */		if ((q = lookupvar("HOME")) == NULL)			return r;		/* fail, home not set */		i = strlen(q);		r = stalloc(i + strlen(p) + 1);		scopy(q, r);		scopy(p, r + i);		TRACE(("expudir converts %s to %s\n", path, r));		didudir = 1;		path = r;		return r;	}#endif#if !USEGETPW	/* can do without the bloat */	setinputfile("/etc/passwd", 1);	q = line + strlen(name);	while (pfgets(line, MAXPWLINE) != NULL) {		if (line[0] == name[0] && prefix(name, line) && *q == ':') {			/* skip to start of home directory */			i = 4;			do {				while (*++q && *q != ':');			} while (--i > 0);			if (*q == '\0')				break;		/* fail, corrupted /etc/passwd */			q++;			for (r = q ; *r && *r != '\n' && *r != ':' ; r++);			*r = '\0';		/* nul terminate home directory */			i = r - q;		/* i = strlen(q) */			r = stalloc(i + strlen(p) + 1);			scopy(q, r);			scopy(p, r + i);			TRACE(("expudir converts %s to %s\n", path, r));			didudir = 1;			path = r;		/* succeed */			break;		}	}	popfile();#else	if ((pw = getpwnam(name)) != NULL) {		/* user exists */		q = pw->pw_dir;		i = strlen(q);		r = stalloc(i + strlen(p) + 1);		scopy(q, r);		scopy(p, r + i);		TRACE(("expudir converts %s to %s\n", path, r));		didudir = 1;		path = r;	}	endpwent();#endif /* USEGETPW */	return r;}#endif/* * Do metacharacter (i.e. *, ?, [...]) expansion. */STATIC voidexpmeta(enddir, name)	char *enddir;	char *name;	{	register char *p;	char *q;	char *start;	char *endname;	int metaflag;	struct stat statb;	DIR *dirp;	struct dirent *dp;	int atend;	int matchdot;	metaflag = 0;	start = name;	for (p = name ; ; p++) {		if (*p == '*' || *p == '?')			metaflag = 1;		else if (*p == '[') {			q = p + 1;			if (*q == '!')				q++;			for (;;) {				if (*q == CTLESC)					q++;				if (*q == '/' || *q == '\0')					break;				if (*++q == ']') {					metaflag = 1;					break;				}			}		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {			metaflag = 1;		} else if (*p == '\0')			break;		else if (*p == CTLESC)			p++;		if (*p == '/') {			if (metaflag)				break;			start = p + 1;		}	}	if (metaflag == 0) {	/* we've reached the end of the file name */		if (enddir != expdir)			metaflag++;		for (p = name ; ; p++) {			if (*p == CTLESC)				p++;			*enddir++ = *p;			if (*p == '\0')				break;		}		if (metaflag == 0 || stat(expdir, &statb) >= 0)			addfname(expdir);		return;	}	endname = p;	if (start != name) {		p = name;		while (p < start) {			if (*p == CTLESC)				p++;			*enddir++ = *p++;		}	}	if (enddir == expdir) {		p = ".";	} else if (enddir == expdir + 1 && *expdir == '/') {		p = "/";	} else {		p = expdir;		enddir[-1] = '\0';	}	if ((dirp = opendir(p)) == NULL)		return;	if (enddir != expdir)		enddir[-1] = '/';	if (*endname == 0) {		atend = 1;	} else {		atend = 0;		*endname++ = '\0';	}	matchdot = 0;	if (start[0] == '.' || start[0] == CTLESC && start[1] == '.')		matchdot++;	while (! int_pending() && (dp = readdir(dirp)) != NULL) {		if (dp->d_name[0] == '.' && ! matchdot)			continue;		if (patmatch(start, dp->d_name)) {			if (atend) {				scopy(dp->d_name, enddir);				addfname(expdir);			} else {				char *q;				for (p = enddir, q = dp->d_name ; *p++ = *q++ ;);				p[-1] = '/';				expmeta(p, endname);			}		}	}	closedir(dirp);	if (! atend)		endname[-1] = '/';}/* * Add a file name to the list. */STATIC voidaddfname(name)	char *name;	{	char *p;	struct strlist *sp;	p = stalloc(strlen(name) + 1);	scopy(name, p);	sp = (struct strlist *)stalloc(sizeof *sp);	sp->text = p;	*exparg.lastp = sp;	exparg.lastp = &sp->next;}/* * Sort the results of file name expansion.  It calculates the number of * strings to sort and then calls msort (short for merge sort) to do the * work. */STATIC struct strlist *expsort(str)	struct strlist *str;	{	int len;	struct strlist *sp;	len = 0;	for (sp = str ; sp ; sp = sp->next)		len++;	return msort(str, len);}STATIC struct strlist *msort(list, len)	struct strlist *list;	{	struct strlist *p, *q;	struct strlist **lpp;	int half;	int n;	if (len <= 1)		return list;	half = len >> 1;      	p = list;	for (n = half ; --n >= 0 ; ) {		q = p;		p = p->next;	}	q->next = NULL;			/* terminate first half of list */	q = msort(list, half);		/* sort first half of list */	p = msort(p, len - half);		/* sort second half */	lpp = &list;	for (;;) {		if (strcmp(p->text, q->text) < 0) {			*lpp = p;			lpp = &p->next;			if ((p = *lpp) == NULL) {				*lpp = q;				break;			}		} else {			*lpp = q;			lpp = &q->next;			if ((q = *lpp) == NULL) {				*lpp = p;				break;			}		}	}	return list;}/* * Returns true if the pattern matches the string. */intpatmatch(pattern, string)	char *pattern;	char *string;	{	if (pattern[0] == '!' && pattern[1] == '!')		return 1 - pmatch(pattern + 2, string);	else		return pmatch(pattern, string);}STATIC intpmatch(pattern, string)	char *pattern;	char *string;	{	register char *p, *q;	register char c;	p = pattern;	q = string;	for (;;) {		switch (c = *p++) {		case '\0':			goto breakloop;		case CTLESC:			if (*q++ != *p++)				return 0;			break;		case '?':			if (*q++ == '\0')				return 0;			break;		case '*':			c = *p;			if (c != CTLESC && c != '?' && c != '*' && c != '[') {				while (*q != c) {					if (*q == '\0')						return 0;					q++;				}			}			do {				if (pmatch(p, q))					return 1;			} while (*q++ != '\0');			return 0;		case '[': {			char *endp;			int invert, found;			char chr;			endp = p;			if (*endp == '!')				endp++;			for (;;) {				if (*endp == '\0')					goto dft;		/* no matching ] */				if (*endp == CTLESC)					endp++;				if (*++endp == ']')					break;			}			invert = 0;			if (*p == '!') {				invert++;				p++;			}			found = 0;			chr = *q++;			c = *p++;			do {				if (c == CTLESC)					c = *p++;				if (*p == '-' && p[1] != ']') {					p++;					if (*p == CTLESC)						p++;					if (chr >= c && chr <= *p)						found = 1;					p++;				} else {					if (chr == c)						found = 1;				}			} while ((c = *p++) != ']');			if (found == invert)				return 0;			break;		}dft:	    default:			if (*q++ != c)				return 0;			break;		}	}breakloop:	if (*q != '\0')		return 0;	return 1;}/* * Remove any CTLESC characters from a string. */voidrmescapes(str)	char *str;	{	register char *p, *q;	p = str;	while (*p != CTLESC) {		if (*p++ == '\0')			return;	}	q = p;	while (*p) {		if (*p == CTLESC)			p++;		*q++ = *p++;	}	*q = '\0';}/* * See if a pattern matches in a case statement. */intcasematch(pattern, val)	union node *pattern;	char *val;	{	struct stackmark smark;	int result;	char *p;	setstackmark(&smark);	argbackq = pattern->narg.backquote;	STARTSTACKSTR(expdest);	ifslastp = NULL;	/* Preserve any CTLESC characters inserted previously, so that	   we won't expand reg exps which are inside strings.  */	argstr(pattern->narg.text, 1);	STPUTC('\0', expdest);	p = grabstackstr(expdest);	result = patmatch(p, val);	popstackmark(&smark);	return result;}

⌨️ 快捷键说明

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