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