Annotation of researchv10no/cmd/nupas/send/message.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include <regexp.h>
                      3: #include <signal.h>
                      4: #include <pwd.h>
                      5: #include "mail.h"
                      6: #include "string.h"
                      7: #include "message.h"
                      8: #include "aux.h"
                      9: 
                     10: /* imported */
                     11: extern char *malloc();
                     12: extern long time();
                     13: extern char *ctime();
                     14: extern char *getlog();
                     15: extern void exit();
                     16: extern char *thedate();
                     17: 
                     18: /* global to this file */
                     19: static regexp *rfprog;
                     20: static regexp *fprog;
                     21: static pipe_err=0;
                     22: 
                     23: #define VMLIMIT (64*1024)
                     24: #define MSGLIMIT (5*1024*1024)
                     25: 
                     26: extern void
                     27: default_from(mp)
                     28:        message *mp;
                     29: {
                     30:        char *logname;
                     31:        struct passwd *pw;
                     32:        extern char *getenv();
                     33: 
                     34:        /* add in date and sender */
                     35:        if ((logname=getenv("upasname")) == NULL) {
                     36:                if ((logname=getlog()) == NULL)
                     37:                        logname = "Liz.Bimmler";
                     38:        }
                     39:        s_append(mp->sender, logname);
                     40:        s_append(mp->date, thedate());
                     41: }
                     42: 
                     43: extern message *
                     44: m_new()
                     45: {
                     46:        message *mp;
                     47: 
                     48:        mp = (message *)malloc(sizeof(message));
                     49:        if (mp == NULL) {
                     50:                perror("message:");
                     51:                exit(1);
                     52:        }
                     53:        mp->sender = s_new();
                     54:        mp->replyaddr = s_new();
                     55:        mp->date = s_new();
                     56:        mp->body = s_new();
                     57:        mp->size = 0;
                     58:        mp->fd = -1;
                     59:        return mp;
                     60: }
                     61: 
                     62: extern int
                     63: m_free(mp)
                     64:        message *mp;
                     65: {
                     66:        if(mp->fd >= 0)
                     67:                close(mp->fd);
                     68:        s_free(mp->sender);
                     69:        s_free(mp->date);
                     70:        s_free(mp->body);
                     71:        free((char *)mp);
                     72: }
                     73: 
                     74: /* read a message into a temp file , return an open fd to it */
                     75: static int
                     76: m_read_to_file(fp, mp)
                     77:        FILE *fp;
                     78:        message *mp;
                     79: {
                     80:        int cfd, fd;
                     81:        int n;
                     82:        char buf[4*1024];
                     83: 
                     84:        /*
                     85:         *  create and unlink temp file
                     86:         */
                     87:        strcpy(buf, MAILROOT);
                     88:        strcat(buf, "mtXXXXXX");
                     89:        mktemp(buf);
                     90:        if((cfd = creat(buf, 0600))<0)
                     91:                return -1;
                     92:        if((fd = open(buf, 2))<0){
                     93:                unlink(buf);
                     94:                close(cfd);
                     95:                return -1;
                     96:        }
                     97:        close(cfd);
                     98:        unlink(buf);
                     99: 
                    100:        /*
                    101:         *  read the rest into the temp file
                    102:         */
                    103:        while((n = fread(buf, 1, sizeof buf, fp)) > 0){
                    104:                if(write(fd, buf, n) != n){
                    105:                        close(fd);
                    106:                        return -1;
                    107:                }
                    108:                mp->size += n;
                    109:                if(mp->size > MSGLIMIT){
                    110:                        mp->size = -1;
                    111:                        break;
                    112:                }
                    113:        }
                    114: 
                    115:        mp->fd = fd;
                    116:        return 0;
                    117: }
                    118: 
                    119: /* read in a message, interpret the 'From' header */
                    120: extern message *
                    121: m_read(fp, rmail, onatty)
                    122:        FILE *fp;
                    123:        int rmail;      /* true if invoked as /bin/rmail */
                    124:        int onatty;     /* true if input from a terminal */
                    125: {
                    126:        message *mp;
                    127:        regsubexp subexp[10];
                    128:        int first;
                    129: 
                    130:        mp = m_new();
                    131: 
                    132:        /* parse From lines */
                    133:        if (rmail) {
                    134:                /* get remote address */
                    135:                string *sender=s_new();
                    136: 
                    137:                if (rfprog == NULL)
                    138:                        rfprog = regcomp(REMFROMRE);
                    139:                first = 1;
                    140:                while(s_read_line(fp, s_restart(mp->body)) != NULL) {
                    141:                        if (regexec(rfprog, s_to_c(mp->body), subexp, 10) == 0){
                    142:                                if(first == 0)
                    143:                                        break;
                    144:                                if (fprog == NULL)
                    145:                                        fprog = regcomp(FROMRE);
                    146:                                if(regexec(fprog, s_to_c(mp->body), subexp,10) == 0)
                    147:                                        break;
                    148:                                s_restart(mp->body);
                    149:                                append_match(subexp, s_restart(sender), SENDERMATCH);
                    150:                                append_match(subexp, s_restart(mp->date), DATEMATCH);
                    151:                                break;
                    152:                        }
                    153:                        append_match(subexp, s_restart(sender), REMSENDERMATCH);
                    154:                        append_match(subexp, s_restart(mp->date), REMDATEMATCH);
                    155:                        if(subexp[REMSYSMATCH].sp!=subexp[REMSYSMATCH].ep){
                    156:                                append_match(subexp, mp->sender, REMSYSMATCH);
                    157:                                s_append(mp->sender, "!");
                    158:                        }
                    159:                        first = 0;
                    160:                }
                    161:                s_append(mp->sender, s_to_c(sender));
                    162:                s_free(sender);
                    163:        }
                    164:        if (*s_to_c(mp->sender)=='\0')
                    165:                default_from(mp);
                    166: 
                    167:        /* get body */
                    168:        if(onatty){
                    169:                /* user typing on terminal: terminator == '.' or EOF */
                    170:                for(;;) {
                    171:                        char *line;
                    172: 
                    173:                        if ((line=s_read_line(fp, mp->body))==NULL)
                    174:                                break;
                    175:                        if (strcmp(".\n", line)==0) {
                    176:                                *line = '\0';
                    177:                                mp->body->ptr = line;
                    178:                                break;
                    179:                        }
                    180:                }
                    181:                mp->size = mp->body->ptr - mp->body->base;
                    182:        } else {
                    183:                /*
                    184:                 *  read up to VMLIMIT bytes (more or less).
                    185:                 *  if message is longer use temp file
                    186:                 */
                    187:                mp->size = s_read_to_lim(fp, mp->body, VMLIMIT);
                    188:                if(mp->size < 0){
                    189:                        mp->size = -mp->size;
                    190:                        if(m_read_to_file(fp, mp) < 0){
                    191:                                perror("m_read");
                    192:                                exit(1);
                    193:                        }
                    194:                }
                    195:        }
                    196: 
                    197:        /*
                    198:         *  ignore 0 length messages from a terminal
                    199:         */
                    200:        if (!rmail && *s_to_c(mp->body) == '\0')
                    201:                return NULL;
                    202: 
                    203:        return mp;
                    204: }
                    205: 
                    206: SIGRETURN
                    207: sigpipe(s)
                    208:        int s;
                    209: {
                    210:        signal(SIGPIPE, sigpipe);
                    211:        pipe_err = -1;
                    212: }
                    213: 
                    214: /* return a piece of message starting at `offset' */
                    215: extern int
                    216: m_get(mp, offset, pp)
                    217:        message *mp;
                    218:        long offset;
                    219:        char **pp;
                    220: {
                    221:        static char buf[4*1024];
                    222: 
                    223:        /*
                    224:         *  are we past eof?
                    225:         */
                    226:        if(offset >= mp->size)
                    227:                return 0;
                    228: 
                    229:        /*
                    230:         *  are we in the virtual memory portion?
                    231:         */
                    232:        if(offset < mp->body->ptr - mp->body->base){
                    233:                *pp = mp->body->base + offset;
                    234:                return mp->body->ptr - mp->body->base - offset;
                    235:        }
                    236: 
                    237:        /*
                    238:         *  read it from the temp file
                    239:         */
                    240:        offset -= mp->body->ptr - mp->body->base;
                    241:        if(mp->fd < 0)
                    242:                return -1;
                    243:        if(lseek(mp->fd, offset, 0)<0)
                    244:                return -1;
                    245:        *pp = buf;
                    246:        return read(mp->fd, buf, sizeof buf);
                    247: }
                    248: 
                    249: /* output the message body without ^From escapes */
                    250: static int
                    251: m_noescape(mp, fp)
                    252:        message *mp;    /* the message */
                    253:        FILE *fp;       /* where to print it */
                    254: {
                    255:        long offset;
                    256:        int n;
                    257:        char *p;
                    258: 
                    259:        for(offset = 0; offset < mp->size; offset += n){
                    260:                n = m_get(mp, offset, &p);
                    261:                if(n < 0){
                    262:                        fflush(fp);
                    263:                        return -1;
                    264:                }
                    265:                fwrite(p, n, 1, fp);
                    266:        }
                    267:        fflush(fp);
                    268:        return 0;
                    269: }
                    270: 
                    271: /*
                    272:  *  output the message body with ^From escapes.  The state machine
                    273:  *  ensures that any line starting with a 'From ' gets a '>' stuck
                    274:  *  in front of it.
                    275:  */
                    276: static int
                    277: m_escape(mp, fp)
                    278:        message *mp;    /* the message */
                    279:        FILE *fp;       /* where to print it */
                    280: {
                    281:        register char *p;
                    282:        register char *end;
                    283:        register int state;
                    284:        long offset;
                    285:        int n;
                    286:        char *start;
                    287: 
                    288:        state = 1;
                    289:        for(offset = 0; offset < mp->size; offset += n){
                    290:                n = m_get(mp, offset, &start);
                    291:                if(n < 0){
                    292:                        fflush(fp);
                    293:                        return -1;
                    294:                }
                    295: 
                    296:                p = start;
                    297:                for(end = p+n; p < end; p++){
                    298:                        switch(state){
                    299:                        case 1:
                    300:                                if(*p == 'F'){
                    301:                                        state = 2;
                    302:                                        continue;
                    303:                                }
                    304:                                state = 0;
                    305:                                break;
                    306:                        case 2:
                    307:                                if(*p == 'r'){
                    308:                                        state = 3;
                    309:                                        continue;
                    310:                                }
                    311:                                state = 0;
                    312:                                fputc('F', fp);
                    313:                                break;
                    314:                        case 3:
                    315:                                if(*p == 'o'){
                    316:                                        state = 4;
                    317:                                        continue;
                    318:                                }
                    319:                                state = 0;
                    320:                                fputc('F', fp);
                    321:                                fputc('r', fp);
                    322:                                break;
                    323:                        case 4:
                    324:                                if(*p == 'm'){
                    325:                                        state = 5;
                    326:                                        continue;
                    327:                                }
                    328:                                state = 0;
                    329:                                fputc('F', fp);
                    330:                                fputc('r', fp);
                    331:                                fputc('o', fp);
                    332:                                break;
                    333:                        case 5:
                    334:                                if(*p == ' ')
                    335:                                        fputc('>', fp);
                    336:                                state = 0;
                    337:                                fputc('F', fp);
                    338:                                fputc('r', fp);
                    339:                                fputc('o', fp);
                    340:                                fputc('m', fp);
                    341:                                break;
                    342:                        }
                    343:                        fputc(*p, fp);
                    344:                        if(*p == '\n')
                    345:                                state = 1;
                    346:                }
                    347:        }
                    348:        fflush(fp);
                    349:        return 0;
                    350: }
                    351: 
                    352: /* output a message */
                    353: extern int
                    354: m_print(mp, fp, remote, mbox)
                    355:        message *mp;    /* the message */
                    356:        FILE *fp;       /* where to print it */
                    357:        char *remote;   /* 'remote from' string */
                    358: {
                    359:        SIG_TYP oldsig;
                    360:        int err;
                    361: 
                    362:        pipe_err = 0;
                    363:        oldsig = signal(SIGPIPE, sigpipe);
                    364:        if (remote != NULL)
                    365:                print_remote_header(fp,s_to_c(mp->sender),s_to_c(mp->date),remote);
                    366:        else
                    367:                print_header(fp, s_to_c(mp->sender), s_to_c(mp->date));
                    368: 
                    369:        if (!mbox)
                    370:                err = m_noescape(mp, fp);
                    371:        else
                    372:                err = m_escape(mp, fp);
                    373:        signal(SIGPIPE, oldsig);
                    374:        if(ferror(fp))
                    375:                err = -1;
                    376:        return pipe_err|err;
                    377: }
                    378: 
                    379: /* print just the message body */
                    380: extern int
                    381: m_bprint(mp, fp)
                    382:        message *mp;    /* the message */
                    383:        FILE *fp;       /* where to print it */
                    384: {
                    385:        SIG_TYP oldsig;
                    386:        int err;
                    387: 
                    388:        pipe_err = 0;
                    389:        oldsig = signal(SIGPIPE, sigpipe);
                    390:        err = m_noescape(mp, fp);
                    391:        signal(SIGPIPE, oldsig);
                    392:        if(ferror(fp))
                    393:                err = -1;
                    394:        return pipe_err|err;
                    395: }

unix.superglobalmegacorp.com

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