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

📄 match.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <regexp.h>#include <thread.h>#include <plumb.h>#include "plumber.h"static char*nonnil(char *s){	if(s == nil)		return "";	return s;}intverbis(int obj, Plumbmsg *m, Rule *r){	switch(obj){	default:		fprint(2, "unimplemented 'is' object %d\n", obj);		break;	case OData:		return strcmp(m->data, r->qarg) == 0;	case ODst:		return strcmp(m->dst, r->qarg) == 0;	case OType:		return strcmp(m->type, r->qarg) == 0;	case OWdir:		return strcmp(m->wdir, r->qarg) == 0;	case OSrc:		return strcmp(m->src, r->qarg) == 0;	}	return 0;}static voidsetvar(Resub rs[10], char *match[10]){	int i, n;	for(i=0; i<10; i++){		free(match[i]);		match[i] = nil;	}	for(i=0; i<10 && rs[i].sp!=nil; i++){		n = rs[i].ep-rs[i].sp;		match[i] = emalloc(n+1);		memmove(match[i], rs[i].sp, n);		match[i][n] = '\0';	}}intclickmatch(Reprog *re, char *text, Resub rs[10], int click){	char *clickp;	int i, w;	Rune r;	/* click is in characters, not bytes */	for(i=0; i<click && text[i]!='\0'; i+=w)		w = chartorune(&r, text+i);	clickp = text+i;	for(i=0; i<=click; i++){		memset(rs, 0, 10*sizeof(Resub));		if(regexec(re, text+i, rs, 10))			if(rs[0].sp<=clickp && clickp<=rs[0].ep)				return 1;	}	return 0;}intverbmatches(int obj, Plumbmsg *m, Rule *r, Exec *e){	Resub rs[10];	char *clickval, *alltext;	int p0, p1, ntext;	memset(rs, 0, sizeof rs);	ntext = -1;	switch(obj){	default:		fprint(2, "unimplemented 'matches' object %d\n", obj);		break;	case OData:		clickval = plumblookup(m->attr, "click");		if(clickval == nil){			alltext = m->data;			ntext = m->ndata;			goto caseAlltext;		}		if(!clickmatch(r->regex, m->data, rs, atoi(clickval)))			break;		p0 = rs[0].sp - m->data;		p1 = rs[0].ep - m->data;		if(e->p0 >=0 && !(p0==e->p0 && p1==e->p1))			break;		e->clearclick = 1;		e->setdata = 1;		e->p0 = p0;		e->p1 = p1;		setvar(rs, e->match);		return 1;	case ODst:		alltext = m->dst;		goto caseAlltext;	case OType:		alltext = m->type;		goto caseAlltext;	case OWdir:		alltext = m->wdir;		goto caseAlltext;	case OSrc:		alltext = m->src;		/* fall through */	caseAlltext:		/* must match full text */		if(ntext < 0)			ntext = strlen(alltext);		if(!regexec(r->regex, alltext, rs, 10) || rs[0].sp!=alltext || rs[0].ep!=alltext+ntext)			break;		setvar(rs, e->match);		return 1;	}	return 0;}intisfile(char *file, ulong maskon, ulong maskoff){	Dir *d;	int mode;	d = dirstat(file);	if(d == nil)		return 0;	mode = d->mode;	free(d);	if((mode & maskon) == 0)		return 0;	if(mode & maskoff)		return 0;	return 1;}char*absolute(char *dir, char *file){	char *p;	if(file[0] == '/')		return estrdup(file);	p = emalloc(strlen(dir)+1+strlen(file)+1);	sprint(p, "%s/%s", dir, file);	return cleanname(p);}intverbisfile(int obj, Plumbmsg *m, Rule *r, Exec *e, ulong maskon, ulong maskoff, char **var){	char *file;	switch(obj){	default:		fprint(2, "unimplemented 'isfile' object %d\n", obj);		break;	case OArg:		file = absolute(m->wdir, expand(e, r->arg, nil));		if(isfile(file, maskon, maskoff)){			*var = file;			return 1;		}		free(file);		break;	case OData:	case OWdir:		file = absolute(m->wdir, obj==OData? m->data : m->wdir);		if(isfile(file, maskon, maskoff)){			*var = file;			return 1;		}		free(file);		break;	}	return 0;}intverbset(int obj, Plumbmsg *m, Rule *r, Exec *e){	char *new;	switch(obj){	default:		fprint(2, "unimplemented 'is' object %d\n", obj);		break;	case OData:		new = estrdup(expand(e, r->arg, nil));		m->ndata = strlen(new);		free(m->data);		m->data = new;		e->p0 = -1;		e->p1 = -1;		e->setdata = 0;		return 1;	case ODst:		new = estrdup(expand(e, r->arg, nil));		free(m->dst);		m->dst = new;		return 1;	case OType:		new = estrdup(expand(e, r->arg, nil));		free(m->type);		m->type = new;		return 1;	case OWdir:		new = estrdup(expand(e, r->arg, nil));		free(m->wdir);		m->wdir = new;		return 1;	case OSrc:		new = estrdup(expand(e, r->arg, nil));		free(m->src);		m->src = new;		return 1;	}	return 0;}intverbadd(int obj, Plumbmsg *m, Rule *r, Exec *e){	switch(obj){	default:		fprint(2, "unimplemented 'add' object %d\n", obj);		break;	case OAttr:		m->attr = plumbaddattr(m->attr, plumbunpackattr(expand(e, r->arg, nil)));		return 1;	}	return 0;}intverbdelete(int obj, Plumbmsg *m, Rule *r, Exec *e){	char *a;	switch(obj){	default:		fprint(2, "unimplemented 'delete' object %d\n", obj);		break;	case OAttr:		a = expand(e, r->arg, nil);		if(plumblookup(m->attr, a) == nil)			break;		m->attr = plumbdelattr(m->attr, a);		return 1;	}	return 0;}intmatchpat(Plumbmsg *m, Exec *e, Rule *r){	switch(r->verb){	default:		fprint(2, "unimplemented verb %d\n", r->verb);		break;	case VAdd:		return verbadd(r->obj, m, r, e);	case VDelete:		return verbdelete(r->obj, m, r, e);	case VIs:		return verbis(r->obj, m, r);	case VIsdir:		return verbisfile(r->obj, m, r, e, DMDIR, 0, &e->dir);	case VIsfile:		return verbisfile(r->obj, m, r, e, ~DMDIR, DMDIR, &e->file);	case VMatches:		return verbmatches(r->obj, m, r, e);	case VSet:		verbset(r->obj, m, r, e);		return 1;	}	return 0;}voidfreeexec(Exec *exec){	int i;	if(exec == nil)		return;	free(exec->dir);	free(exec->file);	for(i=0; i<10; i++)		free(exec->match[i]);	free(exec);}Exec*newexec(Plumbmsg *m){	Exec *exec;		exec = emalloc(sizeof(Exec));	exec->msg = m;	exec->p0 = -1;	exec->p1 = -1;	return exec;}voidrewrite(Plumbmsg *m, Exec *e){	Plumbattr *a, *prev;	if(e->clearclick){		prev = nil;		for(a=m->attr; a!=nil; a=a->next){			if(strcmp(a->name, "click") == 0){				if(prev == nil)					m->attr = a->next;				else					prev->next = a->next;				free(a->name);				free(a->value);					free(a);				break;			}			prev = a;		}		if(e->setdata){			free(m->data);			m->data = estrdup(expand(e, "$0", nil));			m->ndata = strlen(m->data);		}	}}char**buildargv(char *s, Exec *e){	char **av;	int ac;	ac = 0;	av = nil;	for(;;){		av = erealloc(av, (ac+1) * sizeof(char*));		av[ac] = nil;		while(*s==' ' || *s=='\t')			s++;		if(*s == '\0')			break;		av[ac++] = estrdup(expand(e, s, &s));	}	return av;}Exec*matchruleset(Plumbmsg *m, Ruleset *rs){	int i;	Exec *exec;	if(m->dst!=nil && m->dst[0]!='\0' && rs->port!=nil && strcmp(m->dst, rs->port)!=0)		return nil;	exec = newexec(m);	for(i=0; i<rs->npat; i++)		if(!matchpat(m, exec, rs->pat[i])){			freeexec(exec);			return nil;		}	if(rs->port!=nil && (m->dst==nil || m->dst[0]=='\0')){		free(m->dst);		m->dst = estrdup(rs->port);	}	rewrite(m, exec);	return exec;}enum{	NARGS		= 100,	NARGCHAR	= 8*1024,	EXECSTACK 	= 4096+(NARGS+1)*sizeof(char*)+NARGCHAR};/* copy argv to stack and free the incoming strings, so we don't leak argument vectors */voidstackargv(char **inargv, char *argv[NARGS+1], char args[NARGCHAR]){	int i, n;	char *s, *a;	s = args;	for(i=0; i<NARGS; i++){		a = inargv[i];		if(a == nil)			break;		n = strlen(a)+1;		if((s-args)+n >= NARGCHAR)	/* too many characters */			break;		argv[i] = s;		memmove(s, a, n);		s += n;		free(a);	}	argv[i] = nil;}voidexecproc(void *v){	char **av;	char buf[1024], *args[NARGS+1], argc[NARGCHAR];	rfork(RFFDG);	close(0);	open("/dev/null", OREAD);	av = v;	stackargv(av, args, argc);	free(av);	procexec(nil, args[0], args);	if(args[0][0]!='/' && strncmp(args[0], "./", 2)!=0 && strncmp(args[0], "../", 3)!=0)		snprint(buf, sizeof buf, "/bin/%s", args[0]);	procexec(nil, buf, args);	threadexits("can't exec");}char*startup(Ruleset *rs, Exec *e){	char **argv;	int i;	if(rs != nil)		for(i=0; i<rs->nact; i++){			if(rs->act[i]->verb == VStart)				goto Found;			if(rs->act[i]->verb == VClient){				if(e->msg->dst==nil || e->msg->dst[0]=='\0')					return "no port for \"client\" rule";				e->holdforclient = 1;				goto Found;			}		}	return "no start action for plumb message";Found:	argv = buildargv(rs->act[i]->arg, e);	if(argv[0] == nil)		return "empty argument list";	proccreate(execproc, argv, EXECSTACK);	return nil;}

⌨️ 快捷键说明

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