#
/* mail command usage
	mail
		prints your mail
	mail people
		sends standard input to people
 */

#define	SIGINT	2
	/* Overall status */
#define		ALLGOOD 0
#define		SOMEBAD	4
#define		ALLBAD	-1
	/* Incremental status */
#define		GOOD	0
#define		BAD	4
#define		VBAD	-1
 
struct xcode{
	int summary;
	int count;
}xcode;
 

struct	utmp {
	char	name[8];
	char	tty1;
	char	tty2;
	int	ltime[2];
	int	pad2;
}ubuf;

struct	passwd {
	char	*pw_name;
	char	*pw_passwd;
	int	pw_uid;
	char	*pw_gecos;
	char	*pw_dir;
	char	*pw_shell;
};

char	lettmp[] "/tmp/maxxxxx";
char	preptmp[] "/tmp/mbxxxxx";
char	*utmpf	"/etc/utmp";
int	pwfil;
struct{
	char lobyte;
	char hibyte;
};

main(argc, argv)
char **argv;
{
	int me,uf;
	extern fout;
	register struct passwd *p;
	register char *cp;

	xcode.summary = ALLGOOD;
	xcode.count = argc;
	maketemp();
	if (argv[1][0]=='-')
		xcode.count--;
	if (argc==1 || argc==2 && argv[1][0]=='-') {
		printmail(argc, argv);
		delexit();
	}
	signal(SIGINT, delexit);
	xcode.count--;
	fout = creat(lettmp, 0600);
	me = lnxx(1);
	if(me.lobyte == 'x' && me.hibyte == 'x'){
		me = lnxx(2);
		if(me.lobyte == 'x' && me.hibyte == 'x') goto out;
	}
	if((uf=open(utmpf,0)) > 0) {
		while (read(uf, &ubuf, sizeof ubuf) == sizeof ubuf)
			if((ubuf.tty1 == me.lobyte)&&(ubuf.tty2 == me.hibyte)){
				ubuf.name[0] =& ~0200; /*strip negative*/
				ubuf.name[8] = ' ';
				close(uf);
				for(cp=ubuf.name; *cp != ' '; cp++);
				*cp = 0;
				bulkmail(argc, argv, ubuf.name);
			}
	}
out:
	me = getuid() & 0377;
	setpw();
	for (;;)
		if ((p = getpwent()) && p->pw_uid == me)
			bulkmail(argc, argv, p->pw_name);
	fout = 1;
	printf("Who are you?\n");
	xcode.summary = ALLBAD;
	delexit();
}

printmail(argc, argv)
char **argv;
{
	extern fin, fout;
	register n, c, f;
	int ln;

	if (fopen(".mail", &fin)>=0 && (c = getchar())) {
		do {
			putchar(c);
		} while (c = getchar());
		close(fin);
		c = 'y';
		if (argc<2) {
			ln = lnxx(0);
			if(ln.lobyte != 'x' || ln.hibyte != 'x'){
				printf("Save?");
				fin = 0;
				c = getchar();
			}
		} else
			c = argv[1][1];
		if (c=='y') {
			prepend(".mail", "mbox");
			printf("Saved mail in 'mbox'\n");
		}
		close(creat(".mail"));
	} else
		printf("No mail.\n");
}

bulkmail(argc, argv, from)
char **argv, *from;
{
	extern fin, fout;
	int tbuf[2];
	int ex;
	register c;

	fin = 0;
	(&fin)[1] = 0;
	time(tbuf);
	printf("From %s %s", from, ctime(tbuf));
	while (c = getchar())
		putchar(c);
	putchar('\n');
	flush();
	close(fout);
	while (--argc > 0) {
		if((ex = sendto(*++argv)) > GOOD) {
			xcode.count--;
			if(ex > xcode.summary) {
				xcode.summary = ex;
			}
		}
	}
	delexit();
}

sendto(person)
char *person;
{
	static saved;
	extern fout;
	extern fin;
	register struct passwd *p;
	int	ln;

	setpw();
	while (p = getpwent()) {
		if (equal(p->pw_name, person)) {
			if (prepend(lettmp, cat(p->pw_dir, "/.mail"))==0) {
				return(BAD);
				break;
			}
			return(GOOD);
		}
	}
	fout = 1;
	flush();
	printf("Can't send to %s.\n", person);
	ln = lnxx(0);
	if((ln.lobyte != 'x' || ln.hibyte != 'x') && saved == 0){
		unlink("dead.letter");
		saved++;
		printf("Letter saved in 'dead.letter'\n");
		prepend(lettmp, "dead.letter");
	}
	return(BAD);
}

prepend(from, to)
char *from, *to;
{
	extern int fin, fout;

	fcreat(preptmp, &fout);
	fopen(from, &fin);
	while (putchar(getchar()));
	close(fin);
	fopen(to, &fin);
	while (putchar(getchar()));
	close(fin);
	flush();
	close(fout);
	if (fcreat(to, &fout) < 0) {
		fout = 1;
		return(0);
	}
	fopen(preptmp, &fin);
	while(putchar(getchar()));
	flush();
	close(fout);
	close(fin);
	fout = 1;
	return(1);
}

setpw()
{
	extern fin;

	if (pwfil == 0) {
		fopen("/etc/passwd", &fin);
		pwfil = fin;
	} else
		fin = pwfil;
	(&fin)[1] = 0;
	seek(fin, 0, 0);
}

getpwent()
{
	register char *p;
	register c;
	static struct passwd passwd;
	static char line[100];
	extern fin;

	p = line;
	while((c=getchar()) != '\n') {
		if(c <= 0)
			return(0);
		if(p < line+98)
			*p++ = c;
	}
	*p = 0;
	p = line;
	passwd.pw_name = p;
	p = pwskip(p);
	passwd.pw_passwd = p;
	p = pwskip(p);
	passwd.pw_uid = atoi(p);
	p = pwskip(p);
	passwd.pw_gecos = p;
	p = pwskip(p);
	passwd.pw_dir = p;
	p = pwskip(p);
	passwd.pw_shell = p;
	return(&passwd);
}

pwskip(ap)
char *ap;
{
	register char *p;

	p = ap;
	while(*p != ':') {
		if(*p == 0)
			return(p);
		p++;
	}
	*p++ = 0;
	return(p);
}

delexit()
{
	unlink(lettmp);
	unlink(preptmp);
	if(xcode.count == 0)
		exit(ALLBAD);
	else
		exit(xcode.summary);
}

maketemp()
{
	int i, pid, d;

	pid = getpid();
	for (i=11; i>=7; --i) {
		d = (pid&07) + '0';
		lettmp[i] = d;
		preptmp[i] = d;
		pid =>> 3;
	}
}

equal(as1, as2)
{
	register char *s1, *s2;

	s1 = as1;
	s2 = as2;
	while (*s1++ == *s2)
		if (*s2++ == 0)
			return(1);
	return(0);
}

cat(ap1, ap2)
char *ap1, *ap2;
{
	register char *p1, *p2;
	static char fn[32];

	p1 = ap1;
	p2 = fn;
	while (*p2++ = *p1++);
	p2--;
	p1 = ap2;
	while (*p2++ = *p1++);
	return(fn);
}
