]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ipc.cc
2.1 branch merge
[thirdparty/squid.git] / src / ipc.cc
CommitLineData
b13bbe1c 1
2/*
c68e9c6b 3 * $Id: ipc.cc,v 1.12 1998/11/12 06:28:12 wessels Exp $
b13bbe1c 4 *
5 * DEBUG: section 54 Interprocess Communication
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
e25c139f 9 * ----------------------------------------------------------
b13bbe1c 10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
e25c139f 13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
b13bbe1c 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
b13bbe1c 34 */
35
36#include "squid.h"
37
38static const char *hello_string = "hi there\n";
39#define HELLO_BUF_SZ 32
40static char hello_buf[HELLO_BUF_SZ];
41
42static int
43ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd)
44{
45 if (prfd >= 0)
46 comm_close(prfd);
47 if (prfd != pwfd)
48 if (pwfd >= 0)
49 comm_close(pwfd);
50 if (crfd >= 0)
51 comm_close(crfd);
52 if (crfd != cwfd)
53 if (cwfd >= 0)
54 comm_close(cwfd);
55 return -1;
56}
57
58int
59ipcCreate(int type, const char *prog, char *const args[], const char *name, int *rfd, int *wfd)
60{
61 pid_t pid;
62 struct sockaddr_in CS;
63 struct sockaddr_in PS;
64 int crfd = -1;
65 int prfd = -1;
66 int cwfd = -1;
67 int pwfd = -1;
68 int fd;
6637e3a5 69 socklen_t len;
b13bbe1c 70 int tmp_s;
c68e9c6b 71#if HAVE_PUTENV
b13bbe1c 72 char *env_str;
c68e9c6b 73#endif
b13bbe1c 74 int x;
75
91ef94d6 76#if HAVE_POLL && defined(_SQUID_OSF_)
77 assert(type != IPC_FIFO);
78#endif
79
b13bbe1c 80 if (rfd)
81 *rfd = -1;
82 if (wfd)
83 *wfd = -1;
84 if (type == IPC_TCP_SOCKET) {
85 crfd = cwfd = comm_open(SOCK_STREAM,
86 0,
87 local_addr,
88 0,
89 COMM_NOCLOEXEC,
90 name);
91 prfd = pwfd = comm_open(SOCK_STREAM,
92 0, /* protocol */
93 local_addr,
94 0, /* port */
95 0, /* blocking */
96 name);
97 } else if (type == IPC_UDP_SOCKET) {
98 crfd = cwfd = comm_open(SOCK_DGRAM,
99 0,
100 local_addr,
101 0,
102 COMM_NOCLOEXEC,
103 name);
104 prfd = pwfd = comm_open(SOCK_DGRAM,
105 0,
106 local_addr,
107 0,
108 0,
109 name);
110 } else if (type == IPC_FIFO) {
111 int p2c[2];
112 int c2p[2];
113 if (pipe(p2c) < 0) {
114 debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
115 return -1;
116 }
117 if (pipe(c2p) < 0) {
118 debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
119 return -1;
120 }
121 fd_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read");
122 fd_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write");
123 fd_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read");
124 fd_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write");
125 } else {
126 assert(IPC_NONE);
127 }
128 debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd);
129 debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd);
130 debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd);
131 debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd);
132
133 if (crfd < 0) {
134 debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
135 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
136 }
137 if (pwfd < 0) {
138 debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
139 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
140 }
141 if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
142 len = sizeof(PS);
143 memset(&PS, '\0', len);
144 if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) {
145 debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
146 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
147 }
148 debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
149 pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port));
150 len = sizeof(CS);
151 memset(&CS, '\0', len);
152 if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) {
153 debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
154 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
155 }
156 debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
157 crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port));
158 }
159 if (type == IPC_TCP_SOCKET) {
160 if (listen(crfd, 1) < 0) {
0e473d70 161 debug(50, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror());
b13bbe1c 162 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
163 }
164 debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd);
165 }
b13bbe1c 166 /* flush or else we get dup data if unbuffered_logs is set */
167 logsFlush();
168 if ((pid = fork()) < 0) {
a60f7062 169 debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror());
b13bbe1c 170 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
171 }
172 if (pid > 0) { /* parent */
173 /* close shared socket with child */
174 comm_close(crfd);
175 if (cwfd != crfd)
176 comm_close(cwfd);
177 cwfd = crfd = -1;
178 if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
179 if (comm_connect_addr(pwfd, &CS) == COMM_ERROR)
180 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
181 }
182 memset(hello_buf, '\0', HELLO_BUF_SZ);
183 if (type == IPC_UDP_SOCKET)
09ab2125 184 x = recv(prfd, hello_buf, HELLO_BUF_SZ, 0);
b13bbe1c 185 else
09ab2125 186 x = read(prfd, hello_buf, HELLO_BUF_SZ);
b13bbe1c 187 if (x < 0) {
188 debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n");
189 debug(50, 0) ("--> read: %s\n", xstrerror());
190 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
191 } else if (strcmp(hello_buf, hello_string)) {
6f6f0853 192 debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
193 debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
b13bbe1c 194 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
195 }
196 commSetTimeout(prfd, -1, NULL, NULL);
197 commSetNonBlocking(prfd);
198 commSetNonBlocking(pwfd);
199 if (rfd)
200 *rfd = prfd;
201 if (wfd)
202 *wfd = pwfd;
de718ec4 203 fd_table[prfd].flags.ipc = 1;
204 fd_table[pwfd].flags.ipc = 1;
b13bbe1c 205 return pwfd;
206 }
207 /* child */
208 no_suid(); /* give up extra priviliges */
209 /* close shared socket with parent */
210 comm_close(prfd);
211 if (pwfd != prfd)
212 comm_close(pwfd);
213 pwfd = prfd = -1;
214
215 if (type == IPC_TCP_SOCKET) {
216 debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
217 if ((fd = accept(crfd, NULL, NULL)) < 0) {
218 debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
219 _exit(1);
220 }
221 debug(54, 3) ("ipcCreate: accepted new FD %d\n", fd);
222 close(crfd);
223 cwfd = crfd = fd;
224 } else if (type == IPC_UDP_SOCKET) {
0e473d70 225 if (comm_connect_addr(crfd, &PS) == COMM_ERROR)
226 return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
b13bbe1c 227 }
b13bbe1c 228 if (type == IPC_UDP_SOCKET) {
229 x = send(cwfd, hello_string, strlen(hello_string), 0);
230 if (x < 0) {
231 debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
232 debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
233 _exit(1);
234 }
235 } else {
236 if (write(cwfd, hello_string, strlen(hello_string)) < 0) {
237 debug(50, 0) ("write FD %d: %s\n", cwfd, xstrerror());
238 debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
239 _exit(1);
240 }
241 }
c68e9c6b 242#if HAVE_PUTENV
b13bbe1c 243 env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
244 snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
245 putenv(env_str);
c68e9c6b 246#endif
b13bbe1c 247 dup2(crfd, 0);
248 dup2(cwfd, 1);
249 dup2(fileno(debug_log), 2);
250 fclose(debug_log);
251 /*
252 * Solaris pthreads seems to close FD 0 upon fork(), so don't close
253 * this FD if its 0, 1, or 2.
254 * -- Michael O'Reilly <michael@metal.iinet.net.au>
255 */
256 if (crfd > 2)
257 close(crfd);
258 if (cwfd != crfd)
259 if (cwfd > 2)
260 close(cwfd);
c1f0aa2e 261#if HAVE_SETSID
262 setsid();
263#endif
b13bbe1c 264 execvp(prog, args);
265 debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror());
266 _exit(1);
267 return 0;
268}