1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifdef notdef 14 static char sccsid[] = "@(#)head.c 5.4 (Berkeley) 02/18/88"; 15 #endif /* notdef */ 16 17 #include "rcv.h" 18 19 /* 20 * Mail -- a mail program 21 * 22 * Routines for processing and detecting headlines. 23 */ 24 25 /* 26 * See if the passed line buffer is a mail header. 27 * Return true if yes. Note the extreme pains to 28 * accomodate all funny formats. 29 */ 30 ishead(linebuf) 31 char linebuf[]; 32 { 33 register char *cp; 34 struct headline hl; 35 char parbuf[BUFSIZ]; 36 37 cp = linebuf; 38 if (*cp++ != 'F' || *cp++ != 'r' || *cp++ != 'o' || *cp++ != 'm' || 39 *cp++ != ' ') 40 return (0); 41 parse(linebuf, &hl, parbuf); 42 if (hl.l_from == NOSTR || hl.l_date == NOSTR) { 43 fail(linebuf, "No from or date field"); 44 return (0); 45 } 46 if (!isdate(hl.l_date)) { 47 fail(linebuf, "Date field not legal date"); 48 return (0); 49 } 50 /* 51 * I guess we got it! 52 */ 53 return (1); 54 } 55 56 /*ARGSUSED*/ 57 fail(linebuf, reason) 58 char linebuf[], reason[]; 59 { 60 61 /* 62 if (value("debug") == NOSTR) 63 return; 64 fprintf(stderr, "\"%s\"\nnot a header because %s\n", linebuf, reason); 65 */ 66 } 67 68 /* 69 * Split a headline into its useful components. 70 * Copy the line into dynamic string space, then set 71 * pointers into the copied line in the passed headline 72 * structure. Actually, it scans. 73 */ 74 parse(line, hl, pbuf) 75 char line[], pbuf[]; 76 register struct headline *hl; 77 { 78 register char *cp; 79 char *sp; 80 char word[LINESIZE]; 81 82 hl->l_from = NOSTR; 83 hl->l_tty = NOSTR; 84 hl->l_date = NOSTR; 85 cp = line; 86 sp = pbuf; 87 /* 88 * Skip over "From" first. 89 */ 90 cp = nextword(cp, word); 91 cp = nextword(cp, word); 92 if (*word) 93 hl->l_from = copyin(word, &sp); 94 if (cp != NOSTR && cp[0] == 't' && cp[1] == 't' && cp[2] == 'y') { 95 cp = nextword(cp, word); 96 hl->l_tty = copyin(word, &sp); 97 } 98 if (cp != NOSTR) 99 hl->l_date = copyin(cp, &sp); 100 } 101 102 /* 103 * Copy the string on the left into the string on the right 104 * and bump the right (reference) string pointer by the length. 105 * Thus, dynamically allocate space in the right string, copying 106 * the left string into it. 107 */ 108 char * 109 copyin(src, space) 110 register char *src; 111 char **space; 112 { 113 register char *cp; 114 char *top; 115 116 top = cp = *space; 117 while (*cp++ = *src++) 118 ; 119 *space = cp; 120 return (top); 121 } 122 123 /* 124 * Test to see if the passed string is a ctime(3) generated 125 * date string as documented in the manual. The template 126 * below is used as the criterion of correctness. 127 * Also, we check for a possible trailing time zone using 128 * the auxtype template. 129 */ 130 131 #define L 1 /* A lower case char */ 132 #define S 2 /* A space */ 133 #define D 3 /* A digit */ 134 #define O 4 /* An optional digit or space */ 135 #define C 5 /* A colon */ 136 #define N 6 /* A new line */ 137 #define U 7 /* An upper case char */ 138 139 char ctypes[] = { U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0 }; 140 char tmztypes[] = { U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0 }; 141 142 isdate(date) 143 char date[]; 144 { 145 146 if (cmatch(date, ctypes)) 147 return (1); 148 return (cmatch(date, tmztypes)); 149 } 150 151 /* 152 * Match the given string (cp) against the given template (tp). 153 * Return 1 if they match, 0 if they don't 154 */ 155 156 cmatch(cp, tp) 157 register char *cp, *tp; 158 { 159 160 while (*cp && *tp) 161 switch (*tp++) { 162 case L: 163 if (!islower(*cp++)) 164 return 0; 165 break; 166 case U: 167 if (!isupper(*cp++)) 168 return 0; 169 break; 170 case S: 171 if (*cp++ != ' ') 172 return 0; 173 break; 174 case D: 175 if (!isdigit(*cp++)) 176 return 0; 177 break; 178 case O: 179 if (*cp != ' ' && !isdigit(*cp)) 180 return 0; 181 cp++; 182 break; 183 case C: 184 if (*cp++ != ':') 185 return 0; 186 break; 187 case N: 188 if (*cp++ != '\n') 189 return 0; 190 break; 191 } 192 if (*cp || *tp) 193 return 0; 194 return (1); 195 } 196 197 /* 198 * Collect a liberal (space, tab delimited) word into the word buffer 199 * passed. Also, return a pointer to the next word following that, 200 * or NOSTR if none follow. 201 */ 202 char * 203 nextword(wp, wbuf) 204 register char *wp, *wbuf; 205 { 206 register c; 207 208 if (wp == NOSTR) { 209 *wbuf = 0; 210 return (NOSTR); 211 } 212 while ((c = *wp++) && c != ' ' && c != '\t') { 213 *wbuf++ = c; 214 if (c == '"') { 215 while ((c = *wp++) && c != '"') 216 *wbuf++ = c; 217 if (c == '"') 218 *wbuf++ = c; 219 else 220 wp--; 221 } 222 } 223 *wbuf = '\0'; 224 for (; c == ' ' || c == '\t'; c = *wp++) 225 ; 226 if (c == 0) 227 return (NOSTR); 228 return (wp - 1); 229 } 230 231 /* 232 * Is c contained in s? 233 */ 234 any(c, s) 235 register c; 236 register char *s; 237 { 238 239 while (*s) 240 if (*s++ == c) 241 return 1; 242 return 0; 243 } 244