qmail-start.c (3221B)
1 #include <sys/stat.h> 2 #include "fd.h" 3 #include "prot.h" 4 #include "exit.h" 5 #include "fork.h" 6 #include "noreturn.h" 7 #include "uidgid.h" 8 #include "auto_uids.h" 9 #include "auto_users.h" 10 11 char *(qsargs[]) = { "qmail-send", 0 }; 12 char *(qcargs[]) = { "qmail-clean", 0 }; 13 char *(qlargs[]) = { "qmail-lspawn", "./Mailbox", 0 }; 14 char *(qrargs[]) = { "qmail-rspawn", 0 }; 15 16 void _noreturn_ die() { _exit(111); } 17 18 int pi0[2]; 19 int pi1[2]; 20 int pi2[2]; 21 int pi3[2]; 22 int pi4[2]; 23 int pi5[2]; 24 int pi6[2]; 25 26 uid_t auto_uidl; 27 uid_t auto_uidq; 28 uid_t auto_uidr; 29 uid_t auto_uids; 30 31 gid_t auto_gidn; 32 gid_t auto_gidq; 33 34 void close23456() { close(2); close(3); close(4); close(5); close(6); } 35 36 void closepipes() { 37 close(pi1[0]); close(pi1[1]); close(pi2[0]); close(pi2[1]); 38 close(pi3[0]); close(pi3[1]); close(pi4[0]); close(pi4[1]); 39 close(pi5[0]); close(pi5[1]); close(pi6[0]); close(pi6[1]); 40 } 41 42 int main(int argc, char **argv) 43 { 44 if (chdir("/") == -1) die(); 45 umask(077); 46 47 auto_uidl = inituid(auto_userl); 48 auto_uidq = inituid(auto_userq); 49 auto_uidr = inituid(auto_userr); 50 auto_uids = inituid(auto_users); 51 52 auto_gidn = initgid(auto_groupn); 53 auto_gidq = initgid(auto_groupq); 54 55 if (prot_gid(auto_gidq) == -1) die(); 56 57 if (fd_copy(2,0) == -1) die(); 58 if (fd_copy(3,0) == -1) die(); 59 if (fd_copy(4,0) == -1) die(); 60 if (fd_copy(5,0) == -1) die(); 61 if (fd_copy(6,0) == -1) die(); 62 63 if (argv[1]) { 64 qlargs[1] = argv[1]; 65 ++argv; 66 } 67 68 // logger 69 if (argv[1]) { 70 if (pipe(pi0) == -1) die(); 71 switch(fork()) { 72 case -1: 73 die(); 74 case 0: 75 if (prot_gid(auto_gidn) == -1) die(); 76 if (prot_uid(auto_uidl) == -1) die(); 77 close(pi0[1]); 78 if (fd_move(0,pi0[0]) == -1) die(); 79 close23456(); 80 execvp(argv[1],argv + 1); 81 die(); 82 } 83 close(pi0[0]); 84 if (fd_move(1,pi0[1]) == -1) die(); 85 } 86 87 if (pipe(pi1) == -1) die(); 88 if (pipe(pi2) == -1) die(); 89 if (pipe(pi3) == -1) die(); 90 if (pipe(pi4) == -1) die(); 91 if (pipe(pi5) == -1) die(); 92 if (pipe(pi6) == -1) die(); 93 94 // channelspawn: local 95 switch(fork()) { 96 case -1: die(); 97 case 0: 98 if (fd_copy(0,pi1[0]) == -1) die(); 99 if (fd_copy(1,pi2[1]) == -1) die(); 100 close23456(); 101 closepipes(); 102 execvp(*qlargs,qlargs); 103 die(); 104 } 105 106 // channelspawn: remote 107 switch(fork()) { 108 case -1: die(); 109 case 0: 110 if (prot_uid(auto_uidr) == -1) die(); 111 if (fd_copy(0,pi3[0]) == -1) die(); 112 if (fd_copy(1,pi4[1]) == -1) die(); 113 close23456(); 114 closepipes(); 115 execvp(*qrargs,qrargs); 116 die(); 117 } 118 119 // cleanup 120 switch(fork()) { 121 case -1: die(); 122 case 0: 123 if (prot_uid(auto_uidq) == -1) die(); 124 if (fd_copy(0,pi5[0]) == -1) die(); 125 if (fd_copy(1,pi6[1]) == -1) die(); 126 close23456(); 127 closepipes(); 128 execvp(*qcargs,qcargs); 129 die(); 130 } 131 132 // exec into qmsend 133 if (prot_uid(auto_uids) == -1) die(); 134 if (fd_copy(0,1) == -1) die(); 135 if (fd_copy(1,pi1[1]) == -1) die(); 136 if (fd_copy(2,pi2[0]) == -1) die(); 137 if (fd_copy(3,pi3[1]) == -1) die(); 138 if (fd_copy(4,pi4[0]) == -1) die(); 139 if (fd_copy(5,pi5[1]) == -1) die(); 140 if (fd_copy(6,pi6[0]) == -1) die(); 141 closepipes(); 142 execvp(*qsargs,qsargs); 143 die(); 144 }