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 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 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 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 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 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 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 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 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