|
|
1.1 ! root 1: # ! 2: ! 3: #include "rcv.h" ! 4: #include <sys/stat.h> ! 5: #include <sgtty.h> ! 6: #include <ctype.h> ! 7: ! 8: /* ! 9: * Mail -- a mail program ! 10: * ! 11: * Auxiliary functions. ! 12: */ ! 13: ! 14: /* ! 15: * Return a pointer to a dynamic copy of the argument. ! 16: */ ! 17: ! 18: char * ! 19: savestr(str) ! 20: char *str; ! 21: { ! 22: register char *cp, *cp2, *top; ! 23: ! 24: for (cp = str; *cp; cp++) ! 25: ; ! 26: top = salloc(cp-str + 1); ! 27: if (top == NOSTR) ! 28: return(NOSTR); ! 29: for (cp = str, cp2 = top; *cp; cp++) ! 30: *cp2++ = *cp; ! 31: *cp2 = 0; ! 32: return(top); ! 33: } ! 34: ! 35: /* ! 36: * Copy the name from the passed header line into the passed ! 37: * name buffer. Null pad the name buffer. ! 38: */ ! 39: ! 40: copyname(linebuf, nbuf) ! 41: char *linebuf, *nbuf; ! 42: { ! 43: register char *cp, *cp2; ! 44: ! 45: for (cp = linebuf + 5, cp2 = nbuf; *cp != ' ' && cp2-nbuf < 8; cp++) ! 46: *cp2++ = *cp; ! 47: while (cp2-nbuf < 8) ! 48: *cp2++ = 0; ! 49: } ! 50: ! 51: /* ! 52: * Announce a fatal error and die. ! 53: */ ! 54: ! 55: panic(str) ! 56: char *str; ! 57: { ! 58: prs("panic: "); ! 59: prs(str); ! 60: prs("\n"); ! 61: exit(1); ! 62: } ! 63: ! 64: /* ! 65: * Catch stdio errors and report them more nicely. ! 66: */ ! 67: ! 68: _error(str) ! 69: char *str; ! 70: { ! 71: prs("Stdio Error: "); ! 72: prs(str); ! 73: prs("\n"); ! 74: abort(); ! 75: } ! 76: ! 77: /* ! 78: * Print a string on diagnostic output. ! 79: */ ! 80: ! 81: prs(str) ! 82: char *str; ! 83: { ! 84: register char *s; ! 85: ! 86: for (s = str; *s; s++) ! 87: ; ! 88: write(2, str, s-str); ! 89: } ! 90: ! 91: /* ! 92: * Touch the named message by setting its MTOUCH flag. ! 93: * Touched messages have the effect of not being sent ! 94: * back to the system mailbox on exit. ! 95: */ ! 96: ! 97: touch(mesg) ! 98: { ! 99: if (mesg >= 1 && mesg <= msgCount) ! 100: message[mesg-1].m_flag |= MTOUCH; ! 101: } ! 102: ! 103: /* ! 104: * Test to see if the passed file name is a directory. ! 105: * Return true if it is. ! 106: */ ! 107: ! 108: isdir(name) ! 109: char name[]; ! 110: { ! 111: struct stat sbuf; ! 112: ! 113: if (stat(name, &sbuf) < 0) ! 114: return(0); ! 115: return((sbuf.st_mode & S_IFMT) == S_IFDIR); ! 116: } ! 117: ! 118: /* ! 119: * Compute the size in characters of the passed message ! 120: */ ! 121: ! 122: unsigned int ! 123: msize(messp) ! 124: struct message *messp; ! 125: { ! 126: register struct message *mp; ! 127: ! 128: mp = messp; ! 129: return(mp->m_size); ! 130: } ! 131: ! 132: /* ! 133: * Count the number of arguments in the given string raw list. ! 134: */ ! 135: ! 136: argcount(argv) ! 137: char **argv; ! 138: { ! 139: register char **ap; ! 140: ! 141: for (ap = argv; *ap != NOSTR; ap++) ! 142: ; ! 143: return(ap-argv); ! 144: } ! 145: ! 146: /* ! 147: * Given a file address, determine the ! 148: * block number it represents. ! 149: */ ! 150: ! 151: blockof(off) ! 152: off_t off; ! 153: { ! 154: off_t a; ! 155: ! 156: a = off >> 9; ! 157: a &= 077777; ! 158: return((int) a); ! 159: } ! 160: ! 161: /* ! 162: * Take a file address, and determine ! 163: * its offset in the current block. ! 164: */ ! 165: ! 166: offsetof(off) ! 167: off_t off; ! 168: { ! 169: off_t a; ! 170: ! 171: a = off & 0777; ! 172: return((int) a); ! 173: } ! 174: ! 175: /* ! 176: * Determine if the passed file is actually a tty, via a call to ! 177: * gtty. This is not totally reliable, but . . . ! 178: */ ! 179: ! 180: isatty(f) ! 181: { ! 182: struct sgttyb buf; ! 183: ! 184: if (gtty(f, &buf) < 0) ! 185: return(0); ! 186: return(1); ! 187: } ! 188: ! 189: /* ! 190: * Return the desired header line from the passed message ! 191: * pointer (or NOSTR if the desired header field is not available). ! 192: */ ! 193: ! 194: char * ! 195: hfield(field, mp) ! 196: char field[]; ! 197: struct message *mp; ! 198: { ! 199: register FILE *ibuf; ! 200: char linebuf[LINESIZE]; ! 201: register int lc; ! 202: ! 203: ibuf = setinput(mp); ! 204: if ((lc = mp->m_lines) <= 0) ! 205: return(NOSTR); ! 206: if (readline(ibuf, linebuf) < 0) ! 207: return(NOSTR); ! 208: lc--; ! 209: do { ! 210: lc = gethfield(ibuf, linebuf, lc); ! 211: if (lc == -1) ! 212: return(NOSTR); ! 213: if (ishfield(linebuf, field)) ! 214: return(savestr(hcontents(linebuf))); ! 215: } while (lc > 0); ! 216: return(NOSTR); ! 217: } ! 218: ! 219: /* ! 220: * Return the next header field found in the given message. ! 221: * Return > 0 if something found, <= 0 elsewise. ! 222: * Must deal with \ continuations & other such fraud. ! 223: */ ! 224: ! 225: gethfield(f, linebuf, rem) ! 226: register FILE *f; ! 227: char linebuf[]; ! 228: register int rem; ! 229: { ! 230: char line2[LINESIZE]; ! 231: register char *cp, *cp2; ! 232: ! 233: for (;;) { ! 234: if (rem <= 0) ! 235: return(-1); ! 236: if (readline(f, linebuf) < 0) ! 237: return(-1); ! 238: rem--; ! 239: if (strlen(linebuf) == 0) ! 240: return(-1); ! 241: if (isspace(linebuf[0])) ! 242: return(-1); ! 243: if (linebuf[0] == '>') ! 244: continue; ! 245: cp = index(linebuf, ':'); ! 246: if (cp == NOSTR) ! 247: return(-1); ! 248: for (cp2 = linebuf; cp2 < cp; cp2++) ! 249: if (isdigit(*cp2)) ! 250: continue; ! 251: ! 252: /* ! 253: * I guess we got a headline. ! 254: * Handle \ wraparounding ! 255: */ ! 256: ! 257: for (;;) { ! 258: cp = &linebuf[strlen(linebuf) - 1]; ! 259: if (*cp != '\\') ! 260: break; ! 261: if (rem < 0) ! 262: break; ! 263: if (readline(f, line2) < 0) ! 264: break; ! 265: rem--; ! 266: if (strlen(linebuf) + strlen(line2) >= LINESIZE-2) ! 267: break; ! 268: if (cp > linebuf) ! 269: --cp; ! 270: if (!isspace(*cp)) ! 271: *++cp = ' '; ! 272: for (cp2 = line2; *cp2 != 0 && isspace(*cp2); cp2++) ! 273: ; ! 274: strcpy(++cp, cp2); ! 275: } ! 276: return(rem); ! 277: } ! 278: /* NOTREACHED */ ! 279: } ! 280: ! 281: /* ! 282: * Check whether the passed line is a header line of ! 283: * the desired breed. ! 284: */ ! 285: ! 286: ishfield(linebuf, field) ! 287: char linebuf[], field[]; ! 288: { ! 289: register char *cp; ! 290: register int c; ! 291: ! 292: if ((cp = index(linebuf, ':')) == NOSTR) ! 293: return(0); ! 294: if (cp == linebuf) ! 295: return(0); ! 296: cp--; ! 297: while (cp > linebuf && isspace(*cp)) ! 298: cp--; ! 299: c = *++cp; ! 300: *cp = 0; ! 301: if (icequal(linebuf ,field)) { ! 302: *cp = c; ! 303: return(1); ! 304: } ! 305: *cp = c; ! 306: return(0); ! 307: } ! 308: ! 309: /* ! 310: * Extract the non label information from the given header field ! 311: * and return it. ! 312: */ ! 313: ! 314: char * ! 315: hcontents(hfield) ! 316: char hfield[]; ! 317: { ! 318: register char *cp; ! 319: ! 320: if ((cp = index(hfield, ':')) == NOSTR) ! 321: return(NOSTR); ! 322: cp++; ! 323: while (*cp && isspace(*cp)) ! 324: cp++; ! 325: return(cp); ! 326: } ! 327: ! 328: /* ! 329: * Compare two strings, ignoring case. ! 330: */ ! 331: ! 332: icequal(s1, s2) ! 333: register char *s1, *s2; ! 334: { ! 335: ! 336: while (raise(*s1++) == raise(*s2)) ! 337: if (*s2++ == 0) ! 338: return(1); ! 339: return(0); ! 340: } ! 341: ! 342: /* ! 343: * The following code deals with input stacking to do source ! 344: * commands. All but the current file pointer are saved on ! 345: * the stack. ! 346: */ ! 347: ! 348: static int ssp = -1; /* Top of file stack */ ! 349: static FILE *sstack[_NFILE]; /* Saved input files */ ! 350: ! 351: /* ! 352: * Pushdown current input file and switch to a new one. ! 353: * Set the global flag "sourcing" so that others will realize ! 354: * that they are no longer reading from a tty (in all probability). ! 355: */ ! 356: ! 357: source(name) ! 358: char name[]; ! 359: { ! 360: register FILE *fi; ! 361: ! 362: if ((fi = fopen(name, "r")) == NULL) { ! 363: perror(name); ! 364: return(1); ! 365: } ! 366: if (ssp >= _NFILE-2) { ! 367: printf("Too much \"sourcing\" going on.\n"); ! 368: fclose(fi); ! 369: return(1); ! 370: } ! 371: sstack[++ssp] = input; ! 372: input = fi; ! 373: sourcing++; ! 374: return(0); ! 375: } ! 376: ! 377: /* ! 378: * Source a file, but do nothing if the file cannot be opened. ! 379: */ ! 380: ! 381: source1(name) ! 382: char name[]; ! 383: { ! 384: register int f; ! 385: ! 386: if ((f = open(name, 0)) < 0) ! 387: return(0); ! 388: close(f); ! 389: source(name); ! 390: } ! 391: ! 392: /* ! 393: * Pop the current input back to the previous level. ! 394: * Update the "sourcing" flag as appropriate. ! 395: */ ! 396: ! 397: unstack() ! 398: { ! 399: if (ssp < 0) { ! 400: printf("\"Source\" stack over-pop.\n"); ! 401: sourcing = 0; ! 402: return(1); ! 403: } ! 404: fclose(input); ! 405: input = sstack[ssp--]; ! 406: if (ssp < 0) ! 407: sourcing = 0; ! 408: return(0); ! 409: } ! 410: ! 411: /* ! 412: * Touch the indicated file. ! 413: * This is nifty for the shell. ! 414: */ ! 415: ! 416: alter(name) ! 417: char name[]; ! 418: { ! 419: register int pid, f; ! 420: char w; ! 421: ! 422: if ((pid = fork()) != 0) ! 423: return; ! 424: clrbuf(stdout); ! 425: clrbuf(stderr); ! 426: clrbuf(stdin); ! 427: sleep(1); ! 428: if ((f = open(name, 0)) < 0) ! 429: exit(1); ! 430: read(f, &w, 1); ! 431: exit(0); ! 432: } ! 433: ! 434: /* ! 435: * Examine the passed line buffer and ! 436: * return true if it is all blanks and tabs. ! 437: */ ! 438: ! 439: blankline(linebuf) ! 440: char linebuf[]; ! 441: { ! 442: register char *cp; ! 443: ! 444: for (cp = linebuf; *cp; cp++) ! 445: if (!any(*cp, " \t")) ! 446: return(0); ! 447: return(1); ! 448: } ! 449: ! 450: /* ! 451: * Fetch the sender's name from the passed message. ! 452: */ ! 453: ! 454: char * ! 455: nameof(mp) ! 456: register struct message *mp; ! 457: { ! 458: static char namebuf[NAMESIZE]; ! 459: char linebuf[LINESIZE]; ! 460: register char *cp, *cp2; ! 461: register FILE *ibuf; ! 462: int first = 1; ! 463: ! 464: if ((cp = hfield("from", mp)) != NOSTR) { ! 465: strcpy(namebuf, cp); ! 466: return(namebuf); ! 467: } ! 468: ibuf = setinput(mp); ! 469: copy("", namebuf); ! 470: if (readline(ibuf, linebuf) <= 0) ! 471: return(namebuf); ! 472: newname: ! 473: for (cp = linebuf; *cp != ' '; cp++) ! 474: ; ! 475: while (any(*cp, " \t")) ! 476: cp++; ! 477: for (cp2 = &namebuf[strlen(namebuf)]; *cp && !any(*cp, " \t") && ! 478: cp2-namebuf < NAMESIZE-1; *cp2++ = *cp++) ! 479: ; ! 480: *cp2 = '\0'; ! 481: if (readline(ibuf, linebuf) <= 0) ! 482: return(namebuf); ! 483: if ((cp = index(linebuf, 'F')) == NULL) ! 484: return(namebuf); ! 485: if (strncmp(cp, "From", 4) != 0) ! 486: return(namebuf); ! 487: while ((cp = index(cp, 'r')) != NULL) { ! 488: if (strncmp(cp, "remote", 6) == 0) { ! 489: if ((cp = index(cp, 'f')) == NULL) ! 490: break; ! 491: if (strncmp(cp, "from", 4) != 0) ! 492: break; ! 493: if ((cp = index(cp, ' ')) == NULL) ! 494: break; ! 495: cp++; ! 496: if (first) { ! 497: copy(cp, namebuf); ! 498: first = 0; ! 499: } else ! 500: strcpy(rindex(namebuf, '!')+1, cp); ! 501: strcat(namebuf, "!"); ! 502: goto newname; ! 503: } ! 504: cp++; ! 505: } ! 506: return(namebuf); ! 507: } ! 508: ! 509: /* ! 510: * Find the rightmost pointer to an instance of the ! 511: * character in the string and return it. ! 512: */ ! 513: ! 514: char * ! 515: rindex(str, c) ! 516: char str[]; ! 517: register int c; ! 518: { ! 519: register char *cp, *cp2; ! 520: ! 521: for (cp = str, cp2 = NOSTR; *cp; cp++) ! 522: if (c == *cp) ! 523: cp2 = cp; ! 524: return(cp2); ! 525: } ! 526: ! 527: /* ! 528: * See if the string is a number. ! 529: */ ! 530: ! 531: numeric(str) ! 532: char str[]; ! 533: { ! 534: register char *cp = str; ! 535: ! 536: while (*cp) ! 537: if (!isdigit(*cp++)) ! 538: return(0); ! 539: return(1); ! 540: } ! 541: ! 542: /* ! 543: * Are any of the characters in the two strings the same? ! 544: */ ! 545: ! 546: anyof(s1, s2) ! 547: register char *s1, *s2; ! 548: { ! 549: register int c; ! 550: ! 551: while (c = *s1++) ! 552: if (any(c, s2)) ! 553: return(1); ! 554: return(0); ! 555: } ! 556: ! 557: /* ! 558: * Determine the leftmost index of the character ! 559: * in the string. ! 560: */ ! 561: ! 562: char * ! 563: index(str, ch) ! 564: char *str; ! 565: { ! 566: register char *cp; ! 567: register int c; ! 568: ! 569: for (c = ch, cp = str; *cp; cp++) ! 570: if (*cp == c) ! 571: return(cp); ! 572: return(NOSTR); ! 573: } ! 574: ! 575: /* ! 576: * String compare two strings of bounded length. ! 577: */ ! 578: ! 579: strncmp(as1, as2, an) ! 580: char *as1, *as2; ! 581: { ! 582: register char *s1, *s2; ! 583: register int n; ! 584: ! 585: s1 = as1; ! 586: s2 = as2; ! 587: n = an; ! 588: while (--n >= 0 && *s1 == *s2++) ! 589: if (*s1++ == '\0') ! 590: return(0); ! 591: return(n<0 ? 0 : *s1 - *--s2); ! 592: } ! 593:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.