Annotation of researchv10no/cmd/nupas/smtp/header.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include <ctype.h>
                      3: #include "mail.h"
                      4: #include "string.h"
                      5: #include "header.h"
                      6: #include "aux.h"
                      7: #include <regexp.h>
                      8: 
                      9: /* imported */
                     10: extern char *malloc();
                     11: extern char *strcpy();
                     12: extern char *strchr();
                     13: extern int strncmp();
                     14: extern void exit();
                     15: 
                     16: /* predeclared */
                     17: extern void addheader();
                     18: extern void addbody();
                     19: 
                     20: /* global to this file */
                     21: static regexp *rfprog;
                     22: static regexp *fprog;
                     23: 
                     24: /* imported */
                     25: extern int extrafrom;
                     26: 
                     27: /*
                     28:  *     Input header from standard input.  Actually two extra lines are also
                     29:  *     read, but this is a problem.  Save some header lines in the header
                     30:  *     array.
                     31:  */
                     32: extern
                     33: getheader(fgetsp, fp)
                     34:        char *(*fgetsp)();
                     35:        FILE *fp;
                     36: {
                     37:        char buf[4096];
                     38:        string *line;
                     39:        string *from=NULL;
                     40:        string *date=NULL;
                     41:        char *cp;
                     42:        header *hp;
                     43:        int n;
                     44:  
                     45:        /*
                     46:         *  forget any old headers
                     47:         */
                     48:        for (hp = hdrs; *(hp->name) != '\0'; hp++)
                     49:                hp->line = (string *)0;
                     50: 
                     51:        /*
                     52:         *  preload the first line for the parsing below
                     53:         */
                     54:        if((*fgetsp)(buf, sizeof buf, fp) == NULL)
                     55:                return ferror(fp) ? -1 : 0;
                     56: 
                     57:        /*  If the first line of an rfc822 message
                     58:         *  is a unix from line, use that to `seed' the From: and
                     59:         *  Date: fields.
                     60:         */
                     61:        if(strncmp(buf, "From ", 5)==0) {
                     62:                if (getunixfrom(buf, &from, &date)==0) {
                     63:                        for (hp = hdrs; *(hp->name) != '\0'; hp++) {
                     64:                                if (STRCMP("UnixFrom:", hp) == 0) {
                     65:                                        hp->line = from;
                     66:                                        from = (string *)0;
                     67:                                        continue;
                     68:                                };
                     69:                                if (STRCMP("UnixDate:", hp) == 0) {
                     70:                                        hp->line = date;
                     71:                                        date = (string *)0;
                     72:                                        continue;
                     73:                                };
                     74:                        }
                     75:                        return 0;
                     76:                }
                     77:        }
                     78: 
                     79:        /* Now get real 822 headers */
                     80:        while (buf[0] != '\n' && buf[0] != '\0') {
                     81:                /* gather a multiple line header field */
                     82:                line = s_new();
                     83:                do {
                     84:                        s_append(line, buf);
                     85:                        if((*fgetsp)(buf, sizeof buf, fp) == NULL) {
                     86:                                if(ferror(fp))
                     87:                                        return -1;
                     88:                                *buf = 0;
                     89:                                break;
                     90:                        }
                     91:                } while (*buf==' ' || *buf=='\t');
                     92: 
                     93:                /* header lines must contain `:' with no preceding white */
                     94:                for(cp=s_to_c(line); *cp; cp++)
                     95:                        if(isspace(*cp) || *cp==':')
                     96:                                break;
                     97:                if (*cp != ':') {
                     98:                        addbody(line);
                     99:                        break;
                    100:                }
                    101: 
                    102:                /* look for `important' headers */
                    103:                for (hp = hdrs; *(hp->name) != '\0'; hp++) {
                    104:                        if (cistrncmp(s_to_c(line), hp->name, hp->size) == 0) {
                    105:                                hp->line = line;
                    106:                                break;
                    107:                        };
                    108:                }
                    109:                addheader(line);
                    110:        }
                    111:        /* at this point, buf contains a line of the body */
                    112:        if(buf[0])
                    113:                addbody(s_copy(buf));
                    114:        return 0;
                    115: }
                    116: 
                    117: /*
                    118:  *     Keep a (circular) list of header lines to output.
                    119:  */
                    120: typedef struct quux{
                    121:        struct quux *next;
                    122:        string *line;
                    123: } hlist;
                    124: static hlist dummy = { &dummy, '\0' };
                    125: static hlist *list = &dummy;
                    126: 
                    127: /*
                    128:  *     Add to list of header lines.
                    129:  */
                    130: extern void
                    131: addheader(line)
                    132:        string *line;
                    133: {
                    134:        hlist *thing;
                    135: 
                    136:        thing = (hlist *)malloc(sizeof(hlist));
                    137:        if (thing == NULL) {
                    138:                perror("reading header");
                    139:                exit(1);
                    140:        }
                    141:        thing->line = line;
                    142:        thing->next = list->next;
                    143:        list->next = thing;
                    144:        list = thing;
                    145: }
                    146: 
                    147: /*
                    148:  *     Print list of headers.
                    149:  */
                    150: extern int
                    151: printheaders(fputsp, fp, originalfrom)
                    152:        FILE *fp;
                    153:        int (*fputsp)();
                    154: {
                    155:        hlist *thing, *othing;
                    156:        int printed = 0;
                    157: 
                    158:        for(thing = list->next->next; thing != &dummy; ){
                    159:                printed++;
                    160:                if(originalfrom && strncmp(s_to_c(thing->line), "From:", 5)==0)
                    161:                        (*fputsp)("Original-", fp);
                    162:                (*fputsp)(s_to_c(thing->line), fp);
                    163:                s_free(thing->line);
                    164:                othing = thing;
                    165:                thing = thing->next;
                    166:                free(othing);
                    167:        }
                    168:        list = dummy.next = &dummy;     /* reinitialize for future calls */
                    169:        return(printed);
                    170: }
                    171: 
                    172: /*
                    173:  *     Keep a (circular) list of body lines to output.
                    174:  */
                    175: static hlist bdummy = { &bdummy, '\0' };
                    176: static hlist *blist = &bdummy;
                    177: 
                    178: /*
                    179:  *     Add to list of body lines.
                    180:  */
                    181: extern void
                    182: addbody(line)
                    183:        string *line;
                    184: {
                    185:        hlist *thing;
                    186: 
                    187:        thing = (hlist *)malloc(sizeof(hlist));
                    188:        if (thing == NULL) {
                    189:                perror("reading header");
                    190:                exit(1);
                    191:        }
                    192:        thing->line = line;
                    193:        thing->next = blist->next;
                    194:        blist->next = thing;
                    195:        blist = thing;
                    196: }
                    197: 
                    198: /*
                    199:  *     Print list of body lines
                    200:  */
                    201: extern void
                    202: printbodies(fputsp, fp)
                    203:        FILE *fp;
                    204:        int (*fputsp)();
                    205: {
                    206:        hlist *thing, *othing;
                    207:        int line = 0;
                    208: 
                    209:        for(thing = blist->next->next; thing != &bdummy; ){
                    210:                /* dump extraneous new line */
                    211:                if(line++!=0 || *s_to_c(thing->line)!='\n')
                    212:                        (*fputsp)(s_to_c(thing->line), fp);
                    213:                s_free(thing->line);
                    214:                othing = thing;
                    215:                thing = thing->next;
                    216:                free(othing);
                    217:        }
                    218:        blist = bdummy.next = &bdummy;
                    219: }
                    220: 
                    221: /*
                    222:  *  extract sender and date from a unix remote from line.  return -1
                    223:  *  if its the wrong format, 0 otherwise.
                    224:  */
                    225: getunixfrom(line, fpp, dpp)
                    226:        char *line;
                    227:        string **fpp;
                    228:        string **dpp;
                    229: {              
                    230:        regsubexp subexp[10];
                    231: 
                    232:        if (rfprog == NULL)
                    233:                rfprog = regcomp(REMFROMRE);
                    234:        if (regexec(rfprog, line, subexp, 10)) {
                    235:                *fpp = s_new();
                    236:                append_match(subexp, *fpp, REMSYSMATCH);
                    237:                s_append(*fpp, "!");
                    238:                append_match(subexp, *fpp, REMSENDERMATCH);
                    239:                *dpp = s_new();
                    240:                append_match(subexp, *dpp, REMDATEMATCH);
                    241:                return 0;
                    242:        }
                    243:        if (fprog == NULL)
                    244:                fprog = regcomp(FROMRE);
                    245:        if (regexec(fprog, line, subexp, 10)) {
                    246:                *fpp = s_new();
                    247:                append_match(subexp, *fpp, SENDERMATCH);
                    248:                *dpp = s_new();
                    249:                append_match(subexp, *dpp, DATEMATCH);
                    250:                return 0;
                    251:        }
                    252:        return -1;
                    253: }
                    254: 
                    255: /*
                    256:  *  The addr is either the first whitespace delimited token or
                    257:  *  the first thing enclosed in "<" ">".
                    258:  *  Sets extrafrom > 0 if a from line with other cruft in it.
                    259:  */
                    260: extern string *
                    261: getaddr(line)
                    262:        char *line;
                    263: {
                    264:        register char *lp;
                    265:        register int comment = 0;
                    266:        register int anticomment = 0;
                    267:        register int inquote = 0;
                    268:        static string *sender=0;
                    269: 
                    270:        if (!sender)
                    271:                sender = s_new();
                    272:        s_restart(sender);
                    273:        lp = line;
                    274:        for (; *lp; lp++) {
                    275:                if (comment) {
                    276:                        if (*lp=='(')
                    277:                                comment++;
                    278:                        if (*lp==')')
                    279:                                comment--;
                    280:                        continue;
                    281:                }
                    282:                if (anticomment) {
                    283:                        if (*lp=='>') {
                    284:                                if (*(lp+1)!='\n')
                    285:                                        extrafrom++;
                    286:                                break;
                    287:                        }
                    288:                }
                    289:                if (inquote) {
                    290:                        if (*lp=='"')
                    291:                                inquote = 0;
                    292:                        s_putc(sender, *lp);
                    293:                        continue;
                    294:                }
                    295:                switch (*lp) {
                    296:                case '\t':
                    297:                case '\n':
                    298:                        break;
                    299:                case ' ':
                    300:                        if (cistrncmp(lp, " at ", sizeof(" at ")-1)==0) {
                    301:                                s_putc(sender, '@');
                    302:                                lp += sizeof(" at ")-2;
                    303:                        }
                    304:                        break;
                    305:                case '<':
                    306:                        anticomment = 1;
                    307:                        if(*s_to_c(sender)!='\0')
                    308:                                extrafrom++;
                    309:                        s_restart(sender);
                    310:                        break;
                    311:                case '(':
                    312:                        extrafrom++;
                    313:                        comment++;
                    314:                        break;
                    315:                case '"':
                    316:                        inquote = 1;
                    317:                        /* fall through */
                    318:                default:
                    319:                        s_putc(sender, *lp);
                    320:                        break;
                    321:                }
                    322:        }
                    323:        s_terminate(sender);
                    324:        s_restart(sender);
                    325:        return(sender);
                    326: }
                    327: 
                    328: /*
                    329:  *  case independent string compare
                    330:  */
                    331: extern int
                    332: cistrncmp(s1, s2, n)
                    333:        char *s1;
                    334:        char *s2;
                    335: {
                    336:        int c1, c2;
                    337: 
                    338:        for(; *s1 && n>0; n--, s1++, s2++){
                    339:                c1 = isupper(*s1) ? tolower(*s1) : *s1;
                    340:                c2 = isupper(*s2) ? tolower(*s2) : *s2;
                    341:                if (c1 != c2)
                    342:                        return -1;
                    343:        }
                    344:        return(0);
                    345: }

unix.superglobalmegacorp.com

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