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