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

📄 marshal.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
			fatal("input error");		if(n == 0)			break;		m = enc64(obuf, sizeof(obuf), buf, n);		if(Bwrite(out, obuf, m) < 0)			fatal("output error");	}	lastchar = '\n';}// pass message to sendmail, make sure body starts with a newlinevoidcopy(Biobuf *in, Biobuf *out){	char buf[4*1024];	int n;	for(;;){		n = Bread(in, buf, sizeof(buf));		if(n < 0)			fatal("input error");		if(n == 0)			break;		if(Bwrite(out, buf, n) < 0)			fatal("output error");	}}voidattachment(Attach *a, Biobuf *out){	Biobuf *f;	char *p;	// if it's already mime encoded, just copy	if(strcmp(a->type, "mime") == 0){		f = Bopen(a->path, OREAD);		if(f == nil){			/* hack: give marshal time to stdin, before we kill it (for dead.letter) */			sleep(500);			postnote(PNPROC, pid, "interrupt");			sysfatal("opening %s: %r", a->path);		}		copy(f, out);		Bterm(f);	}		// if it's not already mime encoded ...	if(strcmp(a->type, "text/plain") != 0)		Bprint(out, "Content-Type: %s\n", a->type);	if(a->ainline){		Bprint(out, "Content-Disposition: inline\n");	} else {		p = strrchr(a->path, '/');		if(p == nil)			p = a->path;		else			p++;		Bprint(out, "Content-Disposition: attachment; filename=%Z\n", p);	}	f = Bopen(a->path, OREAD);	if(f == nil){		/* hack: give marshal time to stdin, before we kill it (for dead.letter) */		sleep(500);		postnote(PNPROC, pid, "interrupt");		sysfatal("opening %s: %r", a->path);	}	/* dump our local 'From ' line when passing along mail messages */	if(strcmp(a->type, "message/rfc822") == 0){		p = Brdline(f, '\n');		if(strncmp(p, "From ", 5) != 0)			Bseek(f, 0, 0);	}	if(a->ctype->display){		body(f, out, strcmp(a->type, "text/plain") == 0);	} else {		Bprint(out, "Content-Transfer-Encoding: base64\n");		body64(f, out);	}	Bterm(f);}char *ascwday[] ={	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};char *ascmon[] ={	"Jan", "Feb", "Mar", "Apr", "May", "Jun",	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};intprintdate(Biobuf *b){	Tm *tm;	int tz;	tm = localtime(time(0));	tz = (tm->tzoff/3600)*100 + ((tm->tzoff/60)%60);	return Bprint(b, "Date: %s, %d %s %d %2.2d:%2.2d:%2.2d %s%.4d\n",		ascwday[tm->wday], tm->mday, ascmon[tm->mon], 1900+tm->year,		tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz);}intprintfrom(Biobuf *b){	return Bprint(b, "From: %s\n", user);}intprintto(Biobuf *b, Addr *a){	int i;	if(Bprint(b, "To: %s", a->v) < 0)		return -1;	i = 0;	for(a = a->next; a != nil; a = a->next)		if(Bprint(b, "%s%s", ((i++ & 7) == 7)?",\n\t":", ", a->v) < 0)			return -1;	if(Bprint(b, "\n") < 0)		return -1;	return 0;}intprintcc(Biobuf *b, Addr *a){	int i;	if(a == nil)		return 0;	if(Bprint(b, "CC: %s", a->v) < 0)		return -1;	i = 0;	for(a = a->next; a != nil; a = a->next)		if(Bprint(b, "%s%s", ((i++ & 7) == 7)?",\n\t":", ", a->v) < 0)			return -1;	if(Bprint(b, "\n") < 0)		return -1;	return 0;}intprintsubject(Biobuf *b, char *subject){	return Bprint(b, "Subject: %U\n", subject);}intprintinreplyto(Biobuf *out, char *dir){	String *s = s_copy(dir);	char buf[256];	int fd;	int n;	s_append(s, "/messageid");	fd = open(s_to_c(s), OREAD);	s_free(s);	if(fd < 0)		return 0;	n = read(fd, buf, sizeof(buf)-1);	close(fd);	if(n <= 0)		return 0;	buf[n] = 0;	return Bprint(out, "In-Reply-To: %s\n", buf);}Attach*mkattach(char *file, char *type, int ainline){	Ctype *c;	Attach *a;	char ftype[64];	char *p;	int n, pfd[2];	if(file == nil)		return nil;	if(access(file, 4) == -1){		fprint(2, "%s: %s can't read file\n", argv0, file);		return nil;	}	a = emalloc(sizeof(*a));	a->path = file;	a->next = nil;	a->type = type;	a->ainline = ainline;	a->ctype = nil;	if(type != nil){		for(c = ctype; ; c++)			if(strncmp(type, c->type, strlen(c->type)) == 0){				a->ctype = c;				break;			}		return a;	}	// pick a type depending on extension	p = strchr(file, '.');	if(p != nil)		p++;	// check the builtin extensions	if(p != nil){		for(c = ctype; c->ext != nil; c++)			if(strcmp(p, c->ext) == 0){				a->type = c->type;				a->ctype = c;				return a;			}	}	// try the mime types file	if(p != nil){		if(mimetypes == nil)			readmimetypes();		for(c = mimetypes; c != nil && c->ext != nil; c++)			if(strcmp(p, c->ext) == 0){				a->type = c->type;				a->ctype = c;				return a;			}	}	// run file to figure out the type	a->type = "application/octet-stream";		// safest default	if(pipe(pfd) < 0)		return a;	switch(fork()){	case -1:		break;	case 0:		close(pfd[1]);		close(0);		dup(pfd[0], 0);		close(1);		dup(pfd[0], 1);		execl("/bin/file", "file", "-m", file, nil);		exits(0);	default:		close(pfd[0]);		n = read(pfd[1], ftype, sizeof(ftype));		if(n > 0){			ftype[n-1] = 0;			a->type = estrdup(ftype);		}		close(pfd[1]);		waitpid();		break;	}	for(c = ctype; ; c++)		if(strncmp(a->type, c->type, strlen(c->type)) == 0){			a->ctype = c;			break;		}	return a;}char*mkboundary(void){	char buf[32];	int i;	srand((time(0)<<16)|getpid());	strcpy(buf, "upas-");	for(i = 5; i < sizeof(buf)-1; i++)		buf[i] = 'a' + nrand(26);	buf[i] = 0;	return estrdup(buf);}// copy types to two fd'sstatic voidtee(int in, int out1, int out2){	char buf[8*1024];	int n;	for(;;){		n = read(in, buf, sizeof(buf));		if(n <= 0)			break;		if(write(out1, buf, n) < 0)			break;		if(write(out2, buf, n) < 0)			break;	}}// print the unix from lineintprintunixfrom(int fd){	Tm *tm;	int tz;	tm = localtime(time(0));	tz = (tm->tzoff/3600)*100 + ((tm->tzoff/60)%60);	return fprint(fd, "From %s %s %s %d %2.2d:%2.2d:%2.2d %s%.4d %d\n",		user,		ascwday[tm->wday], ascmon[tm->mon], tm->mday,		tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz, 1900+tm->year);}char *specialfile[] ={	"pipeto",	"pipefrom",	"L.mbox",	"forward",	"names"};// return 1 if this is a special filestatic intspecial(String *s){	char *p;	int i;	p = strrchr(s_to_c(s), '/');	if(p == nil)		p = s_to_c(s);	else		p++;	for(i = 0; i < nelem(specialfile); i++)		if(strcmp(p, specialfile[i]) == 0)			return 1;	return 0;}// open the folder using the recipients account namestatic intopenfolder(char *rcvr){	char *p;	int c;	String *file;	Dir *d;	int fd;	int scarey;	file = s_new();	mboxpath("f", user, file, 0);	// if $mail/f exists, store there, otherwise in $mail	d = dirstat(s_to_c(file));	if(d == nil || d->qid.type != QTDIR){		scarey = 1;		file->ptr -= 1;	} else {		s_putc(file, '/');		scarey = 0;	}	free(d);	p = strrchr(rcvr, '!');	if(p != nil)		rcvr = p+1;	while(*rcvr && *rcvr != '@'){		c = *rcvr++;		if(c == '/')			c = '_';		s_putc(file, c);	}	s_terminate(file);	if(scarey && special(file)){		fprint(2, "%s: won't overwrite %s\n", argv0, s_to_c(file));		s_free(file);		return -1;	}	fd = open(s_to_c(file), OWRITE);	if(fd < 0)		fd = create(s_to_c(file), OWRITE, 0660);	s_free(file);	return fd;}// start up sendmail and return an fd to talk to it withintsendmail(Addr *to, Addr *cc, int *pid, char *rcvr){	char **av, **v;	int ac, fd;	int pfd[2];	String *cmd;	Addr *a;	fd = -1;	if(rcvr != nil)		fd = openfolder(rcvr);	ac = 0;	for(a = to; a != nil; a = a->next)		ac++;	for(a = cc; a != nil; a = a->next)		ac++;	v = av = emalloc(sizeof(char*)*(ac+20));	ac = 0;	v[ac++] = "sendmail";	if(xflag)		v[ac++] = "-x";	if(rflag)		v[ac++] = "-r";	if(lbflag)		v[ac++] = "-#";	if(dflag)		v[ac++] = "-d";	for(a = to; a != nil; a = a->next)		v[ac++] = a->v;	for(a = cc; a != nil; a = a->next)		v[ac++] = a->v;	v[ac] = 0;	if(pipe(pfd) < 0)		fatal("%r");	switch(*pid = rfork(RFFDG|RFREND|RFPROC|RFENVG)){	case -1:		fatal("%r");		break;	case 0:		if(holding)			close(holding);		close(pfd[1]);		dup(pfd[0], 0);		close(pfd[0]);		if(rcvr != nil){			if(pipe(pfd) < 0)				fatal("%r");			switch(fork()){			case -1:				fatal("%r");				break;			case 0:				close(pfd[0]);				seek(fd, 0, 2);				printunixfrom(fd);				tee(0, pfd[1], fd);				write(fd, "\n", 1);				exits(0);			default:				close(fd);				close(pfd[1]);				dup(pfd[0], 0);				break;			}		}		if(replymsg != nil)			putenv("replymsg", replymsg);		cmd = mboxpath("pipefrom", login, s_new(), 0);		exec(s_to_c(cmd), av);		exec("/bin/myupassend", av);		exec("/bin/upas/send", av);		fatal("execing: %r");		break;	default:		if(rcvr != nil)			close(fd);		close(pfd[0]);		break;	}	return pfd[1];}// start up pgp process and return an fd to talk to it with.// its standard output will be the original fd, which goes to sendmail.intpgpfilter(int *pid, int fd, int pgpflag){	char **av, **v;	int ac;	int pfd[2];	v = av = emalloc(sizeof(char*)*8);	ac = 0;	v[ac++] = "pgp";	v[ac++] = "-fat";		/* operate as a filter, generate text */	if(pgpflag & PGPsign)		v[ac++] = "-s";	if(pgpflag & PGPencrypt)		v[ac++] = "-e";	v[ac] = 0;	if(pipe(pfd) < 0)		fatal("%r");	switch(*pid = fork()){	case -1:		fatal("%r");		break;	case 0:		close(pfd[1]);		dup(pfd[0], 0);		close(pfd[0]);		dup(fd, 1);		close(fd);		/* add newline to avoid confusing pgp output with 822 headers */		write(1, "\n", 1);		exec("/bin/pgp", av);		fatal("execing: %r");		break;	default:		close(pfd[0]);		break;	}	close(fd);	return pfd[1];}// wait for sendmail and pgp to exit; exit here if either failedchar*waitforsubprocs(void){	Waitmsg *w;	char *err;	err = nil;	while((w = wait()) != nil){		if(w->pid == pid || w->pid == pgppid){			if(w->msg[0] != 0)				err = estrdup(w->msg);		}		free(w);	}	if(err)		exits(err);	return nil;}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 uchar t64d[256];static char t64e[64];static voidinit64(void){	int c, i;	memset(t64d, 255, 256);	memset(t64e, '=', 64);	i = 0;	for(c = 'A'; c <= 'Z'; c++){		t64e[i] = c;		t64d[c] = i++;	}	for(c = 'a'; c <= 'z'; c++){		t64e[i] = c;		t64d[c] = i++;	}	for(c = '0'; c <= '9'; c++){		t64e[i] = c;		t64d[c] = i++;	}	t64e[i] = '+';	t64d['+'] = i++;	t64e[i] = '/';	t64d['/'] = i;}intenc64(char *out, int lim, uchar *in, int n){	int i;	ulong b24;	char *start = out;	char *e = out + lim;	if(t64e[0] == 0)		init64();	for(i = 0; i < n/3; i++){		b24 = (*in++)<<16;		b24 |= (*in++)<<8;		b24 |= *in++;		if(out + 5 >= e)			goto exhausted;		*out++ = t64e[(b24>>18)];		*out++ = t64e[(b24>>12)&0x3f];		*out++ = t64e[(b24>>6)&0x3f];		*out++ = t64e[(b24)&0x3f];		if((i%18) == 17)			*out++ = '\n';	}	switch(n%3){	case 2:		b24 = (*in++)<<16;		b24 |= (*in)<<8;		if(out + 4 >= e)			goto exhausted;		*out++ = t64e[(b24>>18)];		*out++ = t64e[(b24>>12)&0x3f];		*out++ = t64e[(b24>>6)&0x3f];		break;	case 1:		b24 = (*in)<<16;

⌨️ 快捷键说明

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