gethead.c revision 23a1ccea6aac035f084a7a4cdc968687d1b02daf
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27/*	  All Rights Reserved  	*/
28
29#include "mail.h"
30
31#define	MAXHDRSIZE	100	/* Maximum length of header line */
32#define	MAXUNAME	20	/* Maximum length of user name */
33
34/*
35 *	display headers, indicating current and status
36 *
37 *	current is the displacement into the mailfile of the
38 *	current letter
39 *
40 *	all indicates how many headers should be shown.
41 *		0	->	show window +/-6 around current
42 *		1	->	show all messages
43 *		2	->	show deleted messages
44 *
45 *	Only 100 characters of the From (first) header line will
46 *	be read in.  This line is assumed to be in the following
47 *	format:
48 *		From <sender address> <date>
49 *	where
50 *		<sender address> is either a UUCP-style (sysa!sysb!user)
51 *		or domain-style address (user@host).
52 *
53 *	If the sender address contains a UUCP-style address, then
54 *	the user name displayed is made up of the characters following
55 *	the final '!' in the sender address, otherwise the sender
56 *	address is considered to be the user name.
57 *
58 *	The maximum number of characters of a user name displayed
59 *	is 19.
60 *
61 */
62int
63gethead(int current, int all)
64{
65
66	int	displayed = 0;
67	FILE	*file;
68	char	*hold;
69	char	holdval[MAXHDRSIZE];
70	char	*wline;
71	char	wlineval[MAXHDRSIZE];
72	int	ln;
73	char	mark;
74	int	rc, size, start, stop, ix;
75	char	userval[MAXUNAME];
76	char	*uucpptr;
77	int	uucpstart;
78	int	unamechars = MAXUNAME - 1;
79	int	sender_size;
80
81	hold = holdval;
82	wline = wlineval;
83
84	printf("%d letters found in %s, %d scheduled for deletion, "
85	    "%d newly arrived\n", nlet, mailfile, changed, nlet - onlet);
86
87	if (all == 2 && !changed)
88		return (0);
89
90	file = doopen(lettmp, "r", E_TMP);
91	if (!flgr) {
92		stop = current - 6;
93		if (stop < -1) stop = -1;
94		start = current + 5;
95		if (start > nlet - 1) start = nlet - 1;
96		if (all) {
97			start = nlet -1;
98			stop = -1;
99		}
100	} else {
101		stop = current + 6;
102		if (stop > nlet) stop = nlet;
103		start = current - 5;
104		if (start < 0) start = 0;
105		if (all) {
106			start = 0;
107			stop = nlet;
108		}
109	}
110	for (ln = start; ln != stop; ln = flgr ? ln + 1 : ln - 1) {
111		size = let[ln+1].adr - let[ln].adr;
112		if ((rc = fseek(file, let[ln].adr, 0)) != 0) {
113			errmsg(E_FILE, "Cannot seek header");
114			fclose(file);
115			return (1);
116		}
117		if (fgets(wline, MAXHDRSIZE, file) == NULL) {
118			errmsg(E_FILE, "Cannot read header");
119			fclose(file);
120			return (1);
121		}
122		if ((rc = strncmp(wline, header[H_FROM].tag, 5)) != SAME) {
123			errmsg(E_FILE, "Invalid header encountered");
124			fclose(file);
125			return (1);
126		}
127
128		/* skip past trailing white space after header tag */
129		for (rc = 5; wline[rc] == ' ' || wline[rc] == '\t'; ++rc)
130			;
131		(void) strlcpy(hold, wline + rc, MAXHDRSIZE);
132		fgets(wline, MAXHDRSIZE, file);
133
134		while (((rc = strncmp(wline,
135		    header[H_FROM1].tag, 6)) == SAME) &&
136		    (substr(wline, "remote from ") != -1)) {
137			(void) strlcpy(hold, wline + 6, MAXHDRSIZE);
138			fgets(wline, MAXHDRSIZE, file);
139		}
140
141
142		/*
143		 * If UUCP-style sender address, then read past
144		 * last "!" to get the start of the user name.
145		 */
146		sender_size = strcspn(hold, " \t");
147		uucpstart = 0;
148		if ((uucpptr = strrchr(hold, '!')) != NULL) {
149			uucpstart = uucpptr - hold + 1;
150			if (uucpstart > sender_size) {
151				uucpstart = 0;
152			}
153		}
154
155		/* Get the user name out of the sender address. */
156		for (ix = 0, rc = uucpstart; ix < unamechars &&
157		    hold[rc] != ' ' && hold[rc] != '\t' &&
158		    rc < sender_size; ++rc) {
159			userval[ix++] = hold[rc];
160		}
161		if ((ix > 0) && (userval[ix - 1] == '\n')) {
162			userval[ix - 1] = '\0';
163		} else {
164			userval[ix] = '\0';
165		}
166
167		/*
168		 * Skip past the rest of the sender address, and
169		 * delimiting white space.
170		 */
171		for (; hold[rc] != '\0' && hold[rc] != ' ' &&
172		    hold[rc] != '\t'; ++rc)
173			;
174		for (; hold[rc] == ' ' || hold[rc] == '\t'; ++rc)
175			;
176
177		/* Get the date information. */
178		(void) strlcpy(wline, hold + rc, MAXHDRSIZE);
179		for (rc = 0; wline[rc] != '\0' && wline[rc] != '\n'; ++rc)
180			;
181		wline[rc] = '\0';
182
183		if (!flgh && current == ln) mark = '>';
184		else mark = ' ';
185
186		if (all == 2) {
187			if (displayed >= changed) {
188				fclose(file);
189				return (0);
190			}
191			if (let[ln].change == ' ') continue;
192		}
193
194		printf("%c %3d  %c  %-5d  %-10s  %s\n", mark, ln + 1,
195		    let[ln].change, size, userval, wline);
196		displayed++;
197	}
198	fclose(file);
199	return (0);
200}
201
202void
203tmperr(void)
204{
205	fclose(tmpf);
206	errmsg(E_TMP, "");
207}
208
209/*
210 *	Write a string out to tmp file, with error checking.
211 *	Return 1 on success, else 0
212 */
213int
214wtmpf(char *str, int length)
215{
216	if (fwrite(str, 1, length, tmpf) != length) {
217		tmperr();
218		return (0);
219	}
220	return (1);
221}
222
223/*
224 *	Read a line from stdin, assign it to line and
225 *	return number of bytes in length
226 */
227int
228getaline(char *ptr2line, int max, FILE *f)
229{
230	int	i, ch;
231	for (i = 0; i < max-1 && (ch = getc(f)) != EOF; )
232		if ((ptr2line[i++] = ch) == '\n') break;
233	ptr2line[i] = '\0';
234	return (i);
235}
236
237/*
238 *	Make temporary file for letter
239 */
240void
241mktmp(void)
242{
243	static char tmpl[] = "/var/tmp/mailXXXXXX";
244	int fd = mkstemp(lettmp = tmpl);
245
246	if (fd < 0 || (tmpf = fdopen(fd, "w+")) == NULL) {
247		fprintf(stderr,
248		    "%s: Can't open '%s', type: w+\n", program, lettmp);
249		done(0);
250	}
251}
252
253/*
254 * Get a number from user's reply,
255 * return its value or zero if none present, -1 on error
256 */
257int
258getnumbr(char *s)
259{
260	int	k = 0;
261
262	while (*s == ' ' || *s == '\t') s++;
263
264	if (*s != '\0') {
265		if ((k = atoi(s)) != 0)
266			if (!validmsg(k))
267				return (-1);
268
269		for (; *s >= '0' && *s <= '9'; ) s++;
270		if (*s != '\0' && *s != '\n') {
271			printf("Illegal numeric\n");
272			return (-1);
273		}
274		return (k);
275	}
276	return (0);
277}
278
279/*
280 *	If valid msgnum return 1,
281 *		else print message and return 0
282 */
283int
284validmsg(int i)
285{
286	if ((i < 0) || (i > nlet)) {
287		printf("No such message\n");
288		return (0);
289	}
290	return (1);
291}
292
293/*
294 *	Set letter to passed status, and adjust changed as necessary
295 */
296void
297setletr(int letter, int status)
298{
299	if (status == ' ') {
300		if (let[letter].change != ' ')
301			if (changed) changed--;
302	} else {
303		if (let[letter].change == ' ') changed++;
304	}
305	let[letter].change = status;
306}
307