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

📄 mbox.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	}}static voidcencoding(Message *m, Header *h, char *p){	p += h->len;	p = skipwhite(p);	if(cistrncmp(p, "base64", 6) == 0)		m->encoding = Ebase64;	else if(cistrncmp(p, "quoted-printable", 16) == 0)		m->encoding = Equoted;}static voidcdisposition(Message *m, Header *h, char *p){	p += h->len;	p = skipwhite(p);	while(*p){		if(cistrncmp(p, "inline", 6) == 0){			m->disposition = Dinline;		} else if(cistrncmp(p, "attachment", 10) == 0){			m->disposition = Dfile;		} else if(cistrncmp(p, "filename=", 9) == 0){			p += 9;			setfilename(m, p);		}		p = skiptosemi(p);	}}ulong msgallocd, msgfreed;Message*newmessage(Message *parent){	static int id;	Message *m;	msgallocd++;	m = emalloc(sizeof(*m));	memset(m, 0, sizeof(*m));	m->disposition = Dnone;	m->type = s_copy("text/plain");	m->charset = s_copy("iso-8859-1");	m->id = newid();	if(parent)		sprint(m->name, "%d", ++(parent->subname));	if(parent == nil)		parent = m;	m->whole = parent;	m->hlen = -1;	return m;}// delete a message from a mailboxvoiddelmessage(Mailbox *mb, Message *m){	Message **l;	int i;	mb->vers++;	msgfreed++;	if(m->whole != m){		// unchain from parent		for(l = &m->whole->part; *l && *l != m; l = &(*l)->next)			;		if(*l != nil)			*l = m->next;		// clear out of name lookup hash table		if(m->whole->whole == m->whole)			hfree(PATH(mb->id, Qmbox), m->name);		else			hfree(PATH(m->whole->id, Qdir), m->name);		for(i = 0; i < Qmax; i++)			hfree(PATH(m->id, Qdir), dirtab[i]);	}	/* recurse through sub-parts */	while(m->part)		delmessage(mb, m->part);	/* free memory */	if(m->mallocd)		free(m->start);	if(m->hallocd)		free(m->header);	if(m->ballocd)		free(m->body);	s_free(m->unixfrom);	s_free(m->unixdate);	s_free(m->unixheader);	s_free(m->from822);	s_free(m->sender822);	s_free(m->to822);	s_free(m->bcc822);	s_free(m->cc822);	s_free(m->replyto822);	s_free(m->date822);	s_free(m->inreplyto822);	s_free(m->subject822);	s_free(m->messageid822);	s_free(m->addrs);	s_free(m->mimeversion);	s_free(m->sdigest);	s_free(m->boundary);	s_free(m->type);	s_free(m->charset);	s_free(m->filename);	free(m);}// mark messages (identified by path) for deletionvoiddelmessages(int ac, char **av){	Mailbox *mb;	Message *m;	int i, needwrite;	qlock(&mbllock);	for(mb = mbl; mb != nil; mb = mb->next)		if(strcmp(av[0], mb->name) == 0){			qlock(mb);			break;		}	qunlock(&mbllock);	if(mb == nil)		return;	needwrite = 0;	for(i = 1; i < ac; i++){		for(m = mb->root->part; m != nil; m = m->next)			if(strcmp(m->name, av[i]) == 0){				if(!m->deleted){					mailplumb(mb, m, 1);					needwrite = 1;					m->deleted = 1;					logmsg("deleting", m);				}				break;			}	}	if(needwrite)		syncmbox(mb, 1);	qunlock(mb);}/* *  the following are called with the mailbox qlocked */voidmsgincref(Message *m){	m->refs++;}voidmsgdecref(Mailbox *mb, Message *m){	m->refs--;	if(m->refs == 0 && m->deleted)		syncmbox(mb, 1);}/* *  the following are called with mbllock'd */voidmboxincref(Mailbox *mb){	assert(mb->refs > 0);	mb->refs++;}voidmboxdecref(Mailbox *mb){	assert(mb->refs > 0);	qlock(mb);	mb->refs--;	if(mb->refs == 0){		delmessage(mb, mb->root);		if(mb->ctl)			hfree(PATH(mb->id, Qmbox), "ctl");		if(mb->close)			(*mb->close)(mb);		free(mb);	} else		qunlock(mb);}intcistrncmp(char *a, char *b, int n){	while(n-- > 0){		if(tolower(*a++) != tolower(*b++))			return -1;	}	return 0;}intcistrcmp(char *a, char *b){	for(;;){		if(tolower(*a) != tolower(*b++))			return -1;		if(*a++ == 0)			break;	}	return 0;}static char*skipwhite(char *p){	while(isspace(*p))		p++;	return p;}static char*skiptosemi(char *p){	while(*p && *p != ';')		p++;	while(*p == ';' || isspace(*p))		p++;	return p;}static char*getstring(char *p, String *s, int dolower){	s = s_reset(s);	p = skipwhite(p);	if(*p == '"'){		p++;		for(;*p && *p != '"'; p++)			if(dolower)				s_putc(s, tolower(*p));			else				s_putc(s, *p);		if(*p == '"')			p++;		s_terminate(s);		return p;	}	for(; *p && !isspace(*p) && *p != ';'; p++)		if(dolower)			s_putc(s, tolower(*p));		else			s_putc(s, *p);	s_terminate(s);	return p;}static voidsetfilename(Message *m, char *p){	m->filename = s_reset(m->filename);	getstring(p, m->filename, 0);	for(p = s_to_c(m->filename); *p; p++)		if(*p == ' ' || *p == '\t' || *p == ';')			*p = '_';}//// undecode message body//voiddecode(Message *m){	int i, len;	char *x;	if(m->decoded)		return;	switch(m->encoding){	case Ebase64:		len = m->bend - m->body;		i = (len*3)/4+1;	// room for max chars + null		x = emalloc(i);		len = dec64((uchar*)x, i, m->body, len);		if(m->ballocd)			free(m->body);		m->body = x;		m->bend = x + len;		m->ballocd = 1;		break;	case Equoted:		len = m->bend - m->body;		x = emalloc(len+2);	// room for null and possible extra nl		len = decquoted(x, m->body, m->bend, 0);		if(m->ballocd)			free(m->body);		m->body = x;		m->bend = x + len;		m->ballocd = 1;		break;	default:		break;	}	m->decoded = 1;}// convert latin1 to utfvoidconvert(Message *m){	int len;	char *x;	// don't convert if we're not a leaf, not text, or already converted	if(m->converted)		return;	if(m->part != nil)		return;	if(cistrncmp(s_to_c(m->type), "text", 4) != 0)		return;	len = xtoutf(s_to_c(m->charset), &x, m->body, m->bend);	if(len > 0){		if(m->ballocd)			free(m->body);		m->body = x;		m->bend = x + len;		m->ballocd = 1;	}	m->converted = 1;}static inthex2int(int x){	if(x >= '0' && x <= '9')		return x - '0';	if(x >= 'A' && x <= 'F')		return (x - 'A') + 10;	if(x >= 'a' && x <= 'f')		return (x - 'a') + 10;	return 0;}// underscores are translated in 2047 headers (uscores=1) // but not in the body (uscores=0)static char*decquotedline(char *out, char *in, char *e, int uscores){	int c, soft;	/* dump trailing white space */	while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n'))		e--;	/* trailing '=' means no newline */	if(*e == '='){		soft = 1;		e--;	} else		soft = 0;	while(in <= e){		c = (*in++) & 0xff;		switch(c){		case '_':			if(uscores){				*out++ = ' ';				break;			}		default:			*out++ = c;			break;		case '=':			c = hex2int(*in++)<<4;			c |= hex2int(*in++);			*out++ = c;			break;		}	}	if(!soft)		*out++ = '\n';	*out = 0;	return out;}intdecquoted(char *out, char *in, char *e, int uscores){	char *p, *nl;	p = out;	while((nl = strchr(in, '\n')) != nil && nl < e){		p = decquotedline(p, in, nl, uscores);		in = nl + 1;	}	if(in < e)		p = decquotedline(p, in, e-1, uscores);	// make sure we end with a new line	if(*(p-1) != '\n'){		*p++ = '\n';		*p = 0;	}	return p - out;}static char*lowercase(char *p){	char *op;	int c;	for(op = p; c = *p; p++)		if(isupper(c))			*p = tolower(c);	return op;}// translate latin1 directly since it fits neatly in utfstatic intlatin1toutf(char **out, char *in, char *e){	int n;	char *p;	Rune r;	n = 0;	for(p = in; p < e; p++)		if(*p & 0x80)			n++;	if(n == 0)		return 0;	n += e-in;	*out = p = malloc(n+1);	if(p == nil)		return 0;	for(; in < e; in++){		r = (uchar)*in;		p += runetochar(p, &r);	}	*p = 0;	return p - *out;}// translate any thing using the tcs programintxtoutf(char *charset, char **out, char *in, char *e){	char *av[4];	int totcs[2];	int fromtcs[2];	int n, len, sofar;	char *p;	// might not need to convert	if(cistrcmp(charset, "us-ascii") == 0 || cistrcmp(charset, "utf-8") == 0)		return 0;	if(cistrcmp(charset, "iso-8859-1") == 0)		return latin1toutf(out, in, e);	len = e-in+1;	sofar = 0;	*out = p = malloc(len+1);	if(p == nil)		return 0;	av[0] = charset;	av[1] = "-f";	av[2] = charset;	av[3] = 0;	if(pipe(totcs) < 0)		goto error;	if(pipe(fromtcs) < 0){		close(totcs[0]); close(totcs[1]);		goto error;	}	switch(rfork(RFPROC|RFFDG|RFNOWAIT)){	case -1:		close(fromtcs[0]); close(fromtcs[1]);		close(totcs[0]); close(totcs[1]);		goto error;	case 0:		close(fromtcs[0]); close(totcs[1]);		dup(fromtcs[1], 1);		dup(totcs[0], 0);		close(fromtcs[1]); close(totcs[0]);		dup(open("/dev/null", OWRITE), 2);		exec("/bin/tcs", av);		_exits(0);	default:		close(fromtcs[1]); close(totcs[0]);		switch(rfork(RFPROC|RFFDG|RFNOWAIT)){		case -1:			close(fromtcs[0]); close(totcs[1]);			goto error;		case 0:			close(fromtcs[0]);			while(in < e){				n = write(totcs[1], in, e-in);				if(n <= 0)					break;				in += n;			}			close(totcs[1]);			_exits(0);		default:			close(totcs[1]);			for(;;){				n = read(fromtcs[0], &p[sofar], len-sofar);				if(n <= 0)					break;				sofar += n;				p[sofar] = 0;				if(sofar == len){					len += 1024;					p = realloc(p, len+1);					if(p == nil)						goto error;					*out = p;				}			}			close(fromtcs[0]);			break;		}		break;	}	if(sofar == 0)		goto error;	return sofar;error:	free(*out);	*out = nil;	return 0;}void *emalloc(ulong n){	void *p;	p = mallocz(n, 1);	if(!p){		fprint(2, "%s: out of memory alloc %lud\n", argv0, n);		exits("out of memory");	}	setmalloctag(p, getcallerpc(&n));	return p;}void *erealloc(void *p, ulong n){	if(n == 0)		n = 1;	p = realloc(p, n);	if(!p){		fprint(2, "%s: out of memory realloc %lud\n", argv0, n);		exits("out of memory");	}	setrealloctag(p, getcallerpc(&p));	return p;}voidmailplumb(Mailbox *mb, Message *m, int delete){	Plumbmsg p;	Plumbattr a[7];	char buf[256];	int ai;	char lenstr[10], *from, *subject, *date;	static int fd = -1;	if(m->subject822 == nil)		subject = "";	else		subject = s_to_c(m->subject822);	if(m->from822 != nil)		from = s_to_c(m->from822);	else if(m->unixfrom != nil)		from = s_to_c(m->unixfrom);	else		from = "";	if(m->unixdate != nil)		date = s_to_c(m->unixdate);	else		date = "";	sprint(lenstr, "%ld", m->end-m->start);	if(biffing && !delete)		print("[ %s / %s / %s ]\n", from, subject, lenstr);	if(!plumbing)		return;	if(fd < 0)		fd = plumbopen("send", OWRITE);	if(fd < 0)		return;	p.src = "mailfs";	p.dst = "seemail";	p.wdir = "/mail/fs";	p.type = "text";	ai = 0;	a[ai].name = "filetype";	a[ai].value = "mail";	a[++ai].name = "sender";	a[ai].value = from;	a[ai-1].next = &a[ai];	a[++ai].name = "length";	a[ai].value = lenstr;	a[ai-1].next = &a[ai];	a[++ai].name = "mailtype";	a[ai].value = delete?"delete":"new";	a[ai-1].next = &a[ai];	a[++ai].name = "date";	a[ai].value = date;	a[ai-1].next = &a[ai];	if(m->sdigest){		a[++ai].name = "digest";		a[ai].value = s_to_c(m->sdigest);		a[ai-1].next = &a[ai];	}	a[ai].next = nil;	p.attr = a;	snprint(buf, sizeof(buf), "%s/%s/%s",		mntpt, mb->name, m->name);	p.ndata = strlen(buf);	p.data = buf;	plumbsend(fd, &p);}//// count the number of lines in the body (for imap4)//voidcountlines(Message *m){	int i;	char *p;	i = 0;	for(p = strchr(m->rbody, '\n'); p != nil && p < m->rbend; p = strchr(p+1, '\n'))		i++;	sprint(m->lines, "%d", i);}char *LOG = "fs";voidlogmsg(char *s, Message *m){	int pid;	if(!logging)		return;	pid = getpid();	if(m == nil)		syslog(0, LOG, "%s.%d: %s", user, pid, s);	else		syslog(0, LOG, "%s.%d: %s msg from %s digest %s",			user, pid, s,			m->from822 ? s_to_c(m->from822) : "?",			s_to_c(m->sdigest));}/* *  squeeze nulls out of the body */static voidnullsqueeze(Message *m){	char *p, *q;	q = memchr(m->body, 0, m->end-m->body);	if(q == nil)		return;	for(p = m->body; q < m->end; q++){		if(*q == 0)			continue;		*p++ = *q;	}	m->bend = m->rbend = m->end = p;}//// convert an RFC822 date into a Unix style date// for when the Unix From line isn't there (e.g. POP3).// enough client programs depend on having a Unix date// that it's easiest to write this conversion code once, right here.//// people don't follow RFC822 particularly closely,// so we use strtotm, which is a bunch of heuristics.//extern int strtotm(char*, Tm*);String*date822tounix(char *s){	char *p, *q;	Tm tm;	if(strtotm(s, &tm) < 0)		return nil;	p = asctime(&tm);	if(q = strchr(p, '\n'))		*q = '\0';	return s_copy(p);}

⌨️ 快捷键说明

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