msg.c

来自「这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易」· C语言 代码 · 共 1,781 行 · 第 1/3 页

C
1,781
字号
		c = headChar(0);		if(c == '@'){			for(;;){				c = headChar(1);				if(c != '@'){					e = nil;					break;				}				headDomain(e);				c = headChar(1);				if(c != ','){					e = s;					break;				}			}			if(c != ':')				e = nil;		}		if(e != nil)			e = headAddrSpec(s, nil);		if(headChar(1) != '>')			e = nil;	}	/*	 * e points to @host, or nil if an error occured	 */	if(e == nil){		free(personal);		addr = nil;	}else{		if(*e != '\0')			*e++ = '\0';		else			e = site;		addr = MKZ(MAddr);		addr->personal = personal;		addr->box = estrdup(s);		addr->host = estrdup(e);	}	free(s);	return addr;}/* * phrase	: word *		| phrase word * w is the optional initial word of the phrase * returns the end of the phrase, or nil if a failure occured */static char*headPhrase(char *e, char *w){	int c;	for(;;){		if(w == nil){			w = headWord();			if(w == nil)				return nil;		}		if(w[0] == '"')			stripQuotes(w);		strcpy(e, w);		free(w);		w = nil;		e = strchr(e, '\0');		c = headChar(0);		if(c <= ' ' || strchr(headAtomStop, c) != nil && c != '"')			break;		*e++ = ' ';		*e = '\0';	}	return e;}/* * addr-spec	: local-part '@' domain *		| local-part			extension to allow ! and local names * local-part	: word *		| local-part '.' word * * if no '@' is present, rewrite d!e!f!u as @d,@e:u@f, * where d, e, f are valid domain components. * the @d,@e: is ignored, since routes are ignored. * perhaps they should be rewritten as e!f!u@d, but that is inconsistent with upas. * * returns a pointer to '@', the end if none, or nil if there was an error */static char*headAddrSpec(char *e, char *w){	char *s, *at, *b, *bang, *dom;	int c;	s = e;	for(;;){		if(w == nil){			w = headWord();			if(w == nil)				return nil;		}		strcpy(e, w);		free(w);		w = nil;		e = strchr(e, '\0');		lastWhite = headStr;		c = headChar(0);		if(c != '.')			break;		headChar(1);		*e++ = '.';		*e = '\0';	}	if(c != '@'){		/*		 * extenstion: allow name without domain		 * check for domain!xxx		 */		bang = domBang(s);		if(bang == nil)			return e;		/*		 * if dom1!dom2!xxx, ignore dom1!		 */		dom = s;		for(; b = domBang(bang + 1); bang = b)			dom = bang + 1;		/*		 * convert dom!mbox into mbox@dom		 */		*bang = '@';		strrev(dom, bang);		strrev(bang+1, e);		strrev(dom, e);		bang = &dom[e - bang - 1];		if(dom > s){			bang -= dom - s;			for(e = s; *e = *dom; e++)				dom++;		}		/*		 * eliminate a trailing '.'		 */		if(e[-1] == '.')			e[-1] = '\0';		return bang;	}	headChar(1);	at = e;	*e++ = '@';	*e = '\0';	if(!headDomain(e))		return nil;	return at;}/* * find the ! in domain!rest, where domain must have at least * one internal '.' */static char*domBang(char *s){	int dot, c;	dot = 0;	for(; c = *s; s++){		if(c == '!'){			if(!dot || dot == 1 && s[-1] == '.' || s[1] == '\0')				return nil;			return s;		}		if(c == '"')			break;		if(c == '.')			dot++;	}	return nil;}/* * domain	: sub-domain *		| domain '.' sub-domain * returns the end of the domain, or nil if a failure occured */static char*headDomain(char *e){	char *w;	for(;;){		w = headSubDomain();		if(w == nil)			return nil;		strcpy(e, w);		free(w);		e = strchr(e, '\0');		lastWhite = headStr;		if(headChar(0) != '.')			break;		headChar(1);		*e++ = '.';		*e = '\0';	}	return e;}/* * id		: 'content-id' ':' msg-id * msg-id	: '<' addr-spec '>' */static voidmimeId(Header *h){	char *s, *e, *w;	if(headChar(1) != ':')		return;	if(headChar(1) != '<')		return;	s = emalloc(strlen((char*)headStr) + 3);	e = s;	*e++ = '<';	e = headAddrSpec(e, nil);	if(e == nil || headChar(1) != '>'){		free(s);		return;	}	e = strchr(e, '\0');	*e++ = '>';	e[0] = '\0';	w = strdup(s);	free(s);	h->id = mkMimeHdr(w, nil, nil);}/* * description	: 'content-description' ':' *text */static voidmimeDescription(Header *h){	if(headChar(1) != ':')		return;	headSkipWhite(0);	h->description = mkMimeHdr(headText(), nil, nil);}/* * disposition	: 'content-disposition' ':' token params */static voidmimeDisposition(Header *h){	char *s;	if(headChar(1) != ':')		return;	s = headAtom(mimeTokenStop);	if(s == nil)		return;	h->disposition = mkMimeHdr(s, nil, mimeParams());}/* * md5		: 'content-md5' ':' token */static voidmimeMd5(Header *h){	char *s;	if(headChar(1) != ':')		return;	s = headAtom(mimeTokenStop);	if(s == nil)		return;	h->md5 = mkMimeHdr(s, nil, nil);}/* * language	: 'content-language' ':' langs * langs	: token *		| langs commas token * commas	: ',' *		| commas ',' */static voidmimeLanguage(Header *h){	MimeHdr head, *last;	char *s;	head.next = nil;	last = &head;	for(;;){		s = headAtom(mimeTokenStop);		if(s == nil)			break;		last->next = mkMimeHdr(s, nil, nil);		last = last->next;		while(headChar(0) != ',')			headChar(1);	}	h->language = head.next;}/* * token	: 1*<char 33-255, except "()<>@,;:\\\"/[]?=" aka mimeTokenStop> * atom		: 1*<chars 33-255, except "()<>@,;:\\\".[]" aka headAtomStop> * note this allows 8 bit characters, which occur in utf. */static char*headAtom(char *disallowed){	char *s;	int c, ns, as;	headSkipWhite(0);	s = emalloc(StrAlloc);	as = StrAlloc;	ns = 0;	for(;;){		c = *headStr++;		if(c <= ' ' || strchr(disallowed, c) != nil){			headStr--;			break;		}		s[ns++] = c;		if(ns >= as){			as += StrAlloc;			s = erealloc(s, as);		}	}	if(ns == 0){		free(s);		return 0;	}	s[ns] = '\0';	return s;}/* * sub-domain	: atom | domain-lit */static char *headSubDomain(void){	if(headChar(0) == '[')		return headQuoted('[', ']');	return headAtom(headAtomStop);}/* * word	: atom | quoted-str */static char *headWord(void){	if(headChar(0) == '"')		return headQuoted('"', '"');	return headAtom(headAtomStop);}/* * q is a quoted string.  remove enclosing " and and \ escapes */static voidstripQuotes(char *q){	char *s;	int c;	if(q == nil)		return;	s = q++;	while(c = *q++){		if(c == '\\'){			c = *q++;			if(!c)				return;		}		*s++ = c;	}	s[-1] = '\0';}/* * quoted-str	: '"' *(any char but '"\\\r', or '\' any char, or linear-white-space) '"' * domain-lit	: '[' *(any char but '[]\\\r', or '\' any char, or linear-white-space) ']' */static char *headQuoted(int start, int stop){	char *s;	int c, ns, as;	if(headChar(1) != start)		return nil;	s = emalloc(StrAlloc);	as = StrAlloc;	ns = 0;	s[ns++] = start;	for(;;){		c = *headStr;		if(c == stop){			headStr++;			break;		}		if(c == '\0'){			free(s);			return nil;		}		if(c == '\r'){			headStr++;			continue;		}		if(c == '\n'){			headStr++;			while(*headStr == ' ' || *headStr == '\t' || *headStr == '\r' || *headStr == '\n')				headStr++;			c = ' ';		}else if(c == '\\'){			headStr++;			s[ns++] = c;			c = *headStr;			if(c == '\0'){				free(s);				return nil;			}			headStr++;		}else			headStr++;		s[ns++] = c;		if(ns + 1 >= as){	/* leave room for \c or "0 */			as += StrAlloc;			s = erealloc(s, as);		}	}	s[ns++] = stop;	s[ns] = '\0';	return s;}/* * headText	: contents of rest of header line */static char *headText(void){	uchar *v;	char *s;	v = headStr;	headToEnd();	s = emalloc(headStr - v + 1);	memmove(s, v, headStr - v);	s[headStr - v] = '\0';	return s;}/* * white space is ' ' '\t' or nested comments. * skip white space. * if com and a comment is seen, * return it's contents and stop processing white space. */static char*headSkipWhite(int com){	char *s;	int c, incom, as, ns;	s = nil;	as = StrAlloc;	ns = 0;	if(com)		s = emalloc(StrAlloc);	incom = 0;	for(; c = *headStr; headStr++){		switch(c){		case ' ':		case '\t':		case '\r':			c = ' ';			break;		case '\n':			c = headStr[1];			if(c != ' ' && c != '\t')				goto breakout;			c = ' ';			break;		case '\\':			if(com && incom)				s[ns++] = c;			c = headStr[1];			if(c == '\0')				goto breakout;			headStr++;			break;		case '(':			incom++;			if(incom == 1)				continue;			break;		case ')':			incom--;			if(com && !incom){				s[ns] = '\0';				return s;			}			break;		default:			if(!incom)				goto breakout;			break;		}		if(com && incom && (c != ' ' || ns > 0 && s[ns-1] != ' ')){			s[ns++] = c;			if(ns + 1 >= as){	/* leave room for \c or 0 */				as += StrAlloc;				s = erealloc(s, as);			}		}	}breakout:;	free(s);	return nil;}/* * return the next non-white character */static intheadChar(int eat){	int c;	headSkipWhite(0);	c = *headStr;	if(eat && c != '\0' && c != '\n')		headStr++;	return c;}static voidheadToEnd(void){	uchar *s;	int c;	for(;;){		s = headStr;		c = *s++;		while(c == '\r')			c = *s++;		if(c == '\n'){			c = *s++;			if(c != ' ' && c != '\t')				return;		}		if(c == '\0')			return;		headStr = s;	}}static voidheadSkip(void){	int c;	while(c = *headStr){		headStr++;		if(c == '\n'){			c = *headStr;			if(c == ' ' || c == '\t')				continue;			return;		}	}}

⌨️ 快捷键说明

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