|
|
1.1 ! root 1: # ! 2: ! 3: #include "rcv.h" ! 4: ! 5: /* ! 6: * Mail -- a mail program ! 7: * ! 8: * Routines for processing and detecting headlines. ! 9: */ ! 10: ! 11: /* ! 12: * See if the passed line buffer is a mail header. ! 13: * Return true if yes. Note the extreme pains to ! 14: * accomodate all funny formats. ! 15: */ ! 16: ! 17: ishead(linebuf) ! 18: char linebuf[]; ! 19: { ! 20: register char *cp; ! 21: struct headline hl; ! 22: char parbuf[BUFSIZ]; ! 23: ! 24: cp = linebuf; ! 25: if (!isname("From ", cp, 5)) ! 26: return(0); ! 27: parse(cp, &hl, parbuf); ! 28: if (hl.l_from == NOSTR || hl.l_date == NOSTR) { ! 29: fail(linebuf, "No from or date field"); ! 30: return(0); ! 31: } ! 32: if (!isdate(hl.l_date)) { ! 33: fail(linebuf, "Date field not legal date"); ! 34: return(0); ! 35: } ! 36: ! 37: /* ! 38: * I guess we got it! ! 39: */ ! 40: ! 41: return(1); ! 42: } ! 43: ! 44: fail(linebuf, reason) ! 45: char linebuf[], reason[]; ! 46: { ! 47: ! 48: if (1 /*value("debug") == NOSTR*/) ! 49: return; ! 50: fprintf(stderr, "\"%s\"\nnot a header because %s\n", linebuf, reason); ! 51: } ! 52: ! 53: /* ! 54: * Split a headline into its useful components. ! 55: * Copy the line into dynamic string space, then set ! 56: * pointers into the copied line in the passed headline ! 57: * structure. Actually, it scans. ! 58: */ ! 59: ! 60: parse(line, hl, pbuf) ! 61: char line[], pbuf[]; ! 62: struct headline *hl; ! 63: { ! 64: register char *cp, *dp; ! 65: char *sp; ! 66: char word[LINESIZE]; ! 67: ! 68: hl->l_from = NOSTR; ! 69: hl->l_tty = NOSTR; ! 70: hl->l_date = NOSTR; ! 71: cp = line; ! 72: sp = pbuf; ! 73: ! 74: /* ! 75: * Skip the first "word" of the line, which should be "From" ! 76: * anyway. ! 77: */ ! 78: ! 79: cp = nextword(cp, word); ! 80: dp = nextword(cp, word); ! 81: if (!equal(word, "")) ! 82: hl->l_from = copyin(word, &sp); ! 83: if (isname(dp, "tty", 3)) { ! 84: cp = nextword(dp, word); ! 85: hl->l_tty = copyin(word, &sp); ! 86: if (cp != NOSTR) ! 87: hl->l_date = copyin(cp, &sp); ! 88: } ! 89: else ! 90: if (dp != NOSTR) ! 91: hl->l_date = copyin(dp, &sp); ! 92: } ! 93: ! 94: /* ! 95: * Copy the string on the left into the string on the right ! 96: * and bump the right (reference) string pointer by the length. ! 97: * Thus, dynamically allocate space in the right string, copying ! 98: * the left string into it. ! 99: */ ! 100: ! 101: char * ! 102: copyin(src, space) ! 103: char src[]; ! 104: char **space; ! 105: { ! 106: register char *cp, *top; ! 107: register int s; ! 108: ! 109: s = strlen(src); ! 110: cp = *space; ! 111: top = cp; ! 112: strcpy(cp, src); ! 113: cp += s + 1; ! 114: *space = cp; ! 115: return(top); ! 116: } ! 117: ! 118: /* ! 119: * See if the two passed strings agree in the first n characters. ! 120: * Return true if they do, gnu. ! 121: */ ! 122: ! 123: isname(as1, as2, acount) ! 124: char *as1, *as2; ! 125: { ! 126: register char *s1, *s2; ! 127: register count; ! 128: ! 129: s1 = as1; ! 130: s2 = as2; ! 131: count = acount; ! 132: if (count > 0) ! 133: do ! 134: if (*s1++ != *s2++) ! 135: return(0); ! 136: while (--count); ! 137: return(1); ! 138: } ! 139: ! 140: /* ! 141: * Test to see if the passed string is a ctime(3) generated ! 142: * date string as documented in the manual. The template ! 143: * below is used as the criterion of correctness. ! 144: * Also, we check for a possible trailing time zone using ! 145: * the auxtype template. ! 146: */ ! 147: ! 148: #define L 1 /* A lower case char */ ! 149: #define S 2 /* A space */ ! 150: #define D 3 /* A digit */ ! 151: #define O 4 /* An optional digit or space */ ! 152: #define C 5 /* A colon */ ! 153: #define N 6 /* A new line */ ! 154: #define U 7 /* An upper case char */ ! 155: ! 156: 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}; ! 157: 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}; ! 158: ! 159: isdate(date) ! 160: char date[]; ! 161: { ! 162: register char *cp; ! 163: ! 164: cp = date; ! 165: if (cmatch(cp, ctypes)) ! 166: return(1); ! 167: return(cmatch(cp, tmztypes)); ! 168: } ! 169: ! 170: /* ! 171: * Match the given string against the given template. ! 172: * Return 1 if they match, 0 if they don't ! 173: */ ! 174: ! 175: cmatch(str, temp) ! 176: char str[], temp[]; ! 177: { ! 178: register char *cp, *tp; ! 179: register int c; ! 180: ! 181: cp = str; ! 182: tp = temp; ! 183: while (*cp != '\0' && *tp != 0) { ! 184: c = *cp++; ! 185: switch (*tp++) { ! 186: case L: ! 187: if (c < 'a' || c > 'z') ! 188: return(0); ! 189: break; ! 190: ! 191: case U: ! 192: if (c < 'A' || c > 'Z') ! 193: return(0); ! 194: break; ! 195: ! 196: case S: ! 197: if (c != ' ') ! 198: return(0); ! 199: break; ! 200: ! 201: case D: ! 202: if (!isdigit(c)) ! 203: return(0); ! 204: break; ! 205: ! 206: case O: ! 207: if (c != ' ' && !isdigit(c)) ! 208: return(0); ! 209: break; ! 210: ! 211: case C: ! 212: if (c != ':') ! 213: return(0); ! 214: break; ! 215: ! 216: case N: ! 217: if (c != '\n') ! 218: return(0); ! 219: break; ! 220: } ! 221: } ! 222: if (*cp != '\0' || *tp != 0) ! 223: return(0); ! 224: return(1); ! 225: } ! 226: ! 227: /* ! 228: * Collect a liberal (space, tab delimited) word into the word buffer ! 229: * passed. Also, return a pointer to the next word following that, ! 230: * or NOSTR if none follow. ! 231: */ ! 232: ! 233: char * ! 234: nextword(wp, wbuf) ! 235: char wp[], wbuf[]; ! 236: { ! 237: register char *cp, *cp2; ! 238: ! 239: if ((cp = wp) == NOSTR) { ! 240: copy("", wbuf); ! 241: return(NOSTR); ! 242: } ! 243: cp2 = wbuf; ! 244: while (!any(*cp, " \t") && *cp != '\0') ! 245: *cp2++ = *cp++; ! 246: *cp2 = '\0'; ! 247: while (any(*cp, " \t")) ! 248: cp++; ! 249: if (*cp == '\0') ! 250: return(NOSTR); ! 251: return(cp); ! 252: } ! 253: ! 254: /* ! 255: * Test to see if the character is an ascii alphabetic. ! 256: */ ! 257: ! 258: isalpha(c) ! 259: { ! 260: register int ch; ! 261: ! 262: ch = raise(c); ! 263: return(ch >= 'A' && ch <= 'Z'); ! 264: } ! 265: ! 266: /* ! 267: * Test to see if the character is an ascii digit. ! 268: */ ! 269: ! 270: isdigit(c) ! 271: { ! 272: return(c >= '0' && c <= '9'); ! 273: } ! 274: ! 275: /* ! 276: * Copy str1 to str2, return pointer to null in str2. ! 277: */ ! 278: ! 279: char * ! 280: copy(str1, str2) ! 281: char *str1, *str2; ! 282: { ! 283: register char *s1, *s2; ! 284: ! 285: s1 = str1; ! 286: s2 = str2; ! 287: while (*s1) ! 288: *s2++ = *s1++; ! 289: *s2 = 0; ! 290: return(s2); ! 291: } ! 292: ! 293: /* ! 294: * Is ch any of the characters in str? ! 295: */ ! 296: ! 297: any(ch, str) ! 298: char *str; ! 299: { ! 300: register char *f; ! 301: register c; ! 302: ! 303: f = str; ! 304: c = ch; ! 305: while (*f) ! 306: if (c == *f++) ! 307: return(1); ! 308: return(0); ! 309: } ! 310: ! 311: /* ! 312: * Convert lower case letters to upper case. ! 313: */ ! 314: ! 315: raise(c) ! 316: register int c; ! 317: { ! 318: if (c >= 'a' && c <= 'z') ! 319: c += 'A' - 'a'; ! 320: return(c); ! 321: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.