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

📄 message.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "common.h"#include "send.h"#include "../smtp/smtp.h"#include "../smtp/y.tab.h"/* global to this file */static Reprog *rfprog;static Reprog *fprog;#define VMLIMIT (64*1024)#define MSGLIMIT (128*1024*1024)int received;	/* from rfc822.y */static String*	getstring(Node *p);static String*	getaddr(Node *p);extern intdefault_from(message *mp){	char *cp, *lp;	cp = getenv("upasname");	lp = getlog();	if(lp == nil)		return -1;	if(cp && *cp)		s_append(mp->sender, cp);	else		s_append(mp->sender, lp);	s_append(mp->date, thedate());	return 0;}extern message *m_new(void){	message *mp;	mp = (message *)mallocz(sizeof(message), 1);	if (mp == 0) {		perror("message:");		exit(1);	}	mp->sender = s_new();	mp->replyaddr = s_new();	mp->date = s_new();	mp->body = s_new();	mp->size = 0;	mp->fd = -1;	return mp;}extern voidm_free(message *mp){	if(mp->fd >= 0){		close(mp->fd);		sysremove(s_to_c(mp->tmp));		s_free(mp->tmp);	}	s_free(mp->sender);	s_free(mp->date);	s_free(mp->body);	s_free(mp->havefrom);	s_free(mp->havesender);	s_free(mp->havereplyto);	s_free(mp->havesubject);	free((char *)mp);}/* read a message into a temp file , return an open fd to it */static intm_read_to_file(Biobuf *fp, message *mp){	int fd;	int n;	String *file;	char buf[4*1024];	file = s_new();	/*	 *  create temp file to be remove on close	 */	abspath("mtXXXXXX", UPASTMP, file);	mktemp(s_to_c(file));	if((fd = syscreate(s_to_c(file), ORDWR|ORCLOSE, 0600))<0){		s_free(file);		return -1;	}	mp->tmp = file;	/*	 *  read the rest into the temp file	 */	while((n = Bread(fp, buf, sizeof(buf))) > 0){		if(write(fd, buf, n) != n){			close(fd);			return -1;		}		mp->size += n;		if(mp->size > MSGLIMIT){			mp->size = -1;			break;		}	}	mp->fd = fd;	return 0;}/* get the first address from a node */static String*getaddr(Node *p){	for(; p; p = p->next)		if(p->s && p->addr)			return s_copy(s_to_c(p->s));	return nil;}/* get the text of a header line minus the field name */static String*getstring(Node *p){	String *s;	s = s_new();	if(p == nil)		return s;	for(p = p->next; p; p = p->next){		if(p->s){			s_append(s, s_to_c(p->s));		}else{			s_putc(s, p->c);			s_terminate(s);		}		if(p->white)			s_append(s, s_to_c(p->white));	}	return s;}static char *fieldname[] ={[WORD-WORD]	"WORD",[DATE-WORD]	"DATE",[RESENT_DATE-WORD]	"RESENT_DATE",[RETURN_PATH-WORD]	"RETURN_PATH",[FROM-WORD]	"FROM",[SENDER-WORD]	"SENDER",[REPLY_TO-WORD]	"REPLY_TO",[RESENT_FROM-WORD]	"RESENT_FROM",[RESENT_SENDER-WORD]	"RESENT_SENDER",[RESENT_REPLY_TO-WORD]	"RESENT_REPLY_TO",[SUBJECT-WORD]	"SUBJECT",[TO-WORD]	"TO",[CC-WORD]	"CC",[BCC-WORD]	"BCC",[RESENT_TO-WORD]	"RESENT_TO",[RESENT_CC-WORD]	"RESENT_CC",[RESENT_BCC-WORD]	"RESENT_BCC",[REMOTE-WORD]	"REMOTE",[PRECEDENCE-WORD]	"PRECEDENCE",[MIMEVERSION-WORD]	"MIMEVERSION",[CONTENTTYPE-WORD]	"CONTENTTYPE",[MESSAGEID-WORD]	"MESSAGEID",[RECEIVED-WORD]	"RECEIVED",[MAILER-WORD]	"MAILER",[BADTOKEN-WORD]	"BADTOKEN",};/* fix 822 addresses */static voidrfc822cruft(message *mp){	Field *f;	Node *p;	String *body, *s;	char *cp;	/*	 *  parse headers in in-core part	 */	yyinit(s_to_c(mp->body), s_len(mp->body));	mp->rfc822headers = 0;	yyparse();	mp->rfc822headers = 1;	mp->received = received;	/*	 *  remove equivalent systems in all addresses	 */	body = s_new();	cp = s_to_c(mp->body);	for(f = firstfield; f; f = f->next){		if(f->node->c == MIMEVERSION)			mp->havemime = 1;		if(f->node->c == FROM)			mp->havefrom = getaddr(f->node);		if(f->node->c == SENDER)			mp->havesender = getaddr(f->node);		if(f->node->c == REPLY_TO)			mp->havereplyto = getaddr(f->node);		if(f->node->c == TO)			mp->haveto = 1;		if(f->node->c == DATE)			mp->havedate = 1;		if(f->node->c == SUBJECT)			mp->havesubject = getstring(f->node);		if(f->node->c == PRECEDENCE && f->node->next && f->node->next->next){			s = f->node->next->next->s;			if(s && (strcmp(s_to_c(s), "bulk") == 0				|| strcmp(s_to_c(s), "Bulk") == 0))					mp->bulk = 1;		}		for(p = f->node; p; p = p->next){			if(p->s){				if(p->addr){					cp = skipequiv(s_to_c(p->s));					s_append(body, cp);				} else 					s_append(body, s_to_c(p->s));			}else{				s_putc(body, p->c);				s_terminate(body);			}			if(p->white)				s_append(body, s_to_c(p->white));			cp = p->end+1;		}		s_append(body, "\n");	}	if(*s_to_c(body) == 0){		s_free(body);		return;	}	if(*cp != '\n')		s_append(body, "\n");	s_memappend(body, cp, s_len(mp->body) - (cp - s_to_c(mp->body)));	s_terminate(body);	firstfield = 0;	mp->size += s_len(body) - s_len(mp->body);	s_free(mp->body);	mp->body = body;}/* read in a message, interpret the 'From' header */extern message *m_read(Biobuf *fp, int rmail, int interactive){	message *mp;	Resub subexp[10];	char *line;	int first;	int n;	mp = m_new();	/* parse From lines if remote */	if (rmail) {		/* get remote address */		String *sender=s_new();		if (rfprog == 0)			rfprog = regcomp(REMFROMRE);		first = 1;		while(s_read_line(fp, s_restart(mp->body)) != 0) {			memset(subexp, 0, sizeof(subexp));			if (regexec(rfprog, s_to_c(mp->body), subexp, 10) == 0){				if(first == 0)					break;				if (fprog == 0)					fprog = regcomp(FROMRE);				memset(subexp, 0, sizeof(subexp));				if(regexec(fprog, s_to_c(mp->body), subexp,10) == 0)					break;				s_restart(mp->body);				append_match(subexp, s_restart(sender), SENDERMATCH);				append_match(subexp, s_restart(mp->date), DATEMATCH);				break;			}			append_match(subexp, s_restart(sender), REMSENDERMATCH);			append_match(subexp, s_restart(mp->date), REMDATEMATCH);			if(subexp[REMSYSMATCH].sp!=subexp[REMSYSMATCH].ep){				append_match(subexp, mp->sender, REMSYSMATCH);				s_append(mp->sender, "!");			}			first = 0;		}		s_append(mp->sender, s_to_c(sender));		s_free(sender);	}	if(*s_to_c(mp->sender)=='\0')		default_from(mp);	/* if sender address is unreturnable, treat message as bulk mail */	if(!returnable(s_to_c(mp->sender)))		mp->bulk = 1;	/* get body */	if(interactive && !rmail){		/* user typing on terminal: terminator == '.' or EOF */		for(;;) {			line = s_read_line(fp, mp->body);			if (line == 0)				break;			if (strcmp(".\n", line)==0) {				mp->body->ptr -= 2;				*mp->body->ptr = '\0';				break;			}		}		mp->size = mp->body->ptr - mp->body->base;	} else {		/*		 *  read up to VMLIMIT bytes (more or less) into main memory.		 *  if message is longer put the rest in a tmp file.		 */		mp->size = mp->body->ptr - mp->body->base;		n = s_read(fp, mp->body, VMLIMIT);		if(n < 0){			perror("m_read");			exit(1);		}		mp->size += n;		if(n == VMLIMIT){			if(m_read_to_file(fp, mp) < 0){				perror("m_read");				exit(1);			}		}	}	/*	 *  ignore 0 length messages from a terminal	 */	if (!rmail && mp->size == 0)		return 0;	rfc822cruft(mp);	return mp;}/* return a piece of message starting at `offset' */extern intm_get(message *mp, long offset, char **pp){	static char buf[4*1024];	/*	 *  are we past eof?	 */	if(offset >= mp->size)		return 0;	/*	 *  are we in the virtual memory portion?	 */	if(offset < s_len(mp->body)){		*pp = mp->body->base + offset;		return mp->body->ptr - mp->body->base - offset;	}	/*	 *  read it from the temp file	 */	offset -= s_len(mp->body);	if(mp->fd < 0)		return -1;	if(seek(mp->fd, offset, 0)<0)		return -1;	*pp = buf;	return read(mp->fd, buf, sizeof buf);}/* output the message body without ^From escapes */static intm_noescape(message *mp, Biobuf *fp){	long offset;	int n;	char *p;	for(offset = 0; offset < mp->size; offset += n){		n = m_get(mp, offset, &p);		if(n <= 0){			Bflush(fp);			return -1;		}		if(Bwrite(fp, p, n) < 0)			return -1;	}	return Bflush(fp);}/* *  Output the message body with '^From ' escapes. *  Ensures that any line starting with a 'From ' gets a ' ' stuck *  in front of it. */static intm_escape(message *mp, Biobuf *fp){	char *p, *np;	char *end;	long offset;	int m, n;	char *start;	for(offset = 0; offset < mp->size; offset += n){		n = m_get(mp, offset, &start);		if(n < 0){			Bflush(fp);			return -1;		}		p = start;		for(end = p+n; p < end; p += m){			np = memchr(p, '\n', end-p);			if(np == 0){				Bwrite(fp, p, end-p);				break;			}			m = np - p + 1;			if(m > 5 && strncmp(p, "From ", 5) == 0)				Bputc(fp, ' ');			Bwrite(fp, p, m);		}	}	Bflush(fp);	return 0;}static intprintfrom(message *mp, Biobuf *fp){	String *s;	int rv;	if(!returnable(s_to_c(mp->sender)))		return Bprint(fp, "From: Postmaster\n");	s = username(mp->sender);	if(s) {		s_append(s, " <");		s_append(s, s_to_c(mp->sender));		s_append(s, ">");	} else {		s = s_copy(s_to_c(mp->sender));	}	s = unescapespecial(s);	rv = Bprint(fp, "From: %s\n", s_to_c(s));	s_free(s);	return rv;}static char *rewritezone(char *z){	int mindiff;	char s;	Tm *tm;	static char x[7];	tm = localtime(time(0));	mindiff = tm->tzoff/60;	/* if not in my timezone, don't change anything */	if(strcmp(tm->zone, z) != 0)		return z;	if(mindiff < 0){		s = '-';		mindiff = -mindiff;	} else		s = '+';	sprint(x, "%c%.2d%.2d", s, mindiff/60, mindiff%60);	return x;}intisutf8(String *s){	char *p;		for(p = s_to_c(s);  *p; p++)		if(*p&0x80)			return 1;	return 0;}voidprintutf8mime(Biobuf *b){	Bprint(b, "MIME-Version: 1.0\n");	Bprint(b, "Content-Type: text/plain; charset=\"UTF-8\"\n");	Bprint(b, "Content-Transfer-Encoding: 8bit\n");}/* output a message */extern intm_print(message *mp, Biobuf *fp, char *remote, int mbox){	String *date, *sender;	char *f[6];	int n;	sender = unescapespecial(s_clone(mp->sender));	if (remote != 0){		if(print_remote_header(fp,s_to_c(sender),s_to_c(mp->date),remote) < 0){			s_free(sender);			return -1;		}	} else {		if(print_header(fp, s_to_c(sender), s_to_c(mp->date)) < 0){			s_free(sender);			return -1;		}	}	s_free(sender);	if(!rmail && !mp->havedate){		/* add a date: line Date: Sun, 19 Apr 1998 12:27:52 -0400 */		date = s_copy(s_to_c(mp->date));		n = getfields(s_to_c(date), f, 6, 1, " \t");		if(n == 6)			Bprint(fp, "Date: %s, %s %s %s %s %s\n", f[0], f[2], f[1],			 f[5], f[3], rewritezone(f[4]));	}	if(!rmail && !mp->havemime && isutf8(mp->body))		printutf8mime(fp);	if(mp->to){		/* add the to: line */		if (Bprint(fp, "%s\n", s_to_c(mp->to)) < 0)			return -1;		/* add the from: line */		if (!mp->havefrom && printfrom(mp, fp) < 0)			return -1;		if(!mp->rfc822headers && *s_to_c(mp->body) != '\n')			if (Bprint(fp, "\n") < 0)				return -1;	} else if(!rmail){		/* add the from: line */		if (!mp->havefrom && printfrom(mp, fp) < 0)			return -1;		if(!mp->rfc822headers && *s_to_c(mp->body) != '\n')			if (Bprint(fp, "\n") < 0)				return -1;	}	if (!mbox)		return m_noescape(mp, fp);	return m_escape(mp, fp);}/* print just the message body */extern intm_bprint(message *mp, Biobuf *fp){	return m_noescape(mp, fp);}

⌨️ 快捷键说明

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