|
|
1.1 ! root 1: #include "parms.h" ! 2: #include "structs.h" ! 3: #include <sysexits.h> /* bsd only? */ ! 4: ! 5: #ifdef RCSIDENT ! 6: static char *rcsid = "$Header: nfmail.c,v 1.7.0.8 85/10/20 11:09:09 notes Rel $"; ! 7: #endif RCSIDENT ! 8: ! 9: /* ! 10: * nfmail ! 11: * ! 12: * A simple program which goes through standard input, which ! 13: * should be a formatted mail article with headers, and ! 14: * parses out the "Subject:" line. We then turn around and ! 15: * use it to invoke "nfpipe" and send the letter to the appropriate ! 16: * notesfile (specified on the nfmail command line). ! 17: * ! 18: * Original coding: Wayne Hamilton, U of Illinois CSO (I think) ! 19: * Modified: Stuart Cracraft, SRI International ! 20: * ! 21: */ ! 22: ! 23: ! 24: char *getadr (); ! 25: FILE * popen (); ! 26: ! 27: #define IGNORESIZE 256 ! 28: ! 29: static char title[BUFSIZ] = "No Subject Line"; ! 30: ! 31: /* ! 32: * next three variables declared in "parsepath". ! 33: */ ! 34: extern char fromsys[SYSSZ + 1]; /* gave it to us */ ! 35: extern char origsys[SYSSZ + 1]; /* started here */ ! 36: extern char authname[NAMESZ + 1]; /* author */ ! 37: ! 38: char Nfpipe[BUFSIZ]; /* nfpipe pathname */ ! 39: char tmpname[BUFSIZ]; /* scratch file */ ! 40: ! 41: char system_rc[] = "/usr/lib/Mail.rc"; ! 42: ! 43: #define MAX_IGNORE 32 ! 44: char ignore[MAX_IGNORE][IGNORESIZE]; ! 45: int ignore_cnt = 0; ! 46: ! 47: int AnchorSearch = TRUE; ! 48: ! 49: main (argc, argv) ! 50: char **argv; ! 51: { ! 52: register FILE * Ftmp; ! 53: char command[BUFSIZ], ! 54: from[BUFSIZ], ! 55: oldfrom[BUFSIZ], ! 56: buf[BUFSIZ]; ! 57: int gotsubj = FALSE, ! 58: gotfrom = FALSE, ! 59: gotoldfrom = FALSE; ! 60: int stripheader = FALSE; /* leave headers in */ ! 61: int letterstatus = 0; /* director msg? */ ! 62: int tossit; ! 63: char *myrc = 0; ! 64: char *home; ! 65: int i; ! 66: char *p, ! 67: *q, ! 68: *skipwhite (); ! 69: ! 70: struct io_f io; ! 71: struct daddr_f where; ! 72: struct when_f entered; ! 73: struct id_f respid; ! 74: struct auth_f auth; ! 75: struct when_f whentime; ! 76: int notenum; ! 77: int status; ! 78: struct note_f note; ! 79: ! 80: startup (argc, argv); ! 81: argc--; /* blast command */ ! 82: argv++; ! 83: from[0] = oldfrom[0] = '\0'; /* zero them */ ! 84: ! 85: while (argc != 0) ! 86: { ! 87: ! 88: if (strncmp (*argv, "-s\0", 3) == 0) /* strip headers */ ! 89: { ! 90: argc--; ! 91: argv++; ! 92: stripheader = TRUE; ! 93: continue; ! 94: } ! 95: if (strncmp (*argv, "-F\0", 3) == 0) /* floating match */ ! 96: { ! 97: argv++; ! 98: argc--; /* to next arg */ ! 99: AnchorSearch = FALSE; /* floating search */ ! 100: continue; ! 101: } ! 102: if (strncmp (*argv, "-d\0", 3) == 0) /* enable dirmsg */ ! 103: { ! 104: argc--; ! 105: argv++; ! 106: letterstatus |= DIRMES; ! 107: continue; ! 108: } ! 109: if (strncmp (*argv, "-m\0", 3) == 0) /* specify .mailrc */ ! 110: { ! 111: argc--; ! 112: argv++; ! 113: if (argc != 0) ! 114: { ! 115: getignore (*argv); ! 116: } ! 117: else ! 118: { ! 119: fprintf (stderr, "Need to specifiy -m file\n"); ! 120: goto usage; ! 121: } ! 122: argc--; ! 123: argv++; ! 124: continue; /* next arg */ ! 125: } ! 126: break; /* not an arg */ ! 127: } ! 128: ! 129: ! 130: if (!argc) ! 131: { ! 132: usage: ! 133: fprintf (stderr, "Usage: %s [-F] [-s] [-m .mailrc-file] <notesfile>\n", ! 134: Invokedas); ! 135: exit (EX_USAGE); ! 136: } ! 137: ! 138: /* ! 139: * build ourselves a scratch file. If we can't, then pass the ! 140: * mail on with a default title. ! 141: */ ! 142: ! 143: sprintf (tmpname, "/tmp/nfm%05d", getpid ()); ! 144: sprintf (Nfpipe, "%s/nfpipe", BIN); ! 145: if ((Ftmp = fopen (tmpname, "w")) == NULL) ! 146: { ! 147: fprintf (stderr, "nfmail: can't fopen temp file, but the mail gets thru\n"); ! 148: sprintf (command, "%s %s -t \"Mail to %s\"", Nfpipe, *argv, *argv); ! 149: dopipe (command, stdin); ! 150: unlink (tmpname); /* ... remove scratch file */ ! 151: exit (EX_OK); /* and leave */ ! 152: } ! 153: ! 154: /* ! 155: * Step through the system Mail.rc file and pilfer the ignore commands. ! 156: * Then, process the .mailrc file in the home directory if there is one. ! 157: */ ! 158: getignore (system_rc); ! 159: ! 160: /* ! 161: * read through the mail looking for the subject line. ! 162: */ ! 163: ! 164: while (gets (buf) != NULL) ! 165: { ! 166: if (!buf[0]) ! 167: break; /* header's end */ ! 168: if (buf[0] == '\t') /* continuation */ ! 169: goto doit; /* use same "tossit" */ ! 170: ! 171: tossit = stripheader; ! 172: if (!strncmp (buf, "Subject: ", 9)) /* check for title */ ! 173: { ! 174: if (!gotsubj) /* only first one */ ! 175: { ! 176: strcpy (title, buf + 9); ! 177: gotsubj = TRUE; ! 178: } ! 179: tossit = FALSE; ! 180: goto doit; /* skip other tests */ ! 181: } ! 182: if (!strncmp (buf, "From: ", 6)) /* author */ ! 183: { /* grab user name */ ! 184: if (!gotfrom) /* only once */ ! 185: { ! 186: strcpy (from, buf + 6); ! 187: gotfrom = TRUE; ! 188: } ! 189: tossit = FALSE; /* keep all from lines */ ! 190: goto doit; ! 191: } ! 192: if (!strncmp (buf, "From", 4) || !strncmp (buf, ">From", 5)) ! 193: { ! 194: if (!gotoldfrom) ! 195: { ! 196: strcpy (oldfrom, buf + 5); /* save it */ ! 197: gotoldfrom++; ! 198: } ! 199: tossit = FALSE; /* save all addresses */ ! 200: } ! 201: else ! 202: if (stripheader && !shouldignore (buf)) ! 203: tossit = FALSE; /* "ignore" only when stripping */ ! 204: ! 205: doit: /* for continuation lines */ ! 206: if (tossit == FALSE) ! 207: fprintf (Ftmp, "%s\n", buf); /* send the header line also */ ! 208: } /* of header parsing loop */ ! 209: ! 210: putc ('\n', Ftmp); /* blank after headers */ ! 211: copy (stdin, Ftmp); ! 212: fclose (Ftmp); ! 213: ! 214: if ((Ftmp = fopen (tmpname, "r")) == NULL) ! 215: { ! 216: unlink (tmpname); /* ... remove scratch file */ ! 217: fprintf (stderr, "nfmail: can't re-fopen temp file %s\n", tmpname); ! 218: exit (EX_UNAVAILABLE); ! 219: } ! 220: ! 221: /* ! 222: * Now that we have collected the letter and parsed such banalities ! 223: * as the title and the author and stripped any header lines that we ! 224: * don't care to hear about, it's time to put the letter into ! 225: * the notesfile. We use routines scammed from our news/notes gateway ! 226: * code to look at the title and determine if it's a response to ! 227: * a previous letter. This allows us to have the correct linkage ! 228: * for mail sent to a notesfile.... ! 229: */ ! 230: ! 231: if ((i = init (&io, *argv)) < 0) ! 232: { ! 233: unlink (tmpname); /* zap scratch file */ ! 234: fprintf (stderr, "%s: can't open notesfile %s (retcode %d)\n", ! 235: Invokedas, *argv, i); ! 236: /* ! 237: * Should have a better scheme for knowing why can't open ! 238: */ ! 239: exit (EX_UNAVAILABLE); /* bad nf or such */ ! 240: } ! 241: p = title; ! 242: while (*p && (*p == ' ' || *p == '\t')) /* leading trash */ ! 243: p++; /* skip */ ! 244: if (!strncmp (p, "re: ", 4) || /* it looks like */ ! 245: !strncmp (p, "Re: ", 4) || /* a response */ ! 246: !strncmp (p, "RE: ", 4)) ! 247: { ! 248: do ! 249: { ! 250: for (p += 3; *p == ' ' || *p == '\t'; p++); /* drop spaces */ ! 251: } while (!strncmp (p, "re: ", 4) || ! 252: !strncmp (p, "Re: ", 4) || ! 253: !strncmp (p, "RE: ", 4)); ! 254: strncpy (io.xstring, p, TITLEN); /* load it */ ! 255: io.xstring[TITLEN - 1] = '\0'; /* and terminate it */ ! 256: notenum = findtitle (&io, io.descr.d_nnote, AnchorSearch);/* start at back */ ! 257: } ! 258: else ! 259: { ! 260: notenum = 0; /* has to be new */ ! 261: } ! 262: ! 263: /* ! 264: * OK. By now, we have a "notenum" if the article can be pegged ! 265: * as a response to one of our notes. ! 266: * Otherwise, notenum==0 and we'll have to turn it into ! 267: * a base note. ! 268: */ ! 269: ! 270: gettime (&whentime); ! 271: gettime (&entered); ! 272: /* ! 273: * load the user's name ! 274: */ ! 275: if (from[0] != '\0') /* got one */ ! 276: { ! 277: p = q = from; ! 278: while ((p = index (p, '<')) != (char *) NULL) ! 279: q = ++p; /* get innermost <..> */ ! 280: p = index (q, '>'); ! 281: if (p != (char *) NULL) ! 282: *p = '\0'; /* zap */ ! 283: parsepath (q, (char *) NULL); /* actually break it */ ! 284: } ! 285: else ! 286: { ! 287: if (oldfrom[0] != '\0') ! 288: { ! 289: parsepath (oldfrom, (char *) NULL); /* try for something */ ! 290: } ! 291: else ! 292: { ! 293: strcpy (authname, "MAILER-DAEMON"); /* general catch-all */ ! 294: origsys[0] = '\0'; /* local */ ! 295: } ! 296: } ! 297: strncpy (auth.aname, authname, NAMESZ); /* user */ ! 298: if (origsys[0] == '\0') ! 299: strncpy (auth.asystem, Authsystem, HOMESYSSZ); /* local host */ ! 300: else ! 301: strncpy (auth.asystem, origsys, HOMESYSSZ); /* system */ ! 302: auth.aname[NAMESZ - 1] = auth.asystem[HOMESYSSZ - 1] = '\0';/* chop */ ! 303: auth.aid = Anonuid; /* uid (none) */ ! 304: #ifdef DEBUG ! 305: printf ("parse path returns the following:\n"); ! 306: printf ("authname: %s\n", authname); ! 307: printf ("origsys: %s\n", origsys); ! 308: printf ("fromsys: %s\n", fromsys); ! 309: #endif DEBUG ! 310: if (notenum > 0) ! 311: { ! 312: pagein (&io, Ftmp, &where); ! 313: i = putresp (&io, &where, putresp, notenum, &entered, &auth, ¬e, ! 314: LOCKIT, &respid, ADDID, System, ADDTIME, &whentime); ! 315: } ! 316: else ! 317: { ! 318: for (p = &title[0]; *p && (*p == ' ' || *p == '\t');) ! 319: p++; /* strip blanks */ ! 320: for (i = 0; i < TITLEN; i++) /* shift down */ ! 321: { ! 322: if ((title[i] = *p++) == '\0') /* want assignment */ ! 323: break; /* end */ ! 324: } ! 325: title[TITLEN - 1] = '\0'; /* terminate for sure */ ! 326: pagein (&io, Ftmp, &where); ! 327: gettime (¬e.n_date); ! 328: notenum = putnote (&io, &where, title, letterstatus, ¬e, ! 329: &auth, NOPOLICY, LOCKIT, ADDID, System, ADDTIME); ! 330: } ! 331: ! 332: finish (&io); /* update numbers and close */ ! 333: fclose (Ftmp); /* close and ... */ ! 334: unlink (tmpname); /* ... remove scratch file */ ! 335: exit (EX_OK); ! 336: } ! 337: ! 338: ! 339: char *skipwhite (p) ! 340: char *p; ! 341: { ! 342: while (*p == ' ' || *p == '\t' || *p == '\n') ! 343: p++; ! 344: return (p); ! 345: } ! 346: ! 347: ! 348: /* ! 349: * Get all the "ignore" commands from the file. Do nothing if the file ! 350: * does not exist. ! 351: */ ! 352: getignore (name) ! 353: char *name; ! 354: { ! 355: FILE * f; ! 356: char buff[IGNORESIZE]; ! 357: char *p, ! 358: *q; ! 359: ! 360: if ((f = fopen (name, "r")) == 0) ! 361: return (0); ! 362: ! 363: while (!feof (f)) ! 364: { ! 365: p = buff; ! 366: fgets (buff, IGNORESIZE, f); ! 367: p = skipwhite (p); ! 368: ! 369: if (strncmp (p, "ignore", 6) == 0) ! 370: { ! 371: p = skipwhite (p + 6); ! 372: ! 373: /* ! 374: * Collect the tags of the ignore command ! 375: */ ! 376: ! 377: while (*p != 0) ! 378: { ! 379: if (ignore_cnt >= MAX_IGNORE) ! 380: { ! 381: fprintf (stderr, "%s: too many ignore tags\n", Invokedas); ! 382: exit (EX_DATAERR); ! 383: } ! 384: p = skipwhite (p); ! 385: for (q = ignore[ignore_cnt]; ! 386: *p != ' ' && *p != '\t' && *p != '\n' && *p != 0; ! 387: *(q++) = *(p++) ! 388: ); ! 389: *q = 0; ! 390: if (!shouldignore (ignore[ignore_cnt])) ! 391: { ! 392: ignore_cnt++; ! 393: } ! 394: p = skipwhite (p); ! 395: } ! 396: } ! 397: } ! 398: ! 399: fclose (f); ! 400: return (0); ! 401: } ! 402: ! 403: ! 404: ! 405: /* ! 406: * Should we ignore this line? ! 407: */ ! 408: shouldignore (p) ! 409: char *p; ! 410: { ! 411: int i; ! 412: ! 413: for (i = 0; i < ignore_cnt; i++) ! 414: if (strncmp (p, ignore[i], strlen (ignore[i])) == 0) ! 415: return (1); ! 416: return (0); ! 417: } ! 418: ! 419: /* ! 420: * simple command feeds what is left of the file "File" into ! 421: * a pipe feeding stdin of "command". ! 422: * ! 423: */ ! 424: ! 425: dopipe (command, File) char *command; ! 426: FILE * File; ! 427: { ! 428: register FILE * Pipe; ! 429: ! 430: if ((Pipe = popen (command, "w")) == NULL) ! 431: { ! 432: fprintf (stderr, "%s: can't popen (%s)!?\n", Invokedas, command); ! 433: exit (EX_UNAVAILABLE); ! 434: } ! 435: ! 436: copy (File, Pipe); ! 437: pclose (Pipe); ! 438: } ! 439: ! 440: /* ! 441: * copy rest of file "File" to "To". ! 442: */ ! 443: ! 444: copy (From, To) FILE * From, *To; ! 445: { ! 446: register int c; ! 447: ! 448: while ((c = getc (From)) != EOF) ! 449: putc (c, To); ! 450: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.