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