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

📄 plan9.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "common.h"#include <ctype.h>#include <plumb.h>#include <libsec.h>#include "dat.h"enum {	Buffersize = 64*1024,};typedef struct Inbuf Inbuf;struct Inbuf{	int	fd;	uchar	*lim;	uchar	*rptr;	uchar	*wptr;	uchar	data[Buffersize+7];};static voidaddtomessage(Message *m, uchar *p, int n, int done){	int i, len;	// add to message (+ 1 in malloc is for a trailing null)	if(m->lim - m->end < n){		if(m->start != nil){			i = m->end-m->start;			if(done)				len = i + n;			else				len = (4*(i+n))/3;			m->start = erealloc(m->start, len + 1);			m->end = m->start + i;		} else {			if(done)				len = n;			else				len = 2*n;			m->start = emalloc(len + 1);			m->end = m->start;		}		m->lim = m->start + len;	}	memmove(m->end, p, n);	m->end += n;}////  read in a single message//static intreadmessage(Message *m, Inbuf *inb){	int i, n, done;	uchar *p, *np;	char sdigest[SHA1dlen*2+1];	char tmp[64];	for(done = 0; !done;){		n = inb->wptr - inb->rptr;		if(n < 6){			if(n)				memmove(inb->data, inb->rptr, n);			inb->rptr = inb->data;			inb->wptr = inb->rptr + n;			i = read(inb->fd, inb->wptr, Buffersize);			if(i < 0){				if(fd2path(inb->fd, tmp, sizeof tmp) < 0)					strcpy(tmp, "unknown mailbox");				fprint(2, "error reading '%s': %r\n", tmp);				return -1;			}			if(i == 0){				if(n != 0)					addtomessage(m, inb->rptr, n, 1);				if(m->end == m->start)					return -1;				break;			}			inb->wptr += i;		}		// look for end of message		for(p = inb->rptr; p < inb->wptr; p = np+1){			// first part of search for '\nFrom '			np = memchr(p, '\n', inb->wptr - p);			if(np == nil){				p = inb->wptr;				break;			}			/*			 *  if we've found a \n but there's			 *  not enough room for '\nFrom ', don't do			 *  the comparison till we've read in more.			 */			if(inb->wptr - np < 6){				p = np;				break;			}			if(strncmp((char*)np, "\nFrom ", 6) == 0){				done = 1;				p = np+1;				break;			}		}		// add to message (+ 1 in malloc is for a trailing null)		n = p - inb->rptr;		addtomessage(m, inb->rptr, n, done);		inb->rptr += n;	}	// if it doesn't start with a 'From ', this ain't a mailbox	if(strncmp(m->start, "From ", 5) != 0)		return -1;	// dump trailing newline, make sure there's a trailing null	// (helps in body searches)	if(*(m->end-1) == '\n')		m->end--;	*m->end = 0;	m->bend = m->rbend = m->end;	// digest message	sha1((uchar*)m->start, m->end - m->start, m->digest, nil);	for(i = 0; i < SHA1dlen; i++)		sprint(sdigest+2*i, "%2.2ux", m->digest[i]);	m->sdigest = s_copy(sdigest);	return 0;}// throw out deleted messages.  return number of freshly deleted messagesintpurgedeleted(Mailbox *mb){	Message *m, *next;	int newdels;	// forget about what's no longer in the mailbox	newdels = 0;	for(m = mb->root->part; m != nil; m = next){		next = m->next;		if(m->deleted && m->refs == 0){			if(m->inmbox)				newdels++;			delmessage(mb, m);		}	}	return newdels;}////  read in the mailbox and parse into messages.//static char*_readmbox(Mailbox *mb, int doplumb, Mlock *lk){	int fd;	String *tmp;	Dir *d;	static char err[128];	Message *m, **l;	Inbuf *inb;	char *x;	l = &mb->root->part;	/*	 *  open the mailbox.  If it doesn't exist, try the temporary one.	 */retry:	fd = open(mb->path, OREAD);	if(fd < 0){		errstr(err, sizeof(err));		if(strstr(err, "exist") != 0){			tmp = s_copy(mb->path);			s_append(tmp, ".tmp");			if(sysrename(s_to_c(tmp), mb->path) == 0){				s_free(tmp);				goto retry;			}			s_free(tmp);		}		return err;	}	/*	 *  a new qid.path means reread the mailbox, while	 *  a new qid.vers means read any new messages	 */	d = dirfstat(fd);	if(d == nil){		close(fd);		errstr(err, sizeof(err));		return err;	}	if(mb->d != nil){		if(d->qid.path == mb->d->qid.path && d->qid.vers == mb->d->qid.vers){			close(fd);			free(d);			return nil;		}		if(d->qid.path == mb->d->qid.path){			while(*l != nil)				l = &(*l)->next;			seek(fd, mb->d->length, 0);		}		free(mb->d);	}	mb->d = d;	mb->vers++;	henter(PATH(0, Qtop), mb->name,		(Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);	inb = emalloc(sizeof(Inbuf));	inb->rptr = inb->wptr = inb->data;	inb->fd = fd;	//  read new messages	snprint(err, sizeof err, "reading '%s'", mb->path);	logmsg(err, nil);	for(;;){		if(lk != nil)			syslockrefresh(lk);		m = newmessage(mb->root);		m->mallocd = 1;		m->inmbox = 1;		if(readmessage(m, inb) < 0){			delmessage(mb, m);			mb->root->subname--;			break;		}		// merge mailbox versions		while(*l != nil){			if(memcmp((*l)->digest, m->digest, SHA1dlen) == 0){				// matches mail we already read, discard				logmsg("duplicate", *l);				delmessage(mb, m);				mb->root->subname--;				m = nil;				l = &(*l)->next;				break;			} else {				// old mail no longer in box, mark deleted				logmsg("disappeared", *l);				if(doplumb)					mailplumb(mb, *l, 1);				(*l)->inmbox = 0;				(*l)->deleted = 1;				l = &(*l)->next;			}		}		if(m == nil)			continue;		x = strchr(m->start, '\n');		if(x == nil)			m->header = m->end;		else			m->header = x + 1;		m->mheader = m->mhend = m->header;		parseunix(m);		parse(m, 0, mb, 0);		logmsg("new", m);		/* chain in */		*l = m;		l = &m->next;		if(doplumb)			mailplumb(mb, m, 0);	}	logmsg("mbox read", nil);	// whatever is left has been removed from the mbox, mark deleted	while(*l != nil){		if(doplumb)			mailplumb(mb, *l, 1);		(*l)->inmbox = 0;		(*l)->deleted = 1;		l = &(*l)->next;	}	close(fd);	free(inb);	return nil;}static void_writembox(Mailbox *mb, Mlock *lk){	Dir *d;	Message *m;	String *tmp;	int mode, errs;	Biobuf *b;	tmp = s_copy(mb->path);	s_append(tmp, ".tmp");	/*	 * preserve old files permissions, if possible	 */	d = dirstat(mb->path);	if(d != nil){		mode = d->mode&0777;		free(d);	} else		mode = MBOXMODE;	sysremove(s_to_c(tmp));	b = sysopen(s_to_c(tmp), "alc", mode);	if(b == 0){		fprint(2, "can't write temporary mailbox %s: %r\n", s_to_c(tmp));		return;	}	logmsg("writing new mbox", nil);	errs = 0;	for(m = mb->root->part; m != nil; m = m->next){		if(lk != nil)			syslockrefresh(lk);		if(m->deleted)			continue;		logmsg("writing", m);		if(Bwrite(b, m->start, m->end - m->start) < 0)			errs = 1;		if(Bwrite(b, "\n", 1) < 0)			errs = 1;	}	logmsg("wrote new mbox", nil);	if(sysclose(b) < 0)		errs = 1;	if(errs){		fprint(2, "error writing temporary mail file\n");		s_free(tmp);		return;	}	sysremove(mb->path);	if(sysrename(s_to_c(tmp), mb->path) < 0)		fprint(2, "%s: can't rename %s to %s: %r\n", argv0,			s_to_c(tmp), mb->path);	s_free(tmp);	if(mb->d != nil)		free(mb->d);	mb->d = dirstat(mb->path);}char*plan9syncmbox(Mailbox *mb, int doplumb){	Mlock *lk;	char *rv;	lk = nil;	if(mb->dolock){		lk = syslock(mb->path);		if(lk == nil)			return "can't lock mailbox";	}	rv = _readmbox(mb, doplumb, lk);		/* interpolate */	if(purgedeleted(mb) > 0)		_writembox(mb, lk);	if(lk != nil)		sysunlock(lk);	return rv;}////  look to see if we can open this mail box//char*plan9mbox(Mailbox *mb, char *path){	static char err[64];	String *tmp;	if(access(path, AEXIST) < 0){		errstr(err, sizeof(err));		tmp = s_copy(path);		s_append(tmp, ".tmp");		if(access(s_to_c(tmp), AEXIST) < 0){			s_free(tmp);			return err;		}		s_free(tmp);	}	mb->sync = plan9syncmbox;	return nil;}

⌨️ 快捷键说明

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