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