Annotation of 43BSD/contrib/notes/src/nfmail.c, revision 1.1.1.1

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, &note,
                    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 (&note.n_date);
                    328:        notenum = putnote (&io, &where, title, letterstatus, &note,
                    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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.