/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#ident	"@(#)printmail.c	1.11	93/06/24 SMI"	/* SVr4.0 1.8 */

#include "mail.h"
/*
	Print mail entries
*/
void printmail()
{
	static char pn[] = "printmail";
	int	flg, curlet, showlet, k, print, aret, stret, rc;
	int	nsmbox = 0;	/* 1 ==> mailbox is in non-standard place */
	int	sav_j = -1;
	char	*p, *getarg();
	struct	stat stbuf;
	struct	stat *stbufp;
	int ttyf = isatty(1) ? TTY : ORDINARY;
	char	readbuf[LSIZE];	/* holds user's response in interactive mode */
	char	*resp;

	stbufp = &stbuf;

	/*
		create working directory mbox name
	*/
	if ((hmbox = malloc(strlen(home) + strlen(mbox) + 1)) == NULL) {
		errmsg(E_MBOX, "");
		return;
	}
	cat(hmbox, home, mbox);

	/*
		If we are not using an alternate mailfile, then get
		the $MAIL value and build the filename for the mailfile.
		If $MAIL is set, but is NOT the 'standard' place, then
		use it but set flgf to circumvent :saved processing.
	*/
	if (!flgf) {
		if ((p = malloc(strlen(maildir) + strlen(my_name) + 1))
								== NULL) {
			errmsg(E_MEM, "");
			return;
		}
		cat(p, maildir, my_name);
		if (((mailfile = getenv("MAIL")) == NULL) ||
		    (strlen(mailfile) == 0)) {
			/* $MAIL not set, use standard path to mailfile */
			mailfile = p;
		} else {
			if (strcmp(mailfile, p) != 0) {
			    flgf = 1;
			    nsmbox = 1;
			    Dout(pn, 0, "$MAIL ('%s') != standard path\n",
				mailfile);
			    Dout("", 0, "\tSetting flgf to 1.\n");
			}
			free (p);
		}
	}

	/*
		Get ACCESS and MODIFICATION times of mailfile BEFORE we
		use it. This allows us to put them back when we are
		done. If we didn't, the shell would think NEW mail had
		arrived since the file times would have changed.
	*/
	stret = CERROR;
	if (access(mailfile, A_EXIST) == A_OK) {
		if ((stret = stat(mailfile, stbufp)) != A_OK) {
			errmsg(E_FILE, "Cannot stat mailfile");
			return;
		}
		mf_gid = stbufp->st_gid;
		mf_uid = stbufp->st_uid;
		utimep->actime = stbufp->st_atime;
		utimep->modtime = stbufp->st_mtime;
		file_size = stbufp->st_size;
	}

	/*
		Check accessibility of mail file, and open it
	*/
	if ((aret = access(mailfile, A_READ)) == A_OK)
		malf = fopen(mailfile, "r");
	/*
		stat succeeded, but we cannot access the mailfile
	*/
	if (stret == CSUCCESS && aret == CERROR) {
		char buf[MAXFILENAME+50];
		sprintf(buf, "Invalid permissions on %s", mailfile);
		errmsg(E_PERM, buf);
		return;
	}else
	/*
		using an alternate mailfile, but we failed on access
	*/
	if (!nsmbox && flgf && (aret == CERROR || (malf == NULL))) {
		errmsg(E_FILE, "Cannot open mailfile");
		return;
	}
	/*
		we failed to access OR the file is empty
	*/
	else if (aret == CERROR || (malf == NULL) || (stbuf.st_size == 0)) {
		if (!flge && !flgE) {
			printf("No mail.\n");
		}
		error = E_FLGE;
		Dout(pn, 0, "error set to %d\n", error);
		return;
	}
	if (flge)
		return;

	if (flgE) {
		if (utimep->modtime <= utimep->actime) {
			error = E_FLGE_OM;
			Dout(pn, 0, "error set to %d\n", error);
		}
		return;
	}
	/*
		Secure the mailfile to guarantee integrity
	*/
	lock(my_name);

	/*
		copy mail to temp file and mark each letter in the
		let array --- mailfile is still locked !!!
	*/
	mktmp();
	copymt(malf, tmpf);
	onlet = nlet;
	fclose(malf);
	fclose(tmpf);
	unlock();	/* All done, OK to unlock now */
	tmpf = doopen(lettmp, "r+", E_TMP);
	changed = 0;
	print = 1;
	curlet = 0;
	while (curlet < nlet) {
		/*
			reverse order ?
		*/
		showlet = flgr ? curlet : nlet - curlet - 1;

		if (setjmp(sjbuf) == 0 && print != 0) {
				/* -h says to print the headers first */
				if (flgh) {
					gethead(showlet, 0);
					flgh = 0;	/* Only once */
					/* set letter # to invalid # */
					curlet--;
					showlet =
					    flgr ? curlet : nlet - curlet - 1;
				} else {
					if (showlet != sav_j) {
						/* Looking at new message. */
						/* Reset flag to override */
						/* non-display of binary */
						/* contents */
						sav_j = showlet;
						pflg = 0;
						Pflg = flgP;
					}
					copylet(showlet, stdout, ttyf);
				}
		}

		/*
			print only
		*/
		if (flgp) {
			curlet++;
			continue;
		}
		/*
			Interactive
		*/
		interactive = 1;
		setjmp(sjbuf);
		stat(mailfile, stbufp);
		if (stbufp->st_size != file_size) {
			/*
				New mail has arrived, load it
			*/
			k = nlet;
			lock(my_name);
			malf = doopen(mailfile, "r", E_FILE);
			fclose(tmpf);
			tmpf = doopen(lettmp, "a", E_TMP);
			fseek(malf, let[nlet].adr, 0);
			copymt(malf, tmpf);
			file_size = stbufp->st_size;
			fclose(malf);
			fclose(tmpf);
			unlock();
			tmpf = doopen(lettmp, "r+", E_TMP);
			if (++k < nlet)
				printf("New mail loaded into letters %d - %d\n",
				    k, nlet);
			else
				printf("New mail loaded into letter %d\n",
				    nlet);
		}

		/* read the command */
		printf("? ");
		fflush(stdout);
		fflush(stderr);
		if (fgets(readbuf, sizeof (readbuf), stdin) == NULL) break;
		resp = readbuf;
		while (*resp == ' ' || *resp == '\t') resp++;
		print = 1;
		Dout(pn, 0, "resp = '%s'\n", resp);
		if ((rc = atoi(resp)) != 0) {
			if (!validmsg(rc)) print = 0;
			else curlet = flgr ? rc - 1 : nlet - rc;
		} else switch (resp[0]) {
			default:
				printf("Usage:\n");
			/*
				help
			*/
			case '?':
				print = 0;
				for (rc = 0; help[rc]; rc++)
					printf("%s", help[rc]);
				break;
			/*
				print message number of current message
			*/
			case '#':
				print = 0;
				if ((showlet == nlet) || (showlet < 0)) {
					printf("No message selected yet.\n");
				} else {
					printf("Current message number is %d\n",
					    showlet+1);
				}
				break;
			/*
				headers
			*/
			case 'h':
				print = 0;
				if (resp[2] != 'd' &&
				    resp[2] != 'a' &&
				    (rc = getnumbr(resp+1)) > 0) {
					showlet = rc - 1;
					curlet = flgr ? rc - 1 : nlet - rc- 1;
				}
				if (rc == -1 && resp[2] != 'a' &&
				    resp[2] != 'd')
					break;
				if (resp[2] == 'a') rc = 1;
				else if (resp[2] == 'd') rc = 2;
					else rc = 0;

/*
				if (!validmsg(showlet)) break;
*/
				gethead(showlet, rc);
				break;
			/*
				skip entry
			*/
			case '+':
			case 'n':
			case '\n':
				curlet++;
				break;
			case 'P':
				Pflg++;
				break;
			case 'p':
				pflg++;
				break;
			case 'x':
				changed = 0;
			case 'q':
				goto donep;
			/*
				Previous entry
			*/
			case '^':
			case '-':
				if (--curlet < 0) curlet = 0;
				break;
			/*
				Save in file without header
			*/
			case 'y':
			case 'w':
			/*
				Save mail with header
			*/
			case 's':
				print = 0;
				if (!validmsg(curlet)) break;
				if (resp[1] == '\n' || resp[1] == '\0') {
					cat(resp+1, hmbox, "");
				} else if (resp[1] != ' ') {
					printf("Invalid command\n");
					break;
				}
				umask(umsave);
				flg = 0;
				if (getarg(lfil, resp + 1) == NULL) {
					cat(resp + 1, hmbox, "");
				}
				malf = (FILE *)NULL;
				p = resp + 1;
				while ((p = getarg(lfil, p)) != NULL) {
					if (flg) {
					    fprintf(stderr,
						"%s: File '%s' skipped\n",
						program, lfil);
					    continue;
					}
					malf = NULL;
					if ((aret = legal(lfil))) {
						malf = fopen(lfil, "a");
					}
					if ((malf == NULL) || (aret == 0)) {
					    fprintf(stderr,
						"%s: Cannot append to %s\n",
						program, lfil);
					    flg++;
					} else if (aret == 2) {
						chown(lfil, my_euid, my_gid);
					}
					if (!flg &&
					    copylet(showlet, malf, resp[0] ==
					    's'? ORDINARY: ZAP) == FALSE) {
						fprintf(stderr,
					    "%s: Cannot save mail to '%s'\n",
						    program, lfil);
						flg++;
					} else
						Dout(pn, 0, "!saved\n");
					if (malf != (FILE *)NULL) {
						fclose(malf);
					}
				}
				umask(7);
				if (!flg) {
					setletr(showlet, resp[0]);
					print = 1;
					curlet++;
				}
				break;
			/*
				Reply to a letter
			*/
			case 'r':
				print = 0;
				if (!validmsg(curlet)) break;
				replying = 1;
				for (k = 1; resp[k] == ' ' || resp[k] == '\t';
				    ++k);
				resp[strlen(resp)-1] = '\0';
				strcpy(m_sendto, resp+k);
				goback(showlet);
				replying = 0;
				setletr(showlet, resp[0]);
				break;
			/*
				Undelete
			*/
			case 'u':
				print = 0;
				if ((k = getnumbr(resp+1)) <= 0) k = showlet;
				else k--;
				if (!validmsg(k)) break;
				setletr(k, ' ');
				break;
			/*
				Mail letter to someone else
			*/
			case 'm':
				{
				reciplist list;
				print = 0;
				if (!validmsg(curlet)) break;
				new_reciplist(&list);
				flg = 0;
				k = 0;
				if (substr(resp, " -") != -1 ||
					substr(resp, "\t-") != -1) {
					printf("Only users may be specified\n");
					break;
				}
				p = resp + 1;
				while ((p = getarg(lfil, p)) != NULL) {
					char *env;
					if (lfil[0] == '$') {
						if (!(env = getenv(&lfil[1]))) {
							fprintf(stderr,
				"%s: %s has no value or is not exported.\n",
							    program, lfil);
							flg++;
						} else
							add_recip(&list, env,
							    FALSE);
						k++;
					} else if (lfil[0] != '\0') {
						add_recip(&list, lfil, FALSE);
						k++;
					}
				}
				strcpy (Rpath, my_name);
				sending = TRUE;
				flg += sendlist(&list, showlet, 0);
				sending = FALSE;
				if (k) {
					if (!flg) {
						setletr(showlet, 'm');
						print = 1;
						curlet++;
					}
				} else
					printf("Invalid command\n");
				del_reciplist(&list);
				break;
				}
			/*
				Read new letters
			*/
			case 'a':
				if (onlet == nlet) {
					printf("No new mail\n");
					print = 0;
					break;
				}
				curlet = 0;
				print = 1;
				break;
			/*
				Escape to shell
			*/
			case '!':
				systm(resp + 1);
				printf("!\n");
				print = 0;
				break;
			/*
				Delete an entry
			*/
			case 'd':
				print = 0;
				k = 0;
				if (strncmp("dq", resp, 2) != SAME &&
					strncmp("dp", resp, 2) != SAME)
					if ((k = getnumbr(resp+1)) == -1) break;
				if (k == 0) {
					k = showlet;
					if (!validmsg(curlet)) break;
					print = 1;
					curlet++;
				} else	k--;

				setletr(k, 'd');
				if (resp[1] == 'p') print = 1;
				else if (resp[1] == 'q') goto donep;
				break;
		}
	}
	/*
		Copy updated mailfile back
	*/
donep:
	if (changed) {
		copyback();
		stamp();
	}
}
