13e12c5d1SDavid du Colombier #include "common.h" 23e12c5d1SDavid du Colombier #include "send.h" 33e12c5d1SDavid du Colombier 43e12c5d1SDavid du Colombier /* globals to all files */ 53e12c5d1SDavid du Colombier int rmail; 6*219b2ee8SDavid du Colombier char *thissys, *altthissys; 73e12c5d1SDavid du Colombier int nflg; 83e12c5d1SDavid du Colombier int xflg; 93e12c5d1SDavid du Colombier int debug; 103e12c5d1SDavid du Colombier int rflg; 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier /* global to this file */ 133e12c5d1SDavid du Colombier static String *errstring; 143e12c5d1SDavid du Colombier static message *mp; 153e12c5d1SDavid du Colombier static int interrupt; 163e12c5d1SDavid du Colombier static int savemail; 173e12c5d1SDavid du Colombier static Biobuf in; 183e12c5d1SDavid du Colombier 193e12c5d1SDavid du Colombier /* predeclared */ 203e12c5d1SDavid du Colombier static int send(dest *, message *, int); 213e12c5d1SDavid du Colombier static void lesstedious(void); 223e12c5d1SDavid du Colombier static void save_mail(message *); 233e12c5d1SDavid du Colombier static int complain_mail(dest *, message *); 243e12c5d1SDavid du Colombier static int pipe_mail(dest *, message *); 253e12c5d1SDavid du Colombier static int cat_mail(dest *, message *); 263e12c5d1SDavid du Colombier static void appaddr(String *, dest *); 273e12c5d1SDavid du Colombier static int refuse(dest *, message *, char *, int); 283e12c5d1SDavid du Colombier static void mkerrstring(String *, message *, dest *, dest *, char *, int); 293e12c5d1SDavid du Colombier static int replymsg(String *, message *, dest *); 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier void 323e12c5d1SDavid du Colombier main(int argc, char *argv[]) 333e12c5d1SDavid du Colombier { 343e12c5d1SDavid du Colombier dest *dp=0; 353e12c5d1SDavid du Colombier int checkforward; 363e12c5d1SDavid du Colombier char *base; 37*219b2ee8SDavid du Colombier int rv, holding; 38*219b2ee8SDavid du Colombier 39*219b2ee8SDavid du Colombier srand(time(0)); 403e12c5d1SDavid du Colombier 413e12c5d1SDavid du Colombier /* process args */ 423e12c5d1SDavid du Colombier ARGBEGIN{ 433e12c5d1SDavid du Colombier case '#': 443e12c5d1SDavid du Colombier nflg = 1; 453e12c5d1SDavid du Colombier break; 463e12c5d1SDavid du Colombier case 'x': 473e12c5d1SDavid du Colombier nflg = 1; 483e12c5d1SDavid du Colombier xflg = 1; 493e12c5d1SDavid du Colombier break; 503e12c5d1SDavid du Colombier case 'd': 513e12c5d1SDavid du Colombier debug = 1; 523e12c5d1SDavid du Colombier break; 533e12c5d1SDavid du Colombier case 'r': 543e12c5d1SDavid du Colombier rflg = 1; 553e12c5d1SDavid du Colombier break; 563e12c5d1SDavid du Colombier default: 573e12c5d1SDavid du Colombier fprint(2, "usage: mail [-x] list-of-addresses\n"); 583e12c5d1SDavid du Colombier exit(1); 593e12c5d1SDavid du Colombier }ARGEND 603e12c5d1SDavid du Colombier 613e12c5d1SDavid du Colombier while(*argv) 623e12c5d1SDavid du Colombier d_insert(&dp, d_new(s_copy(*argv++))); 633e12c5d1SDavid du Colombier 643e12c5d1SDavid du Colombier if (dp == 0) { 653e12c5d1SDavid du Colombier fprint(2, "usage: mail [-#] address-list\n"); 663e12c5d1SDavid du Colombier exit(1); 673e12c5d1SDavid du Colombier } 683e12c5d1SDavid du Colombier 693e12c5d1SDavid du Colombier /* 703e12c5d1SDavid du Colombier * get context: 713e12c5d1SDavid du Colombier * - whether we're rmail or mail 723e12c5d1SDavid du Colombier */ 733e12c5d1SDavid du Colombier base = basename(argv0); 743e12c5d1SDavid du Colombier checkforward = rmail = (strcmp(base, "rmail")==0) | rflg; 753e12c5d1SDavid du Colombier thissys = sysname_read(); 76*219b2ee8SDavid du Colombier altthissys = alt_sysname_read(); 773e12c5d1SDavid du Colombier 783e12c5d1SDavid du Colombier /* 793e12c5d1SDavid du Colombier * read the mail. If an interrupt occurs while reading, save in 803e12c5d1SDavid du Colombier * dead.letter 813e12c5d1SDavid du Colombier */ 823e12c5d1SDavid du Colombier if (!nflg) { 833e12c5d1SDavid du Colombier Binit(&in, 0, OREAD); 84*219b2ee8SDavid du Colombier if(rmail) 853e12c5d1SDavid du Colombier mp = m_read(&in, rmail); 86*219b2ee8SDavid du Colombier else { 87*219b2ee8SDavid du Colombier holding = holdon(); 88*219b2ee8SDavid du Colombier mp = m_read(&in, rmail); 89*219b2ee8SDavid du Colombier holdoff(holding); 90*219b2ee8SDavid du Colombier } 913e12c5d1SDavid du Colombier if (mp == 0) 923e12c5d1SDavid du Colombier exit(0); 933e12c5d1SDavid du Colombier if (interrupt != 0) { 943e12c5d1SDavid du Colombier save_mail(mp); 953e12c5d1SDavid du Colombier exit(1); 963e12c5d1SDavid du Colombier } 973e12c5d1SDavid du Colombier } else { 983e12c5d1SDavid du Colombier mp = m_new(); 993e12c5d1SDavid du Colombier default_from(mp); 1003e12c5d1SDavid du Colombier } 1013e12c5d1SDavid du Colombier errstring = s_new(); 1023e12c5d1SDavid du Colombier getrules(); 1033e12c5d1SDavid du Colombier 1043e12c5d1SDavid du Colombier /* 1053e12c5d1SDavid du Colombier * If this is a gateway, translate the sender address into a local 1063e12c5d1SDavid du Colombier * address. This only happens if mail to the local address is 1073e12c5d1SDavid du Colombier * forwarded to the sender. 1083e12c5d1SDavid du Colombier */ 1093e12c5d1SDavid du Colombier gateway(mp); 1103e12c5d1SDavid du Colombier 1113e12c5d1SDavid du Colombier /* 1123e12c5d1SDavid du Colombier * Protect against shell characters in the sender name for 1133e12c5d1SDavid du Colombier * security reasons. 1143e12c5d1SDavid du Colombier */ 1153e12c5d1SDavid du Colombier USE(s_restart(mp->sender)); 1163e12c5d1SDavid du Colombier if (shellchars(s_to_c(mp->sender))) 1173e12c5d1SDavid du Colombier mp->replyaddr = s_copy("postmaster"); 1183e12c5d1SDavid du Colombier else 1193e12c5d1SDavid du Colombier mp->replyaddr = s_clone(mp->sender); 1203e12c5d1SDavid du Colombier USE(s_restart(mp->replyaddr)); 1213e12c5d1SDavid du Colombier 1223e12c5d1SDavid du Colombier /* 1233e12c5d1SDavid du Colombier * reject messages that are too long. We don't do it earlier 1243e12c5d1SDavid du Colombier * in m_read since we haven't set up enough things yet. 1253e12c5d1SDavid du Colombier */ 1263e12c5d1SDavid du Colombier if(mp->size < 0) 1273e12c5d1SDavid du Colombier exit(refuse(dp, mp, "message too long", 0)); 1283e12c5d1SDavid du Colombier 1293e12c5d1SDavid du Colombier rv = send(dp, mp, checkforward); 1303e12c5d1SDavid du Colombier if(savemail) 1313e12c5d1SDavid du Colombier save_mail(mp); 1323e12c5d1SDavid du Colombier if(mp) 1333e12c5d1SDavid du Colombier m_free(mp); 1343e12c5d1SDavid du Colombier exit(rv); 1353e12c5d1SDavid du Colombier } 1363e12c5d1SDavid du Colombier 1373e12c5d1SDavid du Colombier 138*219b2ee8SDavid du Colombier 1393e12c5d1SDavid du Colombier /* send a message to a list of sites */ 1403e12c5d1SDavid du Colombier static int 1413e12c5d1SDavid du Colombier send(dest *destp, message *mp, int checkforward) 1423e12c5d1SDavid du Colombier { 1433e12c5d1SDavid du Colombier dest *dp; /* destination being acted upon */ 1443e12c5d1SDavid du Colombier dest *bound; /* bound destinations */ 1453e12c5d1SDavid du Colombier int errors=0; 1463e12c5d1SDavid du Colombier static int forked; 1473e12c5d1SDavid du Colombier 1483e12c5d1SDavid du Colombier /* bind the destinations to actions */ 1493e12c5d1SDavid du Colombier bound = up_bind(destp, mp, checkforward); 1503e12c5d1SDavid du Colombier 1513e12c5d1SDavid du Colombier /* loop through and execute commands */ 1523e12c5d1SDavid du Colombier for (dp = d_rm(&bound); dp != 0; dp = d_rm(&bound)) { 1533e12c5d1SDavid du Colombier switch (dp->status) { 1543e12c5d1SDavid du Colombier case d_cat: 1553e12c5d1SDavid du Colombier errors += cat_mail(dp, mp); 1563e12c5d1SDavid du Colombier break; 1573e12c5d1SDavid du Colombier case d_pipeto: 1583e12c5d1SDavid du Colombier case d_pipe: 1593e12c5d1SDavid du Colombier if (!rmail && !nflg && !forked) { 1603e12c5d1SDavid du Colombier forked = 1; 1613e12c5d1SDavid du Colombier lesstedious(); 1623e12c5d1SDavid du Colombier } 1633e12c5d1SDavid du Colombier errors += pipe_mail(dp, mp); 1643e12c5d1SDavid du Colombier break; 1653e12c5d1SDavid du Colombier default: 1663e12c5d1SDavid du Colombier errors += complain_mail(dp, mp); 1673e12c5d1SDavid du Colombier break; 1683e12c5d1SDavid du Colombier } 1693e12c5d1SDavid du Colombier } 1703e12c5d1SDavid du Colombier 1713e12c5d1SDavid du Colombier return errors; 1723e12c5d1SDavid du Colombier } 1733e12c5d1SDavid du Colombier 1743e12c5d1SDavid du Colombier /* avoid user tedium (as Mike Lesk said in a previous version) */ 1753e12c5d1SDavid du Colombier static void 1763e12c5d1SDavid du Colombier lesstedious(void) 1773e12c5d1SDavid du Colombier { 1783e12c5d1SDavid du Colombier int i; 1793e12c5d1SDavid du Colombier 1803e12c5d1SDavid du Colombier if(debug) 1813e12c5d1SDavid du Colombier return; 182*219b2ee8SDavid du Colombier 1833e12c5d1SDavid du Colombier switch(fork()){ 1843e12c5d1SDavid du Colombier case -1: 1853e12c5d1SDavid du Colombier break; 1863e12c5d1SDavid du Colombier case 0: 1873e12c5d1SDavid du Colombier rfork(RFENVG|RFNAMEG|RFNOTEG); 1883e12c5d1SDavid du Colombier for(i=0; i<nsysfile; i++) 1893e12c5d1SDavid du Colombier close(i); 1903e12c5d1SDavid du Colombier savemail = 0; 1913e12c5d1SDavid du Colombier break; 1923e12c5d1SDavid du Colombier default: 1933e12c5d1SDavid du Colombier exit(0); 1943e12c5d1SDavid du Colombier } 1953e12c5d1SDavid du Colombier } 1963e12c5d1SDavid du Colombier 1973e12c5d1SDavid du Colombier 1983e12c5d1SDavid du Colombier /* save the mail */ 1993e12c5d1SDavid du Colombier static void 2003e12c5d1SDavid du Colombier save_mail(message *mp) 2013e12c5d1SDavid du Colombier { 2023e12c5d1SDavid du Colombier Biobuf *fp; 2033e12c5d1SDavid du Colombier String *file; 2043e12c5d1SDavid du Colombier static saved = 0; 2053e12c5d1SDavid du Colombier 2063e12c5d1SDavid du Colombier file = s_new(); 2073e12c5d1SDavid du Colombier mboxpath("dead.letter", getlog(), file, 0); 2083e12c5d1SDavid du Colombier if ((fp = sysopen(s_to_c(file), "cA", 0660)) == 0) 2093e12c5d1SDavid du Colombier return; 2103e12c5d1SDavid du Colombier m_bprint(mp, fp); 2113e12c5d1SDavid du Colombier sysclose(fp); 2123e12c5d1SDavid du Colombier fprint(2, "saved in %s\n", s_to_c(file)); 2133e12c5d1SDavid du Colombier s_free(file); 2143e12c5d1SDavid du Colombier } 2153e12c5d1SDavid du Colombier 2163e12c5d1SDavid du Colombier /* remember the interrupt happened */ 2173e12c5d1SDavid du Colombier /* dispose of incorrect addresses */ 2183e12c5d1SDavid du Colombier static int 2193e12c5d1SDavid du Colombier complain_mail(dest *dp, message *mp) 2203e12c5d1SDavid du Colombier { 2213e12c5d1SDavid du Colombier char *msg; 2223e12c5d1SDavid du Colombier 2233e12c5d1SDavid du Colombier switch (dp->status) { 2243e12c5d1SDavid du Colombier case d_undefined: 2253e12c5d1SDavid du Colombier msg = "Invalid address"; /* a little different, for debugging */ 2263e12c5d1SDavid du Colombier break; 2273e12c5d1SDavid du Colombier case d_syntax: 2283e12c5d1SDavid du Colombier msg = "invalid address"; 2293e12c5d1SDavid du Colombier break; 2303e12c5d1SDavid du Colombier case d_unknown: 2313e12c5d1SDavid du Colombier msg = "unknown user"; 2323e12c5d1SDavid du Colombier break; 2333e12c5d1SDavid du Colombier case d_eloop: 2343e12c5d1SDavid du Colombier case d_loop: 2353e12c5d1SDavid du Colombier msg = "forwarding loop"; 2363e12c5d1SDavid du Colombier break; 2373e12c5d1SDavid du Colombier case d_noforward: 2383e12c5d1SDavid du Colombier if(dp->pstat && *s_to_c(dp->repl2)) 2393e12c5d1SDavid du Colombier return refuse(dp, mp, s_to_c(dp->repl2), dp->pstat); 2403e12c5d1SDavid du Colombier else 2413e12c5d1SDavid du Colombier msg = "destination unknown or forwarding disallowed"; 2423e12c5d1SDavid du Colombier break; 2433e12c5d1SDavid du Colombier case d_pipe: 2443e12c5d1SDavid du Colombier msg = "broken pipe"; 2453e12c5d1SDavid du Colombier break; 2463e12c5d1SDavid du Colombier case d_cat: 2473e12c5d1SDavid du Colombier msg = "broken cat"; 2483e12c5d1SDavid du Colombier break; 2493e12c5d1SDavid du Colombier case d_translate: 2503e12c5d1SDavid du Colombier if(dp->pstat && *s_to_c(dp->repl2)) 2513e12c5d1SDavid du Colombier return refuse(dp, mp, s_to_c(dp->repl2), dp->pstat); 2523e12c5d1SDavid du Colombier else 2533e12c5d1SDavid du Colombier msg = "name translation failed"; 2543e12c5d1SDavid du Colombier break; 2553e12c5d1SDavid du Colombier case d_alias: 2563e12c5d1SDavid du Colombier msg = "broken alias"; 2573e12c5d1SDavid du Colombier break; 2583e12c5d1SDavid du Colombier case d_badmbox: 2593e12c5d1SDavid du Colombier msg = "corrupted mailbox"; 2603e12c5d1SDavid du Colombier break; 2613e12c5d1SDavid du Colombier case d_resource: 2623e12c5d1SDavid du Colombier msg = "out of some resource. Try again later."; 2633e12c5d1SDavid du Colombier break; 2643e12c5d1SDavid du Colombier default: 2653e12c5d1SDavid du Colombier msg = "unknown d_"; 2663e12c5d1SDavid du Colombier break; 2673e12c5d1SDavid du Colombier } 2683e12c5d1SDavid du Colombier if (nflg) { 2693e12c5d1SDavid du Colombier print("%s: %s\n", msg, s_to_c(dp->addr)); 2703e12c5d1SDavid du Colombier return 0; 2713e12c5d1SDavid du Colombier } 2723e12c5d1SDavid du Colombier return refuse(dp, mp, msg, 0); 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier 2753e12c5d1SDavid du Colombier /* dispose of remote addresses */ 2763e12c5d1SDavid du Colombier static int 2773e12c5d1SDavid du Colombier pipe_mail(dest *dp, message *mp) 2783e12c5d1SDavid du Colombier { 2793e12c5d1SDavid du Colombier String *file; 2803e12c5d1SDavid du Colombier dest *next, *list=0; 2813e12c5d1SDavid du Colombier String *cmd; 2823e12c5d1SDavid du Colombier process *pp; 283bd389b36SDavid du Colombier int status, none; 2843e12c5d1SDavid du Colombier String *errstring=s_new(); 2853e12c5d1SDavid du Colombier 286bd389b36SDavid du Colombier none = dp->status == d_pipeto; 2873e12c5d1SDavid du Colombier /* 2883e12c5d1SDavid du Colombier * collect the arguments 2893e12c5d1SDavid du Colombier */ 2903e12c5d1SDavid du Colombier file = s_new(); 2913e12c5d1SDavid du Colombier abspath(s_to_c(dp->addr), MAILROOT, file); 2923e12c5d1SDavid du Colombier next = d_rm_same(&dp); 2933e12c5d1SDavid du Colombier if(xflg) 2943e12c5d1SDavid du Colombier cmd = s_new(); 2953e12c5d1SDavid du Colombier else 2963e12c5d1SDavid du Colombier cmd = s_clone(s_restart(next->repl1)); 2973e12c5d1SDavid du Colombier for(; next != 0; next = d_rm_same(&dp)){ 2983e12c5d1SDavid du Colombier if(xflg){ 2993e12c5d1SDavid du Colombier s_append(cmd, s_to_c(next->addr)); 3003e12c5d1SDavid du Colombier s_append(cmd, "\n"); 3013e12c5d1SDavid du Colombier } else { 3023e12c5d1SDavid du Colombier if (next->repl2 != 0) { 3033e12c5d1SDavid du Colombier s_append(cmd, " "); 3043e12c5d1SDavid du Colombier s_append(cmd, s_to_c(next->repl2)); 3053e12c5d1SDavid du Colombier } 3063e12c5d1SDavid du Colombier } 3073e12c5d1SDavid du Colombier d_insert(&list, next); 3083e12c5d1SDavid du Colombier } 3093e12c5d1SDavid du Colombier 3103e12c5d1SDavid du Colombier if (nflg) { 3113e12c5d1SDavid du Colombier if(xflg) 3123e12c5d1SDavid du Colombier print("%s", s_to_c(cmd)); 3133e12c5d1SDavid du Colombier else 3143e12c5d1SDavid du Colombier print("%s\n", s_to_c(cmd)); 3153e12c5d1SDavid du Colombier s_free(cmd); 3163e12c5d1SDavid du Colombier s_free(file); 3173e12c5d1SDavid du Colombier return 0; 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier 3203e12c5d1SDavid du Colombier /* 3213e12c5d1SDavid du Colombier * run the process 3223e12c5d1SDavid du Colombier */ 323bd389b36SDavid du Colombier pp = proc_start(s_to_c(cmd), instream(), 0, outstream(), 1, none); 3243e12c5d1SDavid du Colombier if(pp==0 || pp->std[0]==0 || pp->std[2]==0) 3253e12c5d1SDavid du Colombier return refuse(list, mp, "out of processes, pipes, or memory", 0); 3263e12c5d1SDavid du Colombier m_print(mp, pp->std[0]->fp, thissys, 0); 3273e12c5d1SDavid du Colombier stream_free(pp->std[0]); 3283e12c5d1SDavid du Colombier pp->std[0] = 0; 3293e12c5d1SDavid du Colombier while(s_read_line(pp->std[2]->fp, errstring)) 3303e12c5d1SDavid du Colombier ; 3313e12c5d1SDavid du Colombier status = proc_wait(pp); 3323e12c5d1SDavid du Colombier proc_free(pp); 3333e12c5d1SDavid du Colombier s_free(cmd); 3343e12c5d1SDavid du Colombier 3353e12c5d1SDavid du Colombier /* 3363e12c5d1SDavid du Colombier * return status 3373e12c5d1SDavid du Colombier */ 3383e12c5d1SDavid du Colombier if (status != 0) 3393e12c5d1SDavid du Colombier return refuse(list, mp, s_to_c(errstring), status); 3403e12c5d1SDavid du Colombier loglist(list, mp, "remote"); 3413e12c5d1SDavid du Colombier return 0; 3423e12c5d1SDavid du Colombier } 3433e12c5d1SDavid du Colombier 3443e12c5d1SDavid du Colombier /* dispose of local addresses */ 3453e12c5d1SDavid du Colombier static int 3463e12c5d1SDavid du Colombier cat_mail(dest *dp, message *mp) 3473e12c5d1SDavid du Colombier { 3483e12c5d1SDavid du Colombier Biobuf *fp; 3493e12c5d1SDavid du Colombier char *rcvr, *cp; 3503e12c5d1SDavid du Colombier Lock *l; 3513e12c5d1SDavid du Colombier String *tmp; 3523e12c5d1SDavid du Colombier 3533e12c5d1SDavid du Colombier if (nflg) { 3543e12c5d1SDavid du Colombier if(!xflg) 3553e12c5d1SDavid du Colombier print("cat >> %s\n", s_to_c(dp->repl1)); 3563e12c5d1SDavid du Colombier else 3573e12c5d1SDavid du Colombier print("%s\n", s_to_c(dp->addr)); 3583e12c5d1SDavid du Colombier return 0; 3593e12c5d1SDavid du Colombier } 3603e12c5d1SDavid du Colombier l = lock(s_to_c(dp->repl1)); 3613e12c5d1SDavid du Colombier if(l == 0) 3623e12c5d1SDavid du Colombier return refuse(dp, mp, "can't lock mail file", 0); 3633e12c5d1SDavid du Colombier fp = sysopen(s_to_c(dp->repl1), "cal", MBOXMODE); 3643e12c5d1SDavid du Colombier if (fp == 0){ 3653e12c5d1SDavid du Colombier tmp = s_append(0, s_to_c(dp->repl1)); 3663e12c5d1SDavid du Colombier s_append(tmp, ".tmp"); 3673e12c5d1SDavid du Colombier fp = sysopen(s_to_c(tmp), "cal", MBOXMODE); 3683e12c5d1SDavid du Colombier if(fp == 0){ 3693e12c5d1SDavid du Colombier unlock(l); 3703e12c5d1SDavid du Colombier return refuse(dp, mp, "mail file cannot be opened", 0); 3713e12c5d1SDavid du Colombier } 3723e12c5d1SDavid du Colombier syslog(0, "mail", "error: used %s", s_to_c(tmp)); 3733e12c5d1SDavid du Colombier s_free(tmp); 3743e12c5d1SDavid du Colombier } 3753e12c5d1SDavid du Colombier if(m_print(mp, fp, (char *)0, 1) < 0 376*219b2ee8SDavid du Colombier || Bprint(fp, "\n") < 0 3773e12c5d1SDavid du Colombier || Bflush(fp) < 0){ 3783e12c5d1SDavid du Colombier sysclose(fp); 3793e12c5d1SDavid du Colombier unlock(l); 3803e12c5d1SDavid du Colombier return refuse(dp, mp, "error writing mail file", 0); 3813e12c5d1SDavid du Colombier } 3823e12c5d1SDavid du Colombier sysclose(fp); 3833e12c5d1SDavid du Colombier unlock(l); 3843e12c5d1SDavid du Colombier rcvr = s_to_c(dp->addr); 3853e12c5d1SDavid du Colombier if(cp = strrchr(rcvr, '!')) 3863e12c5d1SDavid du Colombier rcvr = cp+1; 3873e12c5d1SDavid du Colombier logdelivery(dp, rcvr, mp); 3883e12c5d1SDavid du Colombier return 0; 3893e12c5d1SDavid du Colombier } 3903e12c5d1SDavid du Colombier 3913e12c5d1SDavid du Colombier static void 3923e12c5d1SDavid du Colombier appaddr(String *sp, dest *dp) 3933e12c5d1SDavid du Colombier { 3943e12c5d1SDavid du Colombier dest *parent; 3953e12c5d1SDavid du Colombier 3963e12c5d1SDavid du Colombier if (dp->parent != 0) { 3973e12c5d1SDavid du Colombier for(parent=dp->parent; parent->parent!=0; parent=parent->parent) 3983e12c5d1SDavid du Colombier ; 3993e12c5d1SDavid du Colombier s_append(sp, s_to_c(parent->addr)); 4003e12c5d1SDavid du Colombier s_append(sp, "' alias `"); 4013e12c5d1SDavid du Colombier } 4023e12c5d1SDavid du Colombier s_append(sp, s_to_c(dp->addr)); 4033e12c5d1SDavid du Colombier } 4043e12c5d1SDavid du Colombier 4053e12c5d1SDavid du Colombier /* reject delivery */ 4063e12c5d1SDavid du Colombier static int 4073e12c5d1SDavid du Colombier refuse(dest *list, message *mp, char *cp, int status) 4083e12c5d1SDavid du Colombier { 4093e12c5d1SDavid du Colombier String *errstring=s_new(); 4103e12c5d1SDavid du Colombier dest *dp; 4113e12c5d1SDavid du Colombier int rv; 4123e12c5d1SDavid du Colombier 4133e12c5d1SDavid du Colombier dp = d_rm(&list); 4143e12c5d1SDavid du Colombier mkerrstring(errstring, mp, dp, list, cp, status); 415*219b2ee8SDavid du Colombier 4163e12c5d1SDavid du Colombier /* 4173e12c5d1SDavid du Colombier * if on a tty just report the error. Otherwise send mail 4183e12c5d1SDavid du Colombier * reporting the error. N.B. To avoid mail loops, don't 4193e12c5d1SDavid du Colombier * send mail reporting a failure of mail to reach the postmaster. 4203e12c5d1SDavid du Colombier */ 421*219b2ee8SDavid du Colombier if (!rmail) { 4223e12c5d1SDavid du Colombier fprint(2, "%s\n", s_to_c(errstring)); 4233e12c5d1SDavid du Colombier savemail = 1; 4243e12c5d1SDavid du Colombier rv = 1; 4253e12c5d1SDavid du Colombier } else { 4263e12c5d1SDavid du Colombier if (strcmp(s_to_c(mp->replyaddr), "postmaster")!=0) 4273e12c5d1SDavid du Colombier rv = replymsg(errstring, mp, dp); 4283e12c5d1SDavid du Colombier else 4293e12c5d1SDavid du Colombier rv = 1; 4303e12c5d1SDavid du Colombier } 4313e12c5d1SDavid du Colombier logrefusal(dp, mp, s_to_c(errstring)); 4323e12c5d1SDavid du Colombier s_free(errstring); 4333e12c5d1SDavid du Colombier return rv; 4343e12c5d1SDavid du Colombier } 4353e12c5d1SDavid du Colombier 4363e12c5d1SDavid du Colombier /* make the error message */ 4373e12c5d1SDavid du Colombier static void 4383e12c5d1SDavid du Colombier mkerrstring(String *errstring, message *mp, dest *dp, dest *list, char *cp, int status) 4393e12c5d1SDavid du Colombier { 4403e12c5d1SDavid du Colombier dest *next; 4413e12c5d1SDavid du Colombier char smsg[64]; 4423e12c5d1SDavid du Colombier 4433e12c5d1SDavid du Colombier /* list all aliases */ 4443e12c5d1SDavid du Colombier s_append(errstring, "Mail to `"); 4453e12c5d1SDavid du Colombier appaddr(errstring, dp); 4463e12c5d1SDavid du Colombier for(next = d_rm(&list); next != 0; next = d_rm(&list)) { 4473e12c5d1SDavid du Colombier s_append(errstring, "', '"); 4483e12c5d1SDavid du Colombier appaddr(errstring, next); 4493e12c5d1SDavid du Colombier d_insert(&dp, next); 4503e12c5d1SDavid du Colombier } 4513e12c5d1SDavid du Colombier s_append(errstring, "' from '"); 4523e12c5d1SDavid du Colombier s_append(errstring, s_to_c(mp->sender)); 4533e12c5d1SDavid du Colombier s_append(errstring, "' failed.\n"); 4543e12c5d1SDavid du Colombier 4553e12c5d1SDavid du Colombier /* >> and | deserve different flavored messages */ 4563e12c5d1SDavid du Colombier switch(dp->status) { 4573e12c5d1SDavid du Colombier case d_pipe: 4583e12c5d1SDavid du Colombier s_append(errstring, "The mailer `"); 4593e12c5d1SDavid du Colombier s_append(errstring, s_to_c(dp->repl1)); 4603e12c5d1SDavid du Colombier sprint(smsg, "' returned error status %x.\n", status); 4613e12c5d1SDavid du Colombier s_append(errstring, smsg); 4623e12c5d1SDavid du Colombier s_append(errstring, "The error message was:\n"); 4633e12c5d1SDavid du Colombier s_append(errstring, cp); 4643e12c5d1SDavid du Colombier break; 4653e12c5d1SDavid du Colombier default: 4663e12c5d1SDavid du Colombier s_append(errstring, "The error message was:\n"); 4673e12c5d1SDavid du Colombier s_append(errstring, cp); 4683e12c5d1SDavid du Colombier break; 4693e12c5d1SDavid du Colombier } 4703e12c5d1SDavid du Colombier } 4713e12c5d1SDavid du Colombier 4723e12c5d1SDavid du Colombier /* 4733e12c5d1SDavid du Colombier * reply with up to 1024 characters of the 4743e12c5d1SDavid du Colombier * original message 4753e12c5d1SDavid du Colombier */ 4763e12c5d1SDavid du Colombier static int 4773e12c5d1SDavid du Colombier replymsg(String *errstring, message *mp, dest *dp) 4783e12c5d1SDavid du Colombier { 4793e12c5d1SDavid du Colombier message *refp = m_new(); 4803e12c5d1SDavid du Colombier dest *ndp; 4813e12c5d1SDavid du Colombier char *rcvr; 4823e12c5d1SDavid du Colombier int rv; 4833e12c5d1SDavid du Colombier 4843e12c5d1SDavid du Colombier rcvr = dp->status==d_eloop ? "postmaster" : s_to_c(mp->replyaddr); 4853e12c5d1SDavid du Colombier ndp = d_new(s_copy(rcvr)); 4863e12c5d1SDavid du Colombier s_append(refp->sender, "postmaster"); 4873e12c5d1SDavid du Colombier s_append(refp->replyaddr, "postmaster"); 4883e12c5d1SDavid du Colombier s_append(refp->date, thedate()); 4893e12c5d1SDavid du Colombier s_append(refp->body, s_to_c(errstring)); 4903e12c5d1SDavid du Colombier s_append(refp->body, "\nThe message began:\n"); 4913e12c5d1SDavid du Colombier s_nappend(refp->body, s_to_c(mp->body), 8*1024); 4923e12c5d1SDavid du Colombier refp->size = strlen(s_to_c(refp->body)); 4933e12c5d1SDavid du Colombier rv = send(ndp, refp, 0); 4943e12c5d1SDavid du Colombier m_free(refp); 4953e12c5d1SDavid du Colombier d_free(ndp); 4963e12c5d1SDavid du Colombier return rv; 4973e12c5d1SDavid du Colombier } 498