qmail.c (4892B)
1 #include "qmail.h" 2 3 #include "substdio.h" 4 //#include "stralloc.h" 5 #include "readwrite.h" 6 #include "wait.h" 7 #include "exit.h" 8 #include "fork.h" 9 #include "fd.h" 10 #include "auto_qmail.h" 11 #include "env.h" 12 #include "fmt.h" 13 14 static char *binqqargs[2] = { 0, 0 } ; 15 16 static void setup_qqargs() 17 { 18 if(!binqqargs[0]) 19 binqqargs[0] = env_get("QMAILQUEUE"); 20 if(!binqqargs[0]) 21 binqqargs[0] = "bin/qmail-queue"; 22 } 23 24 int qmail_open(qq) 25 struct qmail *qq; 26 { 27 int pim[2]; 28 int pie[2]; 29 int pierr[2]; 30 31 setup_qqargs(); 32 33 if (pipe(pim) == -1) return -1; 34 if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; } 35 if (pipe(pierr) == -1) { 36 close(pim[0]); close(pim[1]); 37 close(pie[0]); close(pie[1]); 38 return -1; 39 } 40 41 switch(qq->pid = fork()) { 42 case -1: 43 close(pim[0]); close(pim[1]); 44 close(pie[0]); close(pie[1]); 45 close(pierr[0]); close(pierr[1]); 46 return -1; 47 case 0: 48 close(pim[1]); 49 close(pie[1]); 50 close(pierr[0]); /* we want to receive data */ 51 if (fd_move(0,pim[0]) == -1) _exit(120); 52 if (fd_move(1,pie[0]) == -1) _exit(120); 53 if (fd_move(6,pierr[1]) == -1) _exit(120); 54 if (chdir(auto_qmail) == -1) _exit(61); 55 execv(*binqqargs,binqqargs); 56 _exit(120); 57 } 58 59 qq->fdm = pim[1]; close(pim[0]); 60 qq->fde = pie[1]; close(pie[0]); 61 qq->fderr = pierr[0]; close(pierr[1]); 62 substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf)); 63 qq->flagerr = 0; 64 return 0; 65 } 66 67 unsigned long qmail_qp(qq) struct qmail *qq; 68 { 69 return qq->pid; 70 } 71 72 void qmail_fail(qq) struct qmail *qq; 73 { 74 qq->flagerr = 1; 75 } 76 77 void qmail_put(struct qmail *qq, char *s, size_t len) 78 { 79 if (!qq->flagerr) if (substdio_put(&qq->ss,s,len) == -1) qq->flagerr = 1; 80 } 81 82 void qmail_from(qq,s) struct qmail *qq; char *s; 83 { 84 if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1; 85 close(qq->fdm); 86 substdio_fdbuf(&qq->ss,write,qq->fde,qq->buf,sizeof(qq->buf)); 87 qmail_put(qq,"F",1); 88 qmail_puts(qq,s); 89 qmail_put(qq,"",1); 90 } 91 92 void qmail_to(qq,s) struct qmail *qq; char *s; 93 { 94 qmail_put(qq,"T",1); 95 qmail_puts(qq,s); 96 qmail_put(qq,"",1); 97 } 98 99 static size_t qmail_errstr(struct qmail *qq, char *s) { 100 size_t len = 0; 101 substdio_fdbuf(&qq->ss,read,qq->fderr,qq->buf,sizeof(qq->buf)); 102 while (substdio_get(&qq->ss,s+len,1) > 0 && len < 255) { 103 len++; 104 } 105 s[len] = '\0'; 106 return len; 107 } 108 109 char *qmail_close(qq) 110 struct qmail *qq; 111 { 112 int wstat; 113 int exitcode; 114 static char errstr[256]; 115 size_t errlen; 116 char excode[10]; 117 118 qmail_put(qq,"",1); 119 if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1; 120 close(qq->fde); 121 errlen = qmail_errstr(qq, errstr); 122 close(qq->fderr); 123 124 if (wait_pid(&wstat,qq->pid) != qq->pid) 125 return "Z4.3.0 qq waitpid surprise"; 126 if (wait_crashed(wstat)) 127 return "Z4.3.0 qq crashed"; 128 exitcode = wait_exitcode(wstat); 129 130 switch(exitcode) { 131 case 115: /* compatibility */ 132 case 11: return "D5.1.3 envelope address too long for qq"; 133 case 31: return "D5.3.0 mail server permanently rejected message"; 134 case 51: return "Z4.3.0 qq out of memory"; 135 case 52: return "Z4.3.0 qq timeout"; 136 case 53: return "Z4.3.0 qq write error or disk full"; 137 case 0: if (!qq->flagerr) return ""; /* fall through */ 138 case 54: return "Z4.3.0 qq read error"; 139 case 55: return "Z4.3.0 qq unable to read configuration"; 140 case 56: return "Z4.3.0 qq trouble making network connection"; 141 case 61: return "Z4.3.0 qq trouble in home directory"; 142 case 63: 143 case 64: 144 case 65: 145 case 66: 146 case 62: return "Z4.3.0 qq trouble creating files in queue"; 147 case 71: return "Z4.3.0 mail server temporarily rejected message"; 148 case 72: return "Z4.4.1 connection to mail server timed out"; 149 case 73: return "Z4.4.1 connection to mail server rejected"; 150 case 74: return "Z4.4.2 communication with mail server failed"; 151 case 91: /* fall through */ 152 case 81: return "Z4.3.0 qq internal bug"; 153 case 120: return "Z4.3.0 unable to exec qq"; 154 default: 155 if (exitcode == 82 && errlen > 2) 156 return errstr; 157 if ((exitcode >= 11) && (exitcode <= 40)) 158 return "D5.3.0 qq permanent problem"; 159 #if 0 // change this to zero when done please 160 if (!stralloc_copys(&exitstr, "Z4.3.0 qq temporary problem: exited with code ")) return "Z4.3.0 temporary problem + memory allocation failure"; 161 excode[fmt_ulong(excode, exitcode)] = 0; 162 if (!stralloc_cats(&exitstr, excode)) return "Z4.3.0 temporary problem + memory allocation failure"; 163 if (errlen > 2) { 164 if (!stralloc_cats(&exitstr, " and errstr of")) return "Z4.3.0 temporary problem + memory allocation failure"; 165 if (!stralloc_cats(&exitstr, errstr)) return "Z4.3.0 temporary problem + memory allocation failure"; 166 } 167 stralloc_0(&exitstr); 168 return exitstr.s; // dangling pointer 169 #else 170 return "Z4.3.0 qq temporary problem"; 171 #endif 172 } 173 }