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

📄 smtp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		return Giveup;	default:		return Retry;	}	return 0;}static char hex[] = "0123456789abcdef";/* *  send the damn thing */char *data(String *from, Biobuf *b){	char *buf, *cp;	int i, n, nbytes, bufsize, eof, r;	String *fromline;	char errmsg[Errlen];	char id[40];	/*	 *  input the header.	 */	buf = malloc(1);	if(buf == 0){		s_append(s_restart(reply), "out of memory");		return Retry;	}	n = 0;	eof = 0;	for(;;){		cp = Brdline(b, '\n');		if(cp == nil){			eof = 1;			break;		}		nbytes = Blinelen(b);		buf = realloc(buf, n+nbytes+1);		if(buf == 0){			s_append(s_restart(reply), "out of memory");			return Retry;		}		strncpy(buf+n, cp, nbytes);		n += nbytes;		if(nbytes == 1)		/* end of header */			break;	}	buf[n] = 0;	bufsize = n;	/*	 *  parse the header, turn all addresses into @ format	 */	yyinit(buf, n);	yyparse();	/*	 *  print message observing '.' escapes and using \r\n for \n	 */	alarm(20*alarmscale);	if(!filter){		dBprint("DATA\r\n");		switch(getreply()){		case 3:			break;		case 5:			free(buf);			return Giveup;		default:			free(buf);			return Retry;		}	}	/*	 *  send header.  add a message-id, a sender, and a date if there	 *  isn't one	 */	nbytes = 0;	fromline = convertheader(from);	uneaten = buf;	srand(truerand());	if(messageid == 0){		for(i=0; i<16; i++){			r = rand()&0xFF;			id[2*i] = hex[r&0xF];			id[2*i+1] = hex[(r>>4)&0xF];		}		id[2*i] = '\0';		nbytes += Bprint(&bout, "Message-ID: <%s@%s>\r\n", id, hostdomain);		if(debug)			Bprint(&berr, "Message-ID: <%s@%s>\r\n", id, hostdomain);	}		if(originator==0){		nbytes += Bprint(&bout, "From: %s\r\n", s_to_c(fromline));		if(debug)			Bprint(&berr, "From: %s\r\n", s_to_c(fromline));	}	s_free(fromline);	if(destination == 0 && toline)		if(*s_to_c(toline) == '@'){	/* route addr */			nbytes += Bprint(&bout, "To: <%s>\r\n", s_to_c(toline));			if(debug)				Bprint(&berr, "To: <%s>\r\n", s_to_c(toline));		} else {			nbytes += Bprint(&bout, "To: %s\r\n", s_to_c(toline));			if(debug)				Bprint(&berr, "To: %s\r\n", s_to_c(toline));		}	if(date==0 && udate)		nbytes += printdate(udate);	if (usys)		uneaten = usys->end + 1;	nbytes += printheader();	if (*uneaten != '\n')		putcrnl("\n", 1);	/*	 *  send body	 */			putcrnl(uneaten, buf+n - uneaten);	nbytes += buf+n - uneaten;	if(eof == 0){		for(;;){			n = Bread(b, buf, bufsize);			if(n < 0){				rerrstr(errmsg, sizeof(errmsg));				s_append(s_restart(reply), errmsg);				free(buf);				return Retry;			}			if(n == 0)				break;			alarm(10*alarmscale);			putcrnl(buf, n);			nbytes += n;		}	}	free(buf);	if(!filter){		if(last != '\n')			dBprint("\r\n.\r\n");		else			dBprint(".\r\n");		alarm(10*alarmscale);		switch(getreply()){		case 2:			break;		case 5:			return Giveup;		default:			return Retry;		}		syslog(0, "smtp", "%s sent %d bytes to %s", s_to_c(from),				nbytes, s_to_c(toline));/**/	}	return 0;}/* *  we're leaving */voidquit(char *rv){		/* 60 minutes to quit */	quitting = 1;	quitrv = rv;	alarm(60*alarmscale);	dBprint("QUIT\r\n");	getreply();	Bterm(&bout);	Bterm(&bfile);}/* *  read a reply into a string, return the reply code */intgetreply(void){	char *line;	int rv;	reply = s_reset(reply);	for(;;){		line = getcrnl(reply);		if(debug)			Bflush(&berr);		if(line == 0)			return -1;		if(!isdigit(line[0]) || !isdigit(line[1]) || !isdigit(line[2]))			return -1;		if(line[3] != '-')			break;	}	if(debug)		Bflush(&berr);	rv = atoi(line)/100;	return rv;}voidaddhostdom(String *buf, char *host){	s_append(buf, "@");	s_append(buf, host);}/* *	Convert from `bang' to `source routing' format. * *	   a.x.y!b.p.o!c!d ->	@a.x.y:c!d@b.p.o */String *bangtoat(char *addr){	String *buf;	register int i;	int j, d;	char *field[128];	/* parse the '!' format address */	buf = s_new();	for(i = 0; addr; i++){		field[i] = addr;		addr = strchr(addr, '!');		if(addr)			*addr++ = 0;	}	if (i==1) {		s_append(buf, field[0]);		return buf;	}	/*	 *  count leading domain fields (non-domains don't count)	 */	for(d = 0; d<i-1; d++)		if(strchr(field[d], '.')==0)			break;	/*	 *  if there are more than 1 leading domain elements,	 *  put them in as source routing	 */	if(d > 1){		addhostdom(buf, field[0]);		for(j=1; j<d-1; j++){			s_append(buf, ",");			s_append(buf, "@");			s_append(buf, field[j]);		}		s_append(buf, ":");	}	/*	 *  throw in the non-domain elements separated by '!'s	 */	s_append(buf, field[d]);	for(j=d+1; j<=i-1; j++) {		s_append(buf, "!");		s_append(buf, field[j]);	}	if(d)		addhostdom(buf, field[d-1]);	return buf;}/* *  convert header addresses to @ format. *  if the address is a source address, and a domain is specified, *  make sure it falls in the domain. */String*convertheader(String *from){	Field *f;	Node *p, *lastp;	String *a;	if(!returnable(s_to_c(from))){		from = s_new();		s_append(from, "Postmaster");		addhostdom(from, hostdomain);	} else	if(strchr(s_to_c(from), '@') == 0){		a = username(from);		if(a) {			s_append(a, " <");			s_append(a, s_to_c(from));			addhostdom(a, hostdomain);			s_append(a, ">");			from = a;		} else {			from = s_copy(s_to_c(from));			addhostdom(from, hostdomain);		}	} else		from = s_copy(s_to_c(from));	for(f = firstfield; f; f = f->next){		lastp = 0;		for(p = f->node; p; lastp = p, p = p->next){			if(!p->addr)				continue;			a = bangtoat(s_to_c(p->s));			s_free(p->s);			if(strchr(s_to_c(a), '@') == 0)				addhostdom(a, hostdomain);			else if(*s_to_c(a) == '@')				a = fixrouteaddr(a, p->next, lastp);			p->s = a;		}	}	return from;}/* *	ensure route addr has brackets around it */String*fixrouteaddr(String *raddr, Node *next, Node *last){	String *a;	if(last && last->c == '<' && next && next->c == '>')		return raddr;			/* properly formed already */	a = s_new();	s_append(a, "<");	s_append(a, s_to_c(raddr));	s_append(a, ">");	s_free(raddr);	return a;}/* *  print out the parsed header */intprintheader(void){	int n, len;	Field *f;	Node *p;	char *cp;	char c[1];	n = 0;	for(f = firstfield; f; f = f->next){		for(p = f->node; p; p = p->next){			if(p->s)				n += dBprint("%s", s_to_c(p->s));			else {				c[0] = p->c;				putcrnl(c, 1);				n++;			}			if(p->white){				cp = s_to_c(p->white);				len = strlen(cp);				putcrnl(cp, len);				n += len;			}			uneaten = p->end;		}		putcrnl("\n", 1);		n++;		uneaten++;		/* skip newline */	}	return n;}/* *  add a domain onto an name, return the new name */char *domainify(char *name, char *domain){	static String *s;	char *p;	if(domain==0 || strchr(name, '.')!=0)		return name;	s = s_reset(s);	s_append(s, name);	p = strchr(domain, '.');	if(p == 0){		s_append(s, ".");		p = domain;	}	s_append(s, p);	return s_to_c(s);}/* *  print message observing '.' escapes and using \r\n for \n */voidputcrnl(char *cp, int n){	int c;	for(; n; n--, cp++){		c = *cp;		if(c == '\n')			dBputc('\r');		else if(c == '.' && last=='\n')			dBputc('.');		dBputc(c);		last = c;	}}/* *  Get a line including a crnl into a string.  Convert crnl into nl. */char *getcrnl(String *s){	int c;	int count;	count = 0;	for(;;){		c = Bgetc(&bin);		if(debug)			Bputc(&berr, c);		switch(c){		case -1:			s_append(s, "connection closed unexpectedly by remote system");			s_terminate(s);			return 0;		case '\r':			c = Bgetc(&bin);			if(c == '\n'){		case '\n':				s_putc(s, c);				if(debug)					Bputc(&berr, c);				count++;				s_terminate(s);				return s->ptr - count;			}			Bungetc(&bin);			s_putc(s, '\r');			if(debug)				Bputc(&berr, '\r');			count++;			break;		default:			s_putc(s, c);			count++;			break;		}	}}/* *  print out a parsed date */intprintdate(Node *p){	int n, sep = 0;	n = dBprint("Date: %s,", s_to_c(p->s));	for(p = p->next; p; p = p->next){		if(p->s){			if(sep == 0) {				dBputc(' ');				n++;			}			if (p->next)				n += dBprint("%s", s_to_c(p->s));			else				n += dBprint("%s", rewritezone(s_to_c(p->s)));			sep = 0;		} else {			dBputc(p->c);			n++;			sep = 1;		}	}	n += dBprint("\r\n");	return n;}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;}/* *  stolen from libc/port/print.c */#define	SIZE	4096intdBprint(char *fmt, ...){	char buf[SIZE], *out;	va_list arg;	int n;	va_start(arg, fmt);	out = vseprint(buf, buf+SIZE, fmt, arg);	va_end(arg);	if(debug){		Bwrite(&berr, buf, (long)(out-buf));		Bflush(&berr);	}	n = Bwrite(&bout, buf, (long)(out-buf));	Bflush(&bout);	return n;}intdBputc(int x){	if(debug)		Bputc(&berr, x);	return Bputc(&bout, x);}

⌨️ 快捷键说明

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