xref: /titanic_52/usr/src/cmd/mail/gethead.c (revision 1a7c1b724419d3cb5fa6eea75123c6b2060ba31b)
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  */
66 int
67 gethead(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 
202 void
203 tmperr()
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  */
213 wtmpf(str, length)
214 char	*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  */
227 int
228 getline(ptr2line, max, f)
229 char *ptr2line;
230 int max;
231 FILE	*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  */
243 void
244 mktmp()
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  */
260 getnumbr(s)
261 char	*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  */
286 validmsg(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  */
298 void
299 setletr(letter, status)
300 int	letter;
301 int	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