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

Defined functions

copy defined in line 511; used 2 times
dopipe defined in line 492; used 1 times
getignore defined in line 392; used 2 times
main defined in line 60; never used
shouldignore defined in line 465; used 2 times
skipwhite defined in line 379; used 5 times

Defined variables

AnchorSearch defined in line 58; used 2 times
Debug defined in line 39; used 8 times
Nfpipe defined in line 49; used 2 times
ignore defined in line 55; used 6 times
ignore_cnt defined in line 56; used 6 times
rcsid defined in line 13; never used
system_rc defined in line 52; used 1 times
title defined in line 36; used 6 times
tmpname defined in line 50; used 8 times

Defined macros

EX_DATAERR defined in line 8; used 1 times
EX_OK defined in line 6; used 2 times
EX_UNAVAILABLE defined in line 9; used 3 times
EX_USAGE defined in line 7; used 1 times
IGNORESIZE defined in line 34; used 3 times
MAX_IGNORE defined in line 54; used 2 times
Last modified: 1996-10-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4285
Valid CSS Valid XHTML 1.0 Strict