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

#define	SIGINT	2

struct	utmp {
	char	name[8];
	char	tty;
	char	pad1;
	int	ltime[2];
	int	pad2;
};

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

char	lettmp[]	"/tmp/maxxxxx";
char	preptmp[]	"/tmp/mbxxxxx";
char	mailfile[]	"/usr/mail/";
int	pwfil;
char	*cp;
int	me;
struct	passwd	*p;
struct	utmp	ubuf;
int	uf;

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

	maketemp();
	if (argc==1 || argc==2 && argv[1][0]=='-') {
		printmail(argc, argv);
		delexit();
	}
	signal(SIGINT, delexit);
	fout = creat(lettmp, 0600);
	if (((me=ttyn(1))!='x' || (me=ttyn(2))!='x')
	 && (uf = open("/etc/utmp", 0)) > 0) {
		while (read(uf, &ubuf, sizeof ubuf) == sizeof ubuf)
			if (ubuf.tty == me) {
				ubuf.name[8] = ' ';
				close(uf);
				for (cp=ubuf.name; *cp++!=' ';);
				*--cp = 0;
				bulkmail(argc, argv, ubuf.name);
			}
	}
	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");
	delexit();
}

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

	if ((uf=open("/etc/utmp", 0)) < 0)  {
		fout = 1;
		printf("can't tell who you are\n");
		delexit();
		}
	me = ttyn(1);
	while (read(uf, &ubuf, sizeof ubuf) == sizeof ubuf)
		if (ubuf.tty == me) {
			ubuf.name[8] = ' ';
			close(uf);
			for (cp=ubuf.name; *cp++!=' ';);
			*--cp = 0;
			cp = cat(mailfile, ubuf.name);
			break;
			}
	if (fopen(cp, &fin)>=0 && (c = getchar())) {
		if (argc < 2) do {
			putchar(c);
		} while (c = getchar());
		close(fin);
		c = 'y';
		if (argc<2) {
			if (ttyn(0)!='x') {
				printf("Save: ");
				fin = 0;
				c = getchar();
			}
		} else
			c = argv[1][1];
		if (c=='y') {
			prepend(cp, "mbox", 1);
			printf("Saved mail in 'mbox'\n");
		}
		unlink(cp);
	} else
		printf("No mail.\n");
}

bulkmail(argc, argv, from)
char **argv, *from;
{
	extern fin, fout;
	int tbuf[2];
	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)
		sendto(*++argv);
	delexit();
}

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

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

prepend(from, to, suid)
char *from, *to;
{
	extern int fin, fout;
	register c;
	int status;

	fcreat(preptmp, &fout);
	fopen(from, &fin);
	while ((c = getchar()) && putchar(c))
		;
	close(fin);
	fopen(to, &fin);
	while ((c = getchar()) && putchar(c))
		;
	close(fin);
	flush();
	close(fout);
	fopen(preptmp, &fin);
	if (suid)
		if (fork()) {
			wait(&status);
			close(fin);
			fout = 1;
			return(1);
		} else
			setuid(getuid()&0377);
	if (fcreat(to, &fout) < 0) {
		close(fin);
		fout = 1;
		if (suid)
			exit(1);
		else
			return(0);
	}
	while ((c = getchar()) && putchar(c))
		;
	flush();
	close(fout);
	close(fin);
	fout = 1;
	if (suid)
		exit(0);
	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_gid = 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);
	exit(0);
}

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);
}

