xref: /illumos-gate/usr/src/cmd/mail/gethead.c (revision 6a634c9d)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*23a1cceaSRoger A. Faulkner  * Common Development and Distribution License (the "License").
6*23a1cceaSRoger A. Faulkner  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*23a1cceaSRoger A. Faulkner 
227c478bd9Sstevel@tonic-gate /*
23*23a1cceaSRoger A. Faulkner  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
26b7d62af5Sceastha /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27b7d62af5Sceastha /*	  All Rights Reserved  	*/
28b7d62af5Sceastha 
297c478bd9Sstevel@tonic-gate #include "mail.h"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #define	MAXHDRSIZE	100	/* Maximum length of header line */
327c478bd9Sstevel@tonic-gate #define	MAXUNAME	20	/* Maximum length of user name */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate  *	display headers, indicating current and status
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  *	current is the displacement into the mailfile of the
387c478bd9Sstevel@tonic-gate  *	current letter
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  *	all indicates how many headers should be shown.
417c478bd9Sstevel@tonic-gate  *		0	->	show window +/-6 around current
427c478bd9Sstevel@tonic-gate  *		1	->	show all messages
437c478bd9Sstevel@tonic-gate  *		2	->	show deleted messages
447c478bd9Sstevel@tonic-gate  *
457c478bd9Sstevel@tonic-gate  *	Only 100 characters of the From (first) header line will
467c478bd9Sstevel@tonic-gate  *	be read in.  This line is assumed to be in the following
477c478bd9Sstevel@tonic-gate  *	format:
487c478bd9Sstevel@tonic-gate  *		From <sender address> <date>
497c478bd9Sstevel@tonic-gate  *	where
507c478bd9Sstevel@tonic-gate  *		<sender address> is either a UUCP-style (sysa!sysb!user)
517c478bd9Sstevel@tonic-gate  *		or domain-style address (user@host).
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  *	If the sender address contains a UUCP-style address, then
547c478bd9Sstevel@tonic-gate  *	the user name displayed is made up of the characters following
557c478bd9Sstevel@tonic-gate  *	the final '!' in the sender address, otherwise the sender
567c478bd9Sstevel@tonic-gate  *	address is considered to be the user name.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  *	The maximum number of characters of a user name displayed
597c478bd9Sstevel@tonic-gate  *	is 19.
607c478bd9Sstevel@tonic-gate  *
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate int
gethead(int current,int all)637c478bd9Sstevel@tonic-gate gethead(int current, int all)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	int	displayed = 0;
677c478bd9Sstevel@tonic-gate 	FILE	*file;
687c478bd9Sstevel@tonic-gate 	char	*hold;
697c478bd9Sstevel@tonic-gate 	char	holdval[MAXHDRSIZE];
707c478bd9Sstevel@tonic-gate 	char	*wline;
717c478bd9Sstevel@tonic-gate 	char	wlineval[MAXHDRSIZE];
727c478bd9Sstevel@tonic-gate 	int	ln;
737c478bd9Sstevel@tonic-gate 	char	mark;
747c478bd9Sstevel@tonic-gate 	int	rc, size, start, stop, ix;
757c478bd9Sstevel@tonic-gate 	char	userval[MAXUNAME];
767c478bd9Sstevel@tonic-gate 	char	*uucpptr;
777c478bd9Sstevel@tonic-gate 	int	uucpstart;
787c478bd9Sstevel@tonic-gate 	int	unamechars = MAXUNAME - 1;
797c478bd9Sstevel@tonic-gate 	int	sender_size;
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	hold = holdval;
827c478bd9Sstevel@tonic-gate 	wline = wlineval;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	printf("%d letters found in %s, %d scheduled for deletion, "
857c478bd9Sstevel@tonic-gate 	    "%d newly arrived\n", nlet, mailfile, changed, nlet - onlet);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	if (all == 2 && !changed)
887c478bd9Sstevel@tonic-gate 		return (0);
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	file = doopen(lettmp, "r", E_TMP);
917c478bd9Sstevel@tonic-gate 	if (!flgr) {
927c478bd9Sstevel@tonic-gate 		stop = current - 6;
937c478bd9Sstevel@tonic-gate 		if (stop < -1) stop = -1;
947c478bd9Sstevel@tonic-gate 		start = current + 5;
957c478bd9Sstevel@tonic-gate 		if (start > nlet - 1) start = nlet - 1;
967c478bd9Sstevel@tonic-gate 		if (all) {
977c478bd9Sstevel@tonic-gate 			start = nlet -1;
987c478bd9Sstevel@tonic-gate 			stop = -1;
997c478bd9Sstevel@tonic-gate 		}
1007c478bd9Sstevel@tonic-gate 	} else {
1017c478bd9Sstevel@tonic-gate 		stop = current + 6;
1027c478bd9Sstevel@tonic-gate 		if (stop > nlet) stop = nlet;
1037c478bd9Sstevel@tonic-gate 		start = current - 5;
1047c478bd9Sstevel@tonic-gate 		if (start < 0) start = 0;
1057c478bd9Sstevel@tonic-gate 		if (all) {
1067c478bd9Sstevel@tonic-gate 			start = 0;
1077c478bd9Sstevel@tonic-gate 			stop = nlet;
1087c478bd9Sstevel@tonic-gate 		}
1097c478bd9Sstevel@tonic-gate 	}
1107c478bd9Sstevel@tonic-gate 	for (ln = start; ln != stop; ln = flgr ? ln + 1 : ln - 1) {
1117c478bd9Sstevel@tonic-gate 		size = let[ln+1].adr - let[ln].adr;
1127c478bd9Sstevel@tonic-gate 		if ((rc = fseek(file, let[ln].adr, 0)) != 0) {
1137c478bd9Sstevel@tonic-gate 			errmsg(E_FILE, "Cannot seek header");
1147c478bd9Sstevel@tonic-gate 			fclose(file);
1157c478bd9Sstevel@tonic-gate 			return (1);
1167c478bd9Sstevel@tonic-gate 		}
1177c478bd9Sstevel@tonic-gate 		if (fgets(wline, MAXHDRSIZE, file) == NULL) {
1187c478bd9Sstevel@tonic-gate 			errmsg(E_FILE, "Cannot read header");
1197c478bd9Sstevel@tonic-gate 			fclose(file);
1207c478bd9Sstevel@tonic-gate 			return (1);
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 		if ((rc = strncmp(wline, header[H_FROM].tag, 5)) != SAME) {
1237c478bd9Sstevel@tonic-gate 			errmsg(E_FILE, "Invalid header encountered");
1247c478bd9Sstevel@tonic-gate 			fclose(file);
1257c478bd9Sstevel@tonic-gate 			return (1);
1267c478bd9Sstevel@tonic-gate 		}
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 		/* skip past trailing white space after header tag */
129*23a1cceaSRoger A. Faulkner 		for (rc = 5; wline[rc] == ' ' || wline[rc] == '\t'; ++rc)
130*23a1cceaSRoger A. Faulkner 			;
1317c478bd9Sstevel@tonic-gate 		(void) strlcpy(hold, wline + rc, MAXHDRSIZE);
1327c478bd9Sstevel@tonic-gate 		fgets(wline, MAXHDRSIZE, file);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 		while (((rc = strncmp(wline,
1357c478bd9Sstevel@tonic-gate 		    header[H_FROM1].tag, 6)) == SAME) &&
1367c478bd9Sstevel@tonic-gate 		    (substr(wline, "remote from ") != -1)) {
1377c478bd9Sstevel@tonic-gate 			(void) strlcpy(hold, wline + 6, MAXHDRSIZE);
1387c478bd9Sstevel@tonic-gate 			fgets(wline, MAXHDRSIZE, file);
1397c478bd9Sstevel@tonic-gate 		}
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 		/*
1437c478bd9Sstevel@tonic-gate 		 * If UUCP-style sender address, then read past
1447c478bd9Sstevel@tonic-gate 		 * last "!" to get the start of the user name.
1457c478bd9Sstevel@tonic-gate 		 */
1467c478bd9Sstevel@tonic-gate 		sender_size = strcspn(hold, " \t");
1477c478bd9Sstevel@tonic-gate 		uucpstart = 0;
1487c478bd9Sstevel@tonic-gate 		if ((uucpptr = strrchr(hold, '!')) != NULL) {
1497c478bd9Sstevel@tonic-gate 			uucpstart = uucpptr - hold + 1;
1507c478bd9Sstevel@tonic-gate 			if (uucpstart > sender_size) {
1517c478bd9Sstevel@tonic-gate 				uucpstart = 0;
1527c478bd9Sstevel@tonic-gate 			}
1537c478bd9Sstevel@tonic-gate 		}
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 		/* Get the user name out of the sender address. */
1567c478bd9Sstevel@tonic-gate 		for (ix = 0, rc = uucpstart; ix < unamechars &&
1577c478bd9Sstevel@tonic-gate 		    hold[rc] != ' ' && hold[rc] != '\t' &&
1587c478bd9Sstevel@tonic-gate 		    rc < sender_size; ++rc) {
1597c478bd9Sstevel@tonic-gate 			userval[ix++] = hold[rc];
1607c478bd9Sstevel@tonic-gate 		}
1617c478bd9Sstevel@tonic-gate 		if ((ix > 0) && (userval[ix - 1] == '\n')) {
1627c478bd9Sstevel@tonic-gate 			userval[ix - 1] = '\0';
1637c478bd9Sstevel@tonic-gate 		} else {
1647c478bd9Sstevel@tonic-gate 			userval[ix] = '\0';
1657c478bd9Sstevel@tonic-gate 		}
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 		/*
1687c478bd9Sstevel@tonic-gate 		 * Skip past the rest of the sender address, and
1697c478bd9Sstevel@tonic-gate 		 * delimiting white space.
1707c478bd9Sstevel@tonic-gate 		 */
1717c478bd9Sstevel@tonic-gate 		for (; hold[rc] != '\0' && hold[rc] != ' ' &&
172*23a1cceaSRoger A. Faulkner 		    hold[rc] != '\t'; ++rc)
173*23a1cceaSRoger A. Faulkner 			;
174*23a1cceaSRoger A. Faulkner 		for (; hold[rc] == ' ' || hold[rc] == '\t'; ++rc)
175*23a1cceaSRoger A. Faulkner 			;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 		/* Get the date information. */
1787c478bd9Sstevel@tonic-gate 		(void) strlcpy(wline, hold + rc, MAXHDRSIZE);
179*23a1cceaSRoger A. Faulkner 		for (rc = 0; wline[rc] != '\0' && wline[rc] != '\n'; ++rc)
180*23a1cceaSRoger A. Faulkner 			;
1817c478bd9Sstevel@tonic-gate 		wline[rc] = '\0';
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 		if (!flgh && current == ln) mark = '>';
1847c478bd9Sstevel@tonic-gate 		else mark = ' ';
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 		if (all == 2) {
1877c478bd9Sstevel@tonic-gate 			if (displayed >= changed) {
1887c478bd9Sstevel@tonic-gate 				fclose(file);
1897c478bd9Sstevel@tonic-gate 				return (0);
1907c478bd9Sstevel@tonic-gate 			}
1917c478bd9Sstevel@tonic-gate 			if (let[ln].change == ' ') continue;
1927c478bd9Sstevel@tonic-gate 		}
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 		printf("%c %3d  %c  %-5d  %-10s  %s\n", mark, ln + 1,
1957c478bd9Sstevel@tonic-gate 		    let[ln].change, size, userval, wline);
1967c478bd9Sstevel@tonic-gate 		displayed++;
1977c478bd9Sstevel@tonic-gate 	}
1987c478bd9Sstevel@tonic-gate 	fclose(file);
1997c478bd9Sstevel@tonic-gate 	return (0);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate void
tmperr(void)203b7d62af5Sceastha tmperr(void)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate 	fclose(tmpf);
2067c478bd9Sstevel@tonic-gate 	errmsg(E_TMP, "");
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate  *	Write a string out to tmp file, with error checking.
2117c478bd9Sstevel@tonic-gate  *	Return 1 on success, else 0
2127c478bd9Sstevel@tonic-gate  */
213b7d62af5Sceastha int
wtmpf(char * str,int length)214b7d62af5Sceastha wtmpf(char *str, int length)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	if (fwrite(str, 1, length, tmpf) != length) {
2177c478bd9Sstevel@tonic-gate 		tmperr();
2187c478bd9Sstevel@tonic-gate 		return (0);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 	return (1);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate  *	Read a line from stdin, assign it to line and
2257c478bd9Sstevel@tonic-gate  *	return number of bytes in length
2267c478bd9Sstevel@tonic-gate  */
2277c478bd9Sstevel@tonic-gate int
getaline(char * ptr2line,int max,FILE * f)228*23a1cceaSRoger A. Faulkner getaline(char *ptr2line, int max, FILE *f)
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate 	int	i, ch;
2317c478bd9Sstevel@tonic-gate 	for (i = 0; i < max-1 && (ch = getc(f)) != EOF; )
2327c478bd9Sstevel@tonic-gate 		if ((ptr2line[i++] = ch) == '\n') break;
2337c478bd9Sstevel@tonic-gate 	ptr2line[i] = '\0';
2347c478bd9Sstevel@tonic-gate 	return (i);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate  *	Make temporary file for letter
2397c478bd9Sstevel@tonic-gate  */
2407c478bd9Sstevel@tonic-gate void
mktmp(void)241b7d62af5Sceastha mktmp(void)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 	static char tmpl[] = "/var/tmp/mailXXXXXX";
2447c478bd9Sstevel@tonic-gate 	int fd = mkstemp(lettmp = tmpl);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	if (fd < 0 || (tmpf = fdopen(fd, "w+")) == NULL) {
247*23a1cceaSRoger A. Faulkner 		fprintf(stderr,
2487c478bd9Sstevel@tonic-gate 		    "%s: Can't open '%s', type: w+\n", program, lettmp);
249*23a1cceaSRoger A. Faulkner 		done(0);
2507c478bd9Sstevel@tonic-gate 	}
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate /*
2547c478bd9Sstevel@tonic-gate  * Get a number from user's reply,
2557c478bd9Sstevel@tonic-gate  * return its value or zero if none present, -1 on error
2567c478bd9Sstevel@tonic-gate  */
257b7d62af5Sceastha int
getnumbr(char * s)258b7d62af5Sceastha getnumbr(char *s)
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate 	int	k = 0;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	while (*s == ' ' || *s == '\t') s++;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	if (*s != '\0') {
2657c478bd9Sstevel@tonic-gate 		if ((k = atoi(s)) != 0)
2667c478bd9Sstevel@tonic-gate 			if (!validmsg(k))
2677c478bd9Sstevel@tonic-gate 				return (-1);
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 		for (; *s >= '0' && *s <= '9'; ) s++;
2707c478bd9Sstevel@tonic-gate 		if (*s != '\0' && *s != '\n') {
2717c478bd9Sstevel@tonic-gate 			printf("Illegal numeric\n");
2727c478bd9Sstevel@tonic-gate 			return (-1);
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 		return (k);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 	return (0);
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate /*
2807c478bd9Sstevel@tonic-gate  *	If valid msgnum return 1,
2817c478bd9Sstevel@tonic-gate  *		else print message and return 0
2827c478bd9Sstevel@tonic-gate  */
283b7d62af5Sceastha int
validmsg(int i)284b7d62af5Sceastha validmsg(int i)
2857c478bd9Sstevel@tonic-gate {
2867c478bd9Sstevel@tonic-gate 	if ((i < 0) || (i > nlet)) {
2877c478bd9Sstevel@tonic-gate 		printf("No such message\n");
2887c478bd9Sstevel@tonic-gate 		return (0);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 	return (1);
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate  *	Set letter to passed status, and adjust changed as necessary
2957c478bd9Sstevel@tonic-gate  */
2967c478bd9Sstevel@tonic-gate void
setletr(int letter,int status)297b7d62af5Sceastha setletr(int letter, int status)
2987c478bd9Sstevel@tonic-gate {
2997c478bd9Sstevel@tonic-gate 	if (status == ' ') {
3007c478bd9Sstevel@tonic-gate 		if (let[letter].change != ' ')
3017c478bd9Sstevel@tonic-gate 			if (changed) changed--;
3027c478bd9Sstevel@tonic-gate 	} else {
3037c478bd9Sstevel@tonic-gate 		if (let[letter].change == ' ') changed++;
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 	let[letter].change = status;
3067c478bd9Sstevel@tonic-gate }
307