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

📄 main.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "common.h"#include "send.h"/* globals to all files */int rmail;char *thissys, *altthissys;int nflg;int xflg;int debug;int rflg;int iflg = 1;int nosummary;/* global to this file */static String *errstring;static message *mp;static int interrupt;static int savemail;static Biobuf in;static int forked;static int add822headers = 1;static String *arglist;/* predeclared */static int	send(dest *, message *, int);static void	lesstedious(void);static void	save_mail(message *);static int	complain_mail(dest *, message *);static int	pipe_mail(dest *, message *);static void	appaddr(String *, dest *);static void	mkerrstring(String *, message *, dest *, dest *, char *, int);static int	replymsg(String *, message *, dest *);static int	catchint(void*, char*);voidusage(void){	fprint(2, "usage: mail [-birtx] list-of-addresses\n");	exits("usage");}voidmain(int argc, char *argv[]){	dest *dp=0;	int checkforward;	char *base;	int rv;	/* process args */	ARGBEGIN{	case '#':		nflg = 1;		break;	case 'b':		add822headers = 0;		break;	case 'x':		nflg = 1;		xflg = 1;		break;	case 'd':		debug = 1;		break;	case 'i':		iflg = 0;		break;	case 'r':		rflg = 1;		break;	default:		usage();	}ARGEND	while(*argv){		if(shellchars(*argv)){			fprint(2, "illegal characters in destination\n");			exits("syntax");		}		d_insert(&dp, d_new(s_copy(*argv++)));	}	if (dp == 0)		usage();	arglist = d_to(dp);	/*	 * get context:	 *	- whether we're rmail or mail	 */	base = basename(argv0);	checkforward = rmail = (strcmp(base, "rmail")==0) | rflg;	thissys = sysname_read();	altthissys = alt_sysname_read();	if(rmail)		add822headers = 0;	/*	 *  read the mail.  If an interrupt occurs while reading, save in	 *  dead.letter	 */	if (!nflg) {		Binit(&in, 0, OREAD);		if(!rmail)			atnotify(catchint, 1);		mp = m_read(&in, rmail, !iflg);		if (mp == 0)			exit(0);		if (interrupt != 0) {			save_mail(mp);			exit(1);		}	} else {		mp = m_new();		if(default_from(mp) < 0){			fprint(2, "%s: can't determine login name\n", argv0);			exit(1);		}	}	errstring = s_new();	getrules();	/*	 *  If this is a gateway, translate the sender address into a local	 *  address.  This only happens if mail to the local address is 	 *  forwarded to the sender.	 */	gateway(mp);	/*	 *  Protect against shell characters in the sender name for	 *  security reasons.	 */	mp->sender = escapespecial(mp->sender);	if (shellchars(s_to_c(mp->sender)))		mp->replyaddr = s_copy("postmaster");	else		mp->replyaddr = s_clone(mp->sender);	/*	 *  reject messages that have been looping for too long	 */	if(mp->received > 32)		exit(refuse(dp, mp, "possible forward loop", 0, 0));	/*	 *  reject messages that are too long.  We don't do it earlier	 *  in m_read since we haven't set up enough things yet.	 */	if(mp->size < 0)		exit(refuse(dp, mp, "message too long", 0, 0));	rv = send(dp, mp, checkforward);	if(savemail)		save_mail(mp);	if(mp)		m_free(mp);	exit(rv);}/* send a message to a list of sites */static intsend(dest *destp, message *mp, int checkforward){	dest *dp;		/* destination being acted upon */	dest *bound;		/* bound destinations */	int errors=0;	/* bind the destinations to actions */	bound = up_bind(destp, mp, checkforward);	if(add822headers && mp->haveto == 0){		if(nosummary)			mp->to = d_to(bound);		else			mp->to = arglist;	}	/* loop through and execute commands */	for (dp = d_rm(&bound); dp != 0; dp = d_rm(&bound)) {		switch (dp->status) {		case d_cat:			errors += cat_mail(dp, mp);			break;		case d_pipeto:		case d_pipe:			if (!rmail && !nflg && !forked) {				forked = 1;				lesstedious();			}			errors += pipe_mail(dp, mp);			break;		default:			errors += complain_mail(dp, mp);			break;		}	}	return errors;}/* avoid user tedium (as Mike Lesk said in a previous version) */static voidlesstedious(void){	int i;	if(debug)		return;	switch(fork()){	case -1:		break;	case 0:		sysdetach();		for(i=0; i<3; i++)			close(i);		savemail = 0;		break;	default:		exit(0);	}}/* save the mail */static voidsave_mail(message *mp){	Biobuf *fp;	String *file;	file = s_new();	deadletter(file);	fp = sysopen(s_to_c(file), "cAt", 0660);	if (fp == 0)		return;	m_bprint(mp, fp);	sysclose(fp);	fprint(2, "saved in %s\n", s_to_c(file));	s_free(file);}/* remember the interrupt happened */static intcatchint(void *a, char *msg){	USED(a);	if(strstr(msg, "interrupt") || strstr(msg, "hangup")) {		interrupt = 1;		return 1;	}	return 0;}/* dispose of incorrect addresses */static intcomplain_mail(dest *dp, message *mp){	char *msg;	switch (dp->status) {	case d_undefined:		msg = "Invalid address"; /* a little different, for debugging */		break;	case d_syntax:		msg = "invalid address";		break;	case d_unknown:		msg = "unknown user";		break;	case d_eloop:	case d_loop:		msg = "forwarding loop";		break;	case d_noforward:		if(dp->pstat && *s_to_c(dp->repl2))			return refuse(dp, mp, s_to_c(dp->repl2), dp->pstat, 0);		else			msg = "destination unknown or forwarding disallowed";		break;	case d_pipe:		msg = "broken pipe";		break;	case d_cat:		msg = "broken cat";		break;	case d_translate:		if(dp->pstat && *s_to_c(dp->repl2))			return refuse(dp, mp, s_to_c(dp->repl2), dp->pstat, 0);		else			msg = "name translation failed";		break;	case d_alias:		msg = "broken alias";		break;	case d_badmbox:		msg = "corrupted mailbox";		break;	case d_resource:		return refuse(dp, mp, "out of some resource.  Try again later.", 0, 1);	default:		msg = "unknown d_";		break;	}	if (nflg) {		print("%s: %s\n", msg, s_to_c(dp->addr));		return 0;	}	return refuse(dp, mp, msg, 0, 0);}/* dispose of remote addresses */static intpipe_mail(dest *dp, message *mp){	dest *next, *list=0;	String *cmd;	process *pp;	int status;	char *none;	String *errstring=s_new();	if (dp->status == d_pipeto)		none = "none";	else		none = 0;	/*	 *  collect the arguments	 */	next = d_rm_same(&dp);	if(xflg)		cmd = s_new();	else		cmd = s_clone(next->repl1);	for(; next != 0; next = d_rm_same(&dp)){		if(xflg){			s_append(cmd, s_to_c(next->addr));			s_append(cmd, "\n");		} else {			if (next->repl2 != 0) {				s_append(cmd, " ");				s_append(cmd, s_to_c(next->repl2));			}		}		d_insert(&list, next);	}	if (nflg) {		if(xflg)			print("%s", s_to_c(cmd));		else			print("%s\n", s_to_c(cmd));		s_free(cmd);		return 0;	}	/*	 *  run the process	 */	pp = proc_start(s_to_c(cmd), instream(), 0, outstream(), 1, none);	if(pp==0 || pp->std[0]==0 || pp->std[2]==0)		return refuse(list, mp, "out of processes, pipes, or memory", 0, 1);	pipesig(0);	m_print(mp, pp->std[0]->fp, thissys, 0);	pipesigoff();	stream_free(pp->std[0]);	pp->std[0] = 0;	while(s_read_line(pp->std[2]->fp, errstring))		;	status = proc_wait(pp);	proc_free(pp);	s_free(cmd);	/*	 *  return status	 */	if (status != 0)		return refuse(list, mp, s_to_c(errstring), status, 0);	loglist(list, mp, "remote");	return 0;}static voidappaddr(String *sp, dest *dp){	dest *parent;	String *s;	if (dp->parent != 0) {		for(parent=dp->parent; parent->parent!=0; parent=parent->parent)			;		s = unescapespecial(s_clone(parent->addr));		s_append(sp, s_to_c(s));		s_free(s);		s_append(sp, "' alias `");	}	s = unescapespecial(s_clone(dp->addr));	s_append(sp, s_to_c(s));	s_free(s);}/* *  reject delivery * *  returns	0	- if mail has been disposed of *		other	- if mail has not been disposed */intrefuse(dest *list, message *mp, char *cp, int status, int outofresources){	String *errstring=s_new();	dest *dp;	int rv;	dp = d_rm(&list);	mkerrstring(errstring, mp, dp, list, cp, status);	/*	 *  log first in case we get into trouble	 */	logrefusal(dp, mp, s_to_c(errstring));	/*	 *  bulk mail is never replied to, if we're out of resources,	 *  let the sender try again	 */	if(rmail){		/* accept it or request a retry */		if(outofresources){			fprint(2, "Mail %s\n", s_to_c(errstring));			rv = 1;					/* try again later */		} else if(mp->bulk)			rv = 0;					/* silently discard bulk */		else			rv = replymsg(errstring, mp, dp);	/* try later if we can't reply */	} else {		/* aysnchronous delivery only happens if !rmail */		if(forked){			/*			 *  if spun off for asynchronous delivery, we own the mail now.			 *  return it or dump it on the floor.  rv really doesn't matter.			 */			rv = 0;			if(!outofresources && !mp->bulk)				replymsg(errstring, mp, dp);		} else {			fprint(2, "Mail %s\n", s_to_c(errstring));			savemail = 1;			rv = 1;		}	}	s_free(errstring);	return rv;}/* make the error message */static voidmkerrstring(String *errstring, message *mp, dest *dp, dest *list, char *cp, int status){	dest *next;	char smsg[64];	String *sender;	sender = unescapespecial(s_clone(mp->sender));	/* list all aliases */	s_append(errstring, " from '");	s_append(errstring, s_to_c(sender));	s_append(errstring, "'\nto '");	appaddr(errstring, dp);	for(next = d_rm(&list); next != 0; next = d_rm(&list)) {		s_append(errstring, "'\nand '");		appaddr(errstring, next);		d_insert(&dp, next);	}	s_append(errstring, "'\nfailed with error '");	s_append(errstring, cp);	s_append(errstring, "'.\n");	/* >> and | deserve different flavored messages */	switch(dp->status) {	case d_pipe:		s_append(errstring, "The mailer `");		s_append(errstring, s_to_c(dp->repl1));		sprint(smsg, "' returned error status %x.\n\n", status);		s_append(errstring, smsg);		break;	}	s_free(sender);}/* *  create a new boundary */static String*mkboundary(void){	char buf[32];	int i;	static int already;	if(already == 0){		srand((time(0)<<16)|getpid());		already = 1;	}	strcpy(buf, "upas-");	for(i = 5; i < sizeof(buf)-1; i++)		buf[i] = 'a' + nrand(26);	buf[i] = 0;	return s_copy(buf);}/* *  reply with up to 1024 characters of the *  original message */static intreplymsg(String *errstring, message *mp, dest *dp){	message *refp = m_new();	dest *ndp;	char *rcvr;	int rv;	String *boundary;	boundary = mkboundary();	refp->bulk = 1;	refp->rfc822headers = 1;	rcvr = dp->status==d_eloop ? "postmaster" : s_to_c(mp->replyaddr);	ndp = d_new(s_copy(rcvr));	s_append(refp->sender, "postmaster");	s_append(refp->replyaddr, "/dev/null");	s_append(refp->date, thedate());	refp->haveto = 1;	s_append(refp->body, "To: ");	s_append(refp->body, rcvr);	s_append(refp->body, "\n");	s_append(refp->body, "Subject: bounced mail\n");	s_append(refp->body, "MIME-Version: 1.0\n");	s_append(refp->body, "Content-Type: multipart/mixed;\n");	s_append(refp->body, "\tboundary=\"");	s_append(refp->body, s_to_c(boundary));	s_append(refp->body, "\"\n");	s_append(refp->body, "Content-Disposition: inline\n");	s_append(refp->body, "\n");	s_append(refp->body, "This is a multi-part message in MIME format.\n");	s_append(refp->body, "--");	s_append(refp->body, s_to_c(boundary));	s_append(refp->body, "\n");	s_append(refp->body, "Content-Disposition: inline\n");	s_append(refp->body, "Content-Type: text/plain; charset=\"US-ASCII\"\n");	s_append(refp->body, "Content-Transfer-Encoding: 7bit\n");	s_append(refp->body, "\n");	s_append(refp->body, "The attached mail");	s_append(refp->body, s_to_c(errstring));	s_append(refp->body, "--");	s_append(refp->body, s_to_c(boundary));	s_append(refp->body, "\n");	s_append(refp->body, "Content-Type: message/rfc822\n");	s_append(refp->body, "Content-Disposition: inline\n\n");	s_append(refp->body, s_to_c(mp->body));	s_append(refp->body, "--");	s_append(refp->body, s_to_c(boundary));	s_append(refp->body, "--\n");	refp->size = s_len(refp->body);	rv = send(ndp, refp, 0);	m_free(refp);	d_free(ndp);	return rv;}

⌨️ 快捷键说明

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