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 */
62 int
gethead(int current,int all)63 gethead(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
202 void
tmperr(void)203 tmperr(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 */
213 int
wtmpf(char * str,int length)214 wtmpf(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 */
227 int
getaline(char * ptr2line,int max,FILE * f)228 getaline(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 */
240 void
mktmp(void)241 mktmp(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 */
257 int
getnumbr(char * s)258 getnumbr(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 */
283 int
validmsg(int i)284 validmsg(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 */
296 void
setletr(int letter,int status)297 setletr(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