|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.