13e12c5d1SDavid du Colombier #include "common.h" 23e12c5d1SDavid du Colombier #include "send.h" 33e12c5d1SDavid du Colombier 43e12c5d1SDavid du Colombier /* global to this file */ 53e12c5d1SDavid du Colombier static Reprog *rfprog; 63e12c5d1SDavid du Colombier static Reprog *fprog; 73e12c5d1SDavid du Colombier 83e12c5d1SDavid du Colombier #define VMLIMIT (64*1024) 9*219b2ee8SDavid du Colombier #define MSGLIMIT (128*1024*1024) 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier extern void 123e12c5d1SDavid du Colombier default_from(message *mp) 133e12c5d1SDavid du Colombier { 143e12c5d1SDavid du Colombier char *cp; 153e12c5d1SDavid du Colombier 163e12c5d1SDavid du Colombier cp = getenv("upasname"); 173e12c5d1SDavid du Colombier if(cp) 183e12c5d1SDavid du Colombier s_append(mp->sender, cp); 193e12c5d1SDavid du Colombier else 203e12c5d1SDavid du Colombier s_append(mp->sender, getlog()); 213e12c5d1SDavid du Colombier s_append(mp->date, thedate()); 223e12c5d1SDavid du Colombier } 233e12c5d1SDavid du Colombier 243e12c5d1SDavid du Colombier extern message * 253e12c5d1SDavid du Colombier m_new(void) 263e12c5d1SDavid du Colombier { 273e12c5d1SDavid du Colombier message *mp; 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier mp = (message *)malloc(sizeof(message)); 303e12c5d1SDavid du Colombier if (mp == 0) { 313e12c5d1SDavid du Colombier perror("message:"); 323e12c5d1SDavid du Colombier exit(1); 333e12c5d1SDavid du Colombier } 343e12c5d1SDavid du Colombier mp->sender = s_new(); 353e12c5d1SDavid du Colombier mp->replyaddr = s_new(); 363e12c5d1SDavid du Colombier mp->date = s_new(); 373e12c5d1SDavid du Colombier mp->body = s_new(); 383e12c5d1SDavid du Colombier mp->size = 0; 393e12c5d1SDavid du Colombier mp->fd = -1; 403e12c5d1SDavid du Colombier return mp; 413e12c5d1SDavid du Colombier } 423e12c5d1SDavid du Colombier 433e12c5d1SDavid du Colombier extern void 443e12c5d1SDavid du Colombier m_free(message *mp) 453e12c5d1SDavid du Colombier { 463e12c5d1SDavid du Colombier if(mp->fd >= 0){ 473e12c5d1SDavid du Colombier close(mp->fd); 483e12c5d1SDavid du Colombier remove(s_to_c(mp->tmp)); 493e12c5d1SDavid du Colombier s_free(mp->tmp); 503e12c5d1SDavid du Colombier } 513e12c5d1SDavid du Colombier s_free(mp->sender); 523e12c5d1SDavid du Colombier s_free(mp->date); 533e12c5d1SDavid du Colombier s_free(mp->body); 543e12c5d1SDavid du Colombier free((char *)mp); 553e12c5d1SDavid du Colombier } 563e12c5d1SDavid du Colombier 573e12c5d1SDavid du Colombier /* read a message into a temp file , return an open fd to it */ 583e12c5d1SDavid du Colombier static int 593e12c5d1SDavid du Colombier m_read_to_file(Biobuf *fp, message *mp) 603e12c5d1SDavid du Colombier { 613e12c5d1SDavid du Colombier int fd; 623e12c5d1SDavid du Colombier int n; 633e12c5d1SDavid du Colombier String *file; 643e12c5d1SDavid du Colombier char buf[4*1024]; 653e12c5d1SDavid du Colombier 663e12c5d1SDavid du Colombier file = s_new(); 673e12c5d1SDavid du Colombier /* 683e12c5d1SDavid du Colombier * create and unlink temp file 693e12c5d1SDavid du Colombier */ 703e12c5d1SDavid du Colombier abspath("tmp/mtXXXXXX", MAILROOT, file); 713e12c5d1SDavid du Colombier mktemp(s_to_c(file)); 723e12c5d1SDavid du Colombier if((fd = syscreate(s_to_c(file), 0600))<0){ 733e12c5d1SDavid du Colombier s_free(mp->tmp); 743e12c5d1SDavid du Colombier return -1; 753e12c5d1SDavid du Colombier } 763e12c5d1SDavid du Colombier mp->tmp = file; 773e12c5d1SDavid du Colombier 783e12c5d1SDavid du Colombier /* 793e12c5d1SDavid du Colombier * read the rest into the temp file 803e12c5d1SDavid du Colombier */ 813e12c5d1SDavid du Colombier while((n = Bread(fp, buf, sizeof(buf))) > 0){ 823e12c5d1SDavid du Colombier if(write(fd, buf, n) != n){ 833e12c5d1SDavid du Colombier close(fd); 843e12c5d1SDavid du Colombier return -1; 853e12c5d1SDavid du Colombier } 863e12c5d1SDavid du Colombier mp->size += n; 873e12c5d1SDavid du Colombier if(mp->size > MSGLIMIT){ 883e12c5d1SDavid du Colombier mp->size = -1; 893e12c5d1SDavid du Colombier break; 903e12c5d1SDavid du Colombier } 913e12c5d1SDavid du Colombier } 923e12c5d1SDavid du Colombier 933e12c5d1SDavid du Colombier mp->fd = fd; 943e12c5d1SDavid du Colombier return 0; 953e12c5d1SDavid du Colombier } 963e12c5d1SDavid du Colombier 973e12c5d1SDavid du Colombier /* read in a message, interpret the 'From' header */ 983e12c5d1SDavid du Colombier extern message * 993e12c5d1SDavid du Colombier m_read(Biobuf *fp, int rmail) 1003e12c5d1SDavid du Colombier { 1013e12c5d1SDavid du Colombier message *mp; 1023e12c5d1SDavid du Colombier Resub subexp[10]; 1033e12c5d1SDavid du Colombier int first; 1043e12c5d1SDavid du Colombier int n; 1053e12c5d1SDavid du Colombier 106*219b2ee8SDavid du Colombier 1073e12c5d1SDavid du Colombier mp = m_new(); 1083e12c5d1SDavid du Colombier 1093e12c5d1SDavid du Colombier /* parse From lines if remote */ 1103e12c5d1SDavid du Colombier if (rmail) { 1113e12c5d1SDavid du Colombier /* get remote address */ 1123e12c5d1SDavid du Colombier String *sender=s_new(); 1133e12c5d1SDavid du Colombier 1143e12c5d1SDavid du Colombier if (rfprog == 0) 1153e12c5d1SDavid du Colombier rfprog = regcomp(REMFROMRE); 1163e12c5d1SDavid du Colombier first = 1; 1173e12c5d1SDavid du Colombier while(s_read_line(fp, s_restart(mp->body)) != 0) { 1183e12c5d1SDavid du Colombier memset(subexp, 0, sizeof(subexp)); 1193e12c5d1SDavid du Colombier if (regexec(rfprog, s_to_c(mp->body), subexp, 10) == 0){ 1203e12c5d1SDavid du Colombier if(first == 0) 1213e12c5d1SDavid du Colombier break; 1223e12c5d1SDavid du Colombier if (fprog == 0) 1233e12c5d1SDavid du Colombier fprog = regcomp(FROMRE); 1243e12c5d1SDavid du Colombier memset(subexp, 0, sizeof(subexp)); 1253e12c5d1SDavid du Colombier if(regexec(fprog, s_to_c(mp->body), subexp,10) == 0) 1263e12c5d1SDavid du Colombier break; 1273e12c5d1SDavid du Colombier USE(s_restart(mp->body)); 1283e12c5d1SDavid du Colombier append_match(subexp, s_restart(sender), SENDERMATCH); 1293e12c5d1SDavid du Colombier append_match(subexp, s_restart(mp->date), DATEMATCH); 1303e12c5d1SDavid du Colombier break; 1313e12c5d1SDavid du Colombier } 1323e12c5d1SDavid du Colombier append_match(subexp, s_restart(sender), REMSENDERMATCH); 1333e12c5d1SDavid du Colombier append_match(subexp, s_restart(mp->date), REMDATEMATCH); 1343e12c5d1SDavid du Colombier if(subexp[REMSYSMATCH].sp!=subexp[REMSYSMATCH].ep){ 1353e12c5d1SDavid du Colombier append_match(subexp, mp->sender, REMSYSMATCH); 1363e12c5d1SDavid du Colombier s_append(mp->sender, "!"); 1373e12c5d1SDavid du Colombier } 1383e12c5d1SDavid du Colombier first = 0; 1393e12c5d1SDavid du Colombier } 1403e12c5d1SDavid du Colombier s_append(mp->sender, s_to_c(sender)); 1413e12c5d1SDavid du Colombier s_free(sender); 1423e12c5d1SDavid du Colombier } 1433e12c5d1SDavid du Colombier if (*s_to_c(mp->sender)=='\0') 1443e12c5d1SDavid du Colombier default_from(mp); 1453e12c5d1SDavid du Colombier 1463e12c5d1SDavid du Colombier /* 1473e12c5d1SDavid du Colombier * read up to VMLIMIT bytes (more or less) into main memory. 1483e12c5d1SDavid du Colombier * if message is longer put the rest in a tmp file. 1493e12c5d1SDavid du Colombier */ 1503e12c5d1SDavid du Colombier mp->size = mp->body->ptr - mp->body->base; 1513e12c5d1SDavid du Colombier n = s_read(fp, mp->body, VMLIMIT); 1523e12c5d1SDavid du Colombier if(n < 0){ 1533e12c5d1SDavid du Colombier perror("m_read"); 1543e12c5d1SDavid du Colombier exit(1); 1553e12c5d1SDavid du Colombier } 1563e12c5d1SDavid du Colombier mp->size += n; 1573e12c5d1SDavid du Colombier if(n == VMLIMIT){ 1583e12c5d1SDavid du Colombier if(m_read_to_file(fp, mp) < 0){ 1593e12c5d1SDavid du Colombier perror("m_read"); 1603e12c5d1SDavid du Colombier exit(1); 1613e12c5d1SDavid du Colombier } 1623e12c5d1SDavid du Colombier } 1633e12c5d1SDavid du Colombier 1643e12c5d1SDavid du Colombier /* 1653e12c5d1SDavid du Colombier * ignore 0 length messages from a terminal 1663e12c5d1SDavid du Colombier */ 167*219b2ee8SDavid du Colombier if (!rmail && mp->size == 0) 1683e12c5d1SDavid du Colombier return 0; 1693e12c5d1SDavid du Colombier 1703e12c5d1SDavid du Colombier return mp; 1713e12c5d1SDavid du Colombier } 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier /* return a piece of message starting at `offset' */ 1743e12c5d1SDavid du Colombier extern int 1753e12c5d1SDavid du Colombier m_get(message *mp, long offset, char **pp) 1763e12c5d1SDavid du Colombier { 1773e12c5d1SDavid du Colombier static char buf[4*1024]; 1783e12c5d1SDavid du Colombier 1793e12c5d1SDavid du Colombier /* 1803e12c5d1SDavid du Colombier * are we past eof? 1813e12c5d1SDavid du Colombier */ 1823e12c5d1SDavid du Colombier if(offset >= mp->size) 1833e12c5d1SDavid du Colombier return 0; 1843e12c5d1SDavid du Colombier 1853e12c5d1SDavid du Colombier /* 1863e12c5d1SDavid du Colombier * are we in the virtual memory portion? 1873e12c5d1SDavid du Colombier */ 1883e12c5d1SDavid du Colombier if(offset < mp->body->ptr - mp->body->base){ 1893e12c5d1SDavid du Colombier *pp = mp->body->base + offset; 1903e12c5d1SDavid du Colombier return mp->body->ptr - mp->body->base - offset; 1913e12c5d1SDavid du Colombier } 1923e12c5d1SDavid du Colombier 1933e12c5d1SDavid du Colombier /* 1943e12c5d1SDavid du Colombier * read it from the temp file 1953e12c5d1SDavid du Colombier */ 1963e12c5d1SDavid du Colombier offset -= mp->body->ptr - mp->body->base; 1973e12c5d1SDavid du Colombier if(mp->fd < 0) 1983e12c5d1SDavid du Colombier return -1; 1993e12c5d1SDavid du Colombier if(seek(mp->fd, offset, 0)<0) 2003e12c5d1SDavid du Colombier return -1; 2013e12c5d1SDavid du Colombier *pp = buf; 2023e12c5d1SDavid du Colombier return read(mp->fd, buf, sizeof buf); 2033e12c5d1SDavid du Colombier } 2043e12c5d1SDavid du Colombier 2053e12c5d1SDavid du Colombier /* output the message body without ^From escapes */ 2063e12c5d1SDavid du Colombier static int 2073e12c5d1SDavid du Colombier m_noescape(message *mp, Biobuf *fp) 2083e12c5d1SDavid du Colombier { 2093e12c5d1SDavid du Colombier long offset; 2103e12c5d1SDavid du Colombier int n; 2113e12c5d1SDavid du Colombier char *p; 2123e12c5d1SDavid du Colombier 2133e12c5d1SDavid du Colombier for(offset = 0; offset < mp->size; offset += n){ 2143e12c5d1SDavid du Colombier n = m_get(mp, offset, &p); 2153e12c5d1SDavid du Colombier if(n <= 0){ 2163e12c5d1SDavid du Colombier Bflush(fp); 2173e12c5d1SDavid du Colombier return -1; 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier if(Bwrite(fp, p, n) < 0) 2203e12c5d1SDavid du Colombier return -1; 2213e12c5d1SDavid du Colombier } 2223e12c5d1SDavid du Colombier return Bflush(fp); 2233e12c5d1SDavid du Colombier } 2243e12c5d1SDavid du Colombier 2253e12c5d1SDavid du Colombier /* 226*219b2ee8SDavid du Colombier * Output the message body with '^From ' escapes. 227*219b2ee8SDavid du Colombier * Ensures that any line starting with a 'From ' gets a ' ' stuck 2283e12c5d1SDavid du Colombier * in front of it. 2293e12c5d1SDavid du Colombier */ 2303e12c5d1SDavid du Colombier static int 2313e12c5d1SDavid du Colombier m_escape(message *mp, Biobuf *fp) 2323e12c5d1SDavid du Colombier { 233*219b2ee8SDavid du Colombier char *p, *np; 234*219b2ee8SDavid du Colombier char *end; 2353e12c5d1SDavid du Colombier long offset; 236*219b2ee8SDavid du Colombier int m, n; 2373e12c5d1SDavid du Colombier char *start; 2383e12c5d1SDavid du Colombier 2393e12c5d1SDavid du Colombier for(offset = 0; offset < mp->size; offset += n){ 2403e12c5d1SDavid du Colombier n = m_get(mp, offset, &start); 2413e12c5d1SDavid du Colombier if(n < 0){ 2423e12c5d1SDavid du Colombier Bflush(fp); 2433e12c5d1SDavid du Colombier return -1; 2443e12c5d1SDavid du Colombier } 2453e12c5d1SDavid du Colombier 2463e12c5d1SDavid du Colombier p = start; 247*219b2ee8SDavid du Colombier for(end = p+n; p < end; p += m){ 248*219b2ee8SDavid du Colombier np = memchr(p, '\n', end-p); 249*219b2ee8SDavid du Colombier if(np == 0){ 250*219b2ee8SDavid du Colombier Bwrite(fp, p, end-p); 2513e12c5d1SDavid du Colombier break; 2523e12c5d1SDavid du Colombier } 253*219b2ee8SDavid du Colombier m = np - p + 1; 254*219b2ee8SDavid du Colombier if(m > 5 && strncmp(p, "From ", 5) == 0) 255*219b2ee8SDavid du Colombier Bputc(fp, ' '); 256*219b2ee8SDavid du Colombier Bwrite(fp, p, m); 2573e12c5d1SDavid du Colombier } 2583e12c5d1SDavid du Colombier } 2593e12c5d1SDavid du Colombier Bflush(fp); 2603e12c5d1SDavid du Colombier return 0; 2613e12c5d1SDavid du Colombier } 2623e12c5d1SDavid du Colombier 2633e12c5d1SDavid du Colombier /* output a message */ 2643e12c5d1SDavid du Colombier extern int 2653e12c5d1SDavid du Colombier m_print(message *mp, Biobuf *fp, char *remote, int mbox) 2663e12c5d1SDavid du Colombier { 2673e12c5d1SDavid du Colombier if (remote != 0){ 2683e12c5d1SDavid du Colombier if(print_remote_header(fp,s_to_c(mp->sender),s_to_c(mp->date),remote) < 0) 2693e12c5d1SDavid du Colombier return -1; 2703e12c5d1SDavid du Colombier } else { 2713e12c5d1SDavid du Colombier if(print_header(fp, s_to_c(mp->sender), s_to_c(mp->date)) < 0) 2723e12c5d1SDavid du Colombier return -1; 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier 2753e12c5d1SDavid du Colombier if (!mbox) 2763e12c5d1SDavid du Colombier return m_noescape(mp, fp); 2773e12c5d1SDavid du Colombier return m_escape(mp, fp); 2783e12c5d1SDavid du Colombier } 2793e12c5d1SDavid du Colombier 2803e12c5d1SDavid du Colombier /* print just the message body */ 2813e12c5d1SDavid du Colombier extern int 2823e12c5d1SDavid du Colombier m_bprint(message *mp, Biobuf *fp) 2833e12c5d1SDavid du Colombier { 2843e12c5d1SDavid du Colombier return m_noescape(mp, fp); 2853e12c5d1SDavid du Colombier } 286