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

📄 mail.c

📁 unix v7是最后一个广泛发布的研究型UNIX版本
💻 C
字号:
#include <stdio.h>#include <pwd.h>#include <utmp.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <setjmp.h>#include <whoami.h>/*copylet flags */	/*remote mail, add rmtmsg */#define REMOTE	1	/* zap header and trailing empty line */#define ZAP	3#define ORDINARY 2#define	FORWARD	4#define	LSIZE	256#define	MAXLET	300	/* maximum number of letters */#define	MAILMODE (~0644)		/* mode of created mail */char	line[LSIZE];char	resp[LSIZE];struct let {	long	adr;	char	change;} let[MAXLET];int	nlet	= 0;char	lfil[50];long	iop, time();char	lettmp[] = "/tmp/maXXXXX";char	maildir[] = "/usr/spool/mail/";char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxx";char	dead[] = "dead.letter";char	*thissys = sysname;char	forwmsg[] = " forwarded\n";char	*curlock;int	lockerror;FILE	*tmpf;FILE	*malf;char	*my_name;char	*getlogin();struct	passwd	*getpwuid();int	error;int	locked;int	changed;int	forward;char	from[] = "From ";long	ftell();int	delete();char	*ctime();int	flgf;int	flgp;int	delflg = 1;jmp_buf	sjbuf;main(argc, argv)char **argv;{	register i;	char sobuf[BUFSIZ];	setbuf(stdout, sobuf);	mktemp(lettmp);	unlink(lettmp);	my_name = getlogin();	if (my_name == NULL) {		struct passwd *pwent;		pwent = getpwuid(getuid());		if (pwent==NULL)			my_name = "???";		else			my_name = pwent->pw_name;	}	if(setjmp(sjbuf)) done();	for (i=0; i<20; i++)		setsig(i, delete);	tmpf = fopen(lettmp, "w");	if (tmpf == NULL) {		fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);		done();	}	if (argv[0][0] != 'r' &&	/* no favors for rmail*/	   (argc == 1 || argv[1][0] == '-'))		printmail(argc, argv);	else		sendmail(argc, argv);	done();}setsig(i, f)int i;int (*f)();{	if(signal(i, SIG_IGN)!=SIG_IGN)		signal(i, f);}printmail(argc, argv)char **argv;{	int flg, i, j, print;	char *p, *getarg();	setuid(getuid());	cat(mailfile, maildir, my_name);	for (; argc>1; argv++, argc--) {		if (argv[1][0]=='-') {			if (argv[1][1]=='q')				delflg = 0;			else if (argv[1][1]=='p') {				flgp++;				delflg = 0;			} else if (argv[1][1]=='f') {				if (argc>=3) {					strcpy(mailfile, argv[2]);					argv++;					argc--;				}			} else if (argv[1][1]=='r') {				forward = 1;			} else {				fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);				done();			}		} else			break;	}	malf = fopen(mailfile, "r");	if (malf == NULL) {		fprintf(stdout, "No mail.\n");		return;	}	lock(mailfile);	copymt(malf, tmpf);	fclose(malf);	fclose(tmpf);	unlock();	tmpf = fopen(lettmp, "r");	changed = 0;	print = 1;	for (i = 0; i < nlet; ) {		j = forward ? i : nlet - i - 1;		if(setjmp(sjbuf)) {			print=0;		} else {			if (print)				copylet(j, stdout, ORDINARY);			print = 1;		}		if (flgp) {			i++;			continue;		}		setjmp(sjbuf);		fprintf(stdout, "? ");		fflush(stdout);		if (fgets(resp, LSIZE, stdin) == NULL)			break;		switch (resp[0]) {		default:			fprintf(stderr, "usage\n");		case '?':			print = 0;			fprintf(stderr, "q\tquit\n");			fprintf(stderr, "x\texit without changing mail\n");			fprintf(stderr, "p\tprint\n");			fprintf(stderr, "s[file]\tsave (default mbox)\n");			fprintf(stderr, "w[file]\tsame without header\n");			fprintf(stderr, "-\tprint previous\n");			fprintf(stderr, "d\tdelete\n");			fprintf(stderr, "+\tnext (no delete)\n");			fprintf(stderr, "m user\tmail to user\n");			fprintf(stderr, "! cmd\texecute cmd\n");			break;		case '+':		case 'n':		case '\n':			i++;			break;		case 'x':			changed = 0;		case 'q':			goto donep;		case 'p':			break;		case '^':		case '-':			if (--i < 0)				i = 0;			break;		case 'y':		case 'w':		case 's':			flg = 0;			if (resp[1] != '\n' && resp[1] != ' ') {				printf("illegal\n");				flg++;				print = 0;				continue;			}			if (resp[1] == '\n' || resp[1] == '\0')				cat(resp+1, "mbox", "");			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {				malf = fopen(lfil, "a");				if (malf == NULL) {					fprintf(stdout, "mail: cannot append to %s\n", lfil);					flg++;					continue;				}				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);				fclose(malf);			}			if (flg)				print = 0;			else {				let[j].change = 'd';				changed++;				i++;			}			break;		case 'm':			flg = 0;			if (resp[1] == '\n' || resp[1] == '\0') {				i++;				continue;			}			if (resp[1] != ' ') {				printf("invalid command\n");				flg++;				print = 0;				continue;			}			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )				if (!sendrmt(j, lfil))	/* couldn't send it */					flg++;			if (flg)				print = 0;			else {				let[j].change = 'd';				changed++;				i++;			}			break;		case '!':			system(resp+1);			printf("!\n");			print = 0;			break;		case 'd':			let[j].change = 'd';			changed++;			i++;			if (resp[1] == 'q')				goto donep;			break;		}	}   donep:	if (changed)		copyback();}copyback()	/* copy temp or whatever back to /usr/spool/mail */{	register i, n, c;	int new = 0;	struct stat stbuf;	signal(SIGINT, SIG_IGN);	signal(SIGHUP, SIG_IGN);	signal(SIGQUIT, SIG_IGN);	lock(mailfile);	stat(mailfile, &stbuf);	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */		malf = fopen(mailfile, "r");		if (malf == NULL) {			fprintf(stdout, "mail: can't re-read %s\n", mailfile);			done();		}		fseek(malf, let[nlet].adr, 0);		fclose(tmpf);		tmpf = fopen(lettmp, "a");		fseek(tmpf, let[nlet].adr, 0);		while ((c = fgetc(malf)) != EOF)			fputc(c, tmpf);		fclose(malf);		fclose(tmpf);		tmpf = fopen(lettmp, "r");		let[++nlet].adr = stbuf.st_size;		new = 1;	}	malf = fopen(mailfile, "w");	if (malf == NULL) {		fprintf(stderr, "mail: can't rewrite %s\n", lfil);		done();	}	n = 0;	for (i = 0; i < nlet; i++)		if (let[i].change != 'd') {			copylet(i, malf, ORDINARY);			n++;		}	fclose(malf);	if (new)		fprintf(stdout, "new mail arrived\n");	unlock();}copymt(f1, f2)	/* copy mail (f1) to temp (f2) */FILE *f1, *f2;{	long nextadr;	nlet = nextadr = 0;	let[0].adr = 0;	while (fgets(line, LSIZE, f1) != NULL) {		if (isfrom(line))			let[nlet++].adr = nextadr;		nextadr += strlen(line);		fputs(line, f2);	}	let[nlet].adr = nextadr;	/* last plus 1 */}copylet(n, f, type) FILE *f;{	int ch, k;	fseek(tmpf, let[n].adr, 0);	k = let[n+1].adr - let[n].adr;	while(k-- > 1 && (ch=fgetc(tmpf))!='\n')		if(type!=ZAP) fputc(ch,f);	if(type==REMOTE)		fprintf(f, " remote from %s\n", thissys);	else if (type==FORWARD)		fprintf(f, forwmsg);	else if(type==ORDINARY)		fputc(ch,f);	while(k-->1)		fputc(ch=fgetc(tmpf), f);	if(type!=ZAP || ch!= '\n')		fputc(fgetc(tmpf), f);}isfrom(lp)register char *lp;{	register char *p;	for (p = from; *p; )		if (*lp++ != *p++)			return(0);	return(1);}sendmail(argc, argv)char **argv;{	time(&iop);	fprintf(tmpf, "%s%s %s", from, my_name, ctime(&iop));	iop = ftell(tmpf);	flgf = 1;	while (fgets(line, LSIZE, stdin) != NULL) {		if (line[0] == '.' && line[1] == '\n')			break;		if (isfrom(line))			fputs(">", tmpf);		fputs(line, tmpf);		flgf = 0;	}	fputs("\n", tmpf);	nlet = 1;	let[0].adr = 0;	let[1].adr = ftell(tmpf);	fclose(tmpf);	if (flgf)		return;	tmpf = fopen(lettmp, "r");	if (tmpf == NULL) {		fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);		return;	}	while (--argc > 0)		if (!send(0, *++argv))	/* couldn't send to him */			error++;	if (error) {		setuid(getuid());		malf = fopen(dead, "w");		if (malf == NULL) {			fprintf(stdout, "mail: cannot open %s\n", dead);			fclose(tmpf);			return;		}		copylet(0, malf, ZAP);		fclose(malf);		fprintf(stdout, "Mail saved in %s\n", dead);	}	fclose(tmpf);}sendrmt(n, name)char *name;{	FILE *rmf, *popen();	register char *p;	char rsys[64], cmd[64];	register local, pid;	int sts;	local = 0;	if (*name=='!')		name++;	for(p=rsys; *name!='!'; *p++ = *name++)		if (*name=='\0') {			local++;			break;		}	*p = '\0';	if ((!local && *name=='\0') || (local && *rsys=='\0')) {		fprintf(stdout, "null name\n");		return(0);	}	if ((pid = fork()) == -1) {		fprintf(stderr, "mail: can't create proc for remote\n");		return(0);	}	if (pid) {		while (wait(&sts) != pid) {			if (wait(&sts)==-1)				return(0);		}		return(!sts);	}	setuid(getuid());	if (local)		sprintf(cmd, "mail %s", rsys);	else {		if (index(name+1, '!'))			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);		else			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);	}	if ((rmf=popen(cmd, "w")) == NULL)		exit(1);	copylet(n, rmf, local? FORWARD: REMOTE);	pclose(rmf);	exit(0);}send(n, name)	/* send letter n to name */int n;char *name;{	char file[50];	register char *p;	register mask;	struct passwd *pw, *getpwnam();	for(p=name; *p!='!' &&*p!='\0'; p++)		;	if (*p == '!')		return(sendrmt(n, name));	if ((pw = getpwnam(name)) == NULL) {		fprintf(stdout, "mail: can't send to %s\n", name);		return(0);	}	cat(file, maildir, name);	mask = umask(MAILMODE);	malf = fopen(file, "a");	umask(mask);	if (malf == NULL) {		fprintf(stdout, "mail: cannot append to %s\n", file);		return(0);	}	lock(file);	chown(file, pw->pw_uid, pw->pw_gid);	copylet(n, malf, ORDINARY);	fclose(malf);	unlock();	return(1);}delete(i){	setsig(i, delete);	fprintf(stderr, "\n");	if(delflg)		longjmp(sjbuf, 1);	done();}done(){	if(!lockerror)		unlock();	unlink(lettmp);	exit(error+lockerror);}lock(file)char *file;{	struct stat stbuf;	if (locked || flgf)		return;	if (stat(file, &stbuf)<0)		return;	if (stbuf.st_mode&01) { 	/* user x bit is the lock */		if (stbuf.st_ctime+60 >= time((long *)0)) {			fprintf(stderr, "%s busy; try again in a minute\n", file);			lockerror++;			done();		}	}	locked = stbuf.st_mode & ~01;	curlock = file;	chmod(file, stbuf.st_mode|01);}unlock(){	if (locked)		chmod(curlock, locked);	locked = 0;}cat(to, from1, from2)char *to, *from1, *from2;{	int i, j;	j = 0;	for (i=0; from1[i]; i++)		to[j++] = from1[i];	for (i=0; from2[i]; i++)		to[j++] = from2[i];	to[j] = 0;}char *getarg(s, p)	/* copy p... into s, update p */register char *s, *p;{	while (*p == ' ' || *p == '\t')		p++;	if (*p == '\n' || *p == '\0')		return(NULL);	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')		*s++ = *p++;	*s = '\0';	return(p);}

⌨️ 快捷键说明

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