3 * $Id: ipc_win32.cc,v 1.1 2006/09/03 18:47:18 serassio Exp $
5 * DEBUG: section 54 Windows Interprocess Communication
6 * AUTHOR: Andrey Shorin & Guido Serassio
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
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.
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.
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
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
39 #include "SquidTime.h"
52 struct sockaddr_in PS
;
66 static unsigned int __stdcall
ipc_thread_1(void *params
);
67 static unsigned int __stdcall
ipc_thread_2(void *params
);
69 static const char *ok_string
= "OK\n";
70 static const char *err_string
= "ERR\n";
71 static const char *shutdown_string
= "$shutdown\n";
73 static const char *hello_string
= "hi there\n";
74 #define HELLO_BUF_SZ 32
75 static char hello_buf
[HELLO_BUF_SZ
];
78 ipcCloseAllFD(int prfd
, int pwfd
, int crfd
, int cwfd
)
103 env_str
= (char *)xcalloc((tmp_s
= strlen(Config
.debugOptions
) + 32), 1);
104 snprintf(env_str
, tmp_s
, "SQUID_DEBUG=%s", Config
.debugOptions
);
110 ipcCreate(int type
, const char *prog
, const char *const args
[], const char *name
, int *rfd
, int *wfd
, void **hIpc
)
112 unsigned long thread
;
114 struct ipc_params params
;
116 int optlen
= sizeof(opt
);
120 struct sockaddr_in CS
;
122 struct sockaddr_in PS
;
130 requirePathnameExists(name
, prog
);
141 if (WIN32_OS_version
!= _WIN_OS_WINNT
) {
142 getsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, &optlen
);
143 opt
= opt
& ~(SO_SYNCHRONOUS_NONALERT
| SO_SYNCHRONOUS_ALERT
);
144 setsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, sizeof(opt
));
147 if (type
== IPC_TCP_SOCKET
) {
148 crfd
= cwfd
= comm_open(SOCK_STREAM
,
154 prfd
= pwfd
= comm_open(SOCK_STREAM
,
155 IPPROTO_TCP
, /* protocol */
160 } else if (type
== IPC_UDP_SOCKET
) {
161 crfd
= cwfd
= comm_open(SOCK_DGRAM
,
167 prfd
= pwfd
= comm_open(SOCK_DGRAM
,
173 } else if (type
== IPC_FIFO
) {
175 ("ipcCreate: %s: use IPC_TCP_SOCKET instead of IP_FIFO on Windows\n",
182 debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd
);
183 debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd
);
184 debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd
);
185 debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd
);
187 if (WIN32_OS_version
!= _WIN_OS_WINNT
) {
188 getsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, &optlen
);
189 opt
= opt
| SO_SYNCHRONOUS_NONALERT
;
190 setsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, optlen
);
194 debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
195 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
199 debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
200 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
203 if (type
== IPC_TCP_SOCKET
|| type
== IPC_UDP_SOCKET
) {
205 memset(&PS
, '\0', len
);
207 if (getsockname(pwfd
, (struct sockaddr
*) &PS
, &len
) < 0) {
208 debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
209 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
212 debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
213 pwfd
, inet_ntoa(PS
.sin_addr
), ntohs(PS
.sin_port
));
215 memset(&CS
, '\0', len
);
217 if (getsockname(crfd
, (struct sockaddr
*) &CS
, &len
) < 0) {
218 debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
219 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
222 debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
223 crfd
, inet_ntoa(CS
.sin_addr
), ntohs(CS
.sin_port
));
226 if (type
== IPC_TCP_SOCKET
) {
227 if (listen(crfd
, 1) < 0) {
228 debug(54, 1) ("ipcCreate: listen FD %d: %s\n", crfd
, xstrerror());
229 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
232 debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd
);
235 /* flush or else we get dup data if unbuffered_logs is set */
248 params
.args
= (char **) args
;
250 thread
= _beginthreadex(NULL
, 0, ipc_thread_1
, ¶ms
, 0, NULL
);
253 debug(54, 1) ("ipcCreate: _beginthread: %s\n", xstrerror());
254 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
257 if (comm_connect_addr(pwfd
, &CS
) == COMM_ERROR
) {
258 CloseHandle((HANDLE
) thread
);
259 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
262 memset(hello_buf
, '\0', HELLO_BUF_SZ
);
263 x
= recv(prfd
, (void *)hello_buf
, HELLO_BUF_SZ
- 1, 0);
266 debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
267 debug(54, 0) ("--> read: %s\n", xstrerror());
268 CloseHandle((HANDLE
) thread
);
269 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
270 } else if (strcmp(hello_buf
, hello_string
)) {
271 debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
272 debug(54, 0) ("--> read returned %d\n", x
);
273 debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf
));
274 CloseHandle((HANDLE
) thread
);
275 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
278 x
= send(pwfd
, (const void *)ok_string
, strlen(ok_string
), 0);
281 debug(54, 0) ("ipcCreate: PARENT: OK write test failed\n");
282 debug(54, 0) ("--> read: %s\n", xstrerror());
283 CloseHandle((HANDLE
) thread
);
284 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
287 memset(hello_buf
, '\0', HELLO_BUF_SZ
);
288 x
= recv(prfd
, (void *)hello_buf
, HELLO_BUF_SZ
- 1, 0);
291 debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
292 debug(54, 0) ("--> read: %s\n", xstrerror());
293 CloseHandle((HANDLE
) thread
);
294 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
295 } else if (!strcmp(hello_buf
, err_string
)) {
296 debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
297 debug(54, 0) ("--> read returned %d\n", x
);
298 debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf
));
299 CloseHandle((HANDLE
) thread
);
300 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
304 pid
= atol(hello_buf
);
305 commSetTimeout(prfd
, -1, NULL
, NULL
);
306 commSetNonBlocking(prfd
);
307 commSetNonBlocking(pwfd
);
308 commSetCloseOnExec(prfd
);
309 commSetCloseOnExec(pwfd
);
317 fd_table
[prfd
].flags
.ipc
= 1;
319 fd_table
[pwfd
].flags
.ipc
= 1;
321 fd_table
[crfd
].flags
.ipc
= 1;
323 fd_table
[cwfd
].flags
.ipc
= 1;
325 if (Config
.sleep_after_fork
) {
326 /* XXX emulation of usleep() */
328 sl
= Config
.sleep_after_fork
/ 1000;
336 if (GetExitCodeThread((HANDLE
) thread
, &ecode
) && ecode
== STILL_ACTIVE
) {
338 *hIpc
= (HANDLE
) thread
;
342 CloseHandle((HANDLE
) thread
);
343 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
348 ipcSend(int cwfd
, const char *buf
, int len
)
352 x
= send(cwfd
, (const void *)buf
, len
, 0);
355 debug(54, 0) ("sendto FD %d: %s\n", cwfd
, xstrerror());
356 debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
362 static unsigned int __stdcall
363 ipc_thread_1(void *in_params
)
365 int t1
, t2
, t3
, retval
= -1;
370 HANDLE hProcess
= NULL
, thread
= NULL
;
373 struct thread_params thread_params
;
378 PROCESS_INFORMATION pi
;
380 int prfd_ipc
= -1, pwfd_ipc
= -1, crfd_ipc
= -1, cwfd_ipc
= -1;
381 char *prog
= NULL
, *buf1
= NULL
;
383 struct sockaddr_in CS_ipc
, PS_ipc
;
385 struct ipc_params
*params
= (struct ipc_params
*) in_params
;
386 int type
= params
->type
;
387 int crfd
= params
->crfd
;
388 int cwfd
= params
->cwfd
;
389 char **args
= params
->args
;
391 struct sockaddr_in PS
= params
->PS
;
394 buf1
= (char *)xcalloc(1, 8192);
395 strcpy(buf1
, params
->prog
);
396 prog
= strtok(buf1
, w_space
);
398 if ((str
= strrchr(prog
, '/')))
401 if ((str
= strrchr(prog
, '\\')))
404 prog
= xstrdup(prog
);
406 if (type
== IPC_TCP_SOCKET
) {
407 debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd
);
409 if ((fd
= accept(crfd
, NULL
, NULL
)) < 0) {
410 debug(54, 0) ("ipcCreate: FD %d accept: %s\n", crfd
, xstrerror());
414 debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd
);
416 snprintf(buf1
, 8191, "%s CHILD socket", prog
);
417 fd_open(fd
, FD_SOCKET
, buf1
);
418 fd_table
[fd
].flags
.ipc
= 1;
420 } else if (type
== IPC_UDP_SOCKET
) {
421 if (comm_connect_addr(crfd
, &PS
) == COMM_ERROR
)
425 x
= send(cwfd
, (const void *)hello_string
, strlen(hello_string
) + 1, 0);
428 debug(54, 0) ("sendto FD %d: %s\n", cwfd
, xstrerror());
429 debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
434 memset(buf1
, '\0', sizeof(buf1
));
435 x
= recv(crfd
, (void *)buf1
, 8191, 0);
438 debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
439 debug(54, 0) ("--> read: %s\n", xstrerror());
441 } else if (strcmp(buf1
, ok_string
)) {
442 debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
443 debug(54, 0) ("--> read returned %d\n", x
);
444 debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf
));
448 /* assign file descriptors to child process */
449 if (_pipe(p2c
, 1024, _O_BINARY
| _O_NOINHERIT
) < 0) {
450 debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
451 ipcSend(cwfd
, err_string
, strlen(err_string
));
455 if (_pipe(c2p
, 1024, _O_BINARY
| _O_NOINHERIT
) < 0) {
456 debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
457 ipcSend(cwfd
, err_string
, strlen(err_string
));
461 if (type
== IPC_UDP_SOCKET
) {
462 snprintf(buf1
, 8192, "%s(%ld) <-> ipc CHILD socket", prog
, -1L);
463 crfd_ipc
= cwfd_ipc
= comm_open(SOCK_DGRAM
, IPPROTO_UDP
, local_addr
, 0, 0, buf1
);
466 debug(54, 0) ("ipcCreate: CHILD: Failed to create child FD for %s.\n",
468 ipcSend(cwfd
, err_string
, strlen(err_string
));
472 snprintf(buf1
, 8192, "%s(%ld) <-> ipc PARENT socket", prog
, -1L);
473 prfd_ipc
= pwfd_ipc
= comm_open(SOCK_DGRAM
, IPPROTO_UDP
, local_addr
, 0, 0, buf1
);
476 debug(54, 0) ("ipcCreate: CHILD: Failed to create server FD for %s.\n",
478 ipcSend(cwfd
, err_string
, strlen(err_string
));
482 tmp_s
= sizeof(PS_ipc
);
483 memset(&PS_ipc
, '\0', tmp_s
);
485 if (getsockname(pwfd_ipc
, (struct sockaddr
*) &PS_ipc
, &tmp_s
) < 0) {
486 debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
487 ipcSend(cwfd
, err_string
, strlen(err_string
));
491 debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
492 pwfd_ipc
, inet_ntoa(PS_ipc
.sin_addr
), ntohs(PS_ipc
.sin_port
));
493 tmp_s
= sizeof(CS_ipc
);
494 memset(&CS_ipc
, '\0', tmp_s
);
496 if (getsockname(crfd_ipc
, (struct sockaddr
*) &CS_ipc
, &tmp_s
) < 0) {
497 debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
498 ipcSend(cwfd
, err_string
, strlen(err_string
));
502 debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
503 crfd_ipc
, inet_ntoa(CS_ipc
.sin_addr
), ntohs(CS_ipc
.sin_port
));
505 if (comm_connect_addr(pwfd_ipc
, &CS_ipc
) == COMM_ERROR
) {
506 ipcSend(cwfd
, err_string
, strlen(err_string
));
512 if (comm_connect_addr(crfd_ipc
, &PS_ipc
) == COMM_ERROR
) {
513 ipcSend(cwfd
, err_string
, strlen(err_string
));
516 } /* IPC_UDP_SOCKET */
528 dup2(fileno(debug_log
), 2);
534 commUnsetNonBlocking(fd
);
536 memset(&si
, 0, sizeof(STARTUPINFO
));
538 si
.cb
= sizeof(STARTUPINFO
);
540 si
.hStdInput
= (HANDLE
) _get_osfhandle(0);
542 si
.hStdOutput
= (HANDLE
) _get_osfhandle(1);
544 si
.hStdError
= (HANDLE
) _get_osfhandle(2);
546 si
.dwFlags
= STARTF_USESTDHANDLES
;
548 /* Make sure all other valid handles are not inerithable */
549 for (x
= 3; x
< Squid_MaxFD
; x
++) {
550 if ((F
= _get_osfhandle(x
)) == -1)
553 SetHandleInformation((HANDLE
) F
, HANDLE_FLAG_INHERIT
, 0);
557 strcpy(buf1
+ 4096, params
->prog
);
558 str
= strtok(buf1
+ 4096, w_space
);
563 } while ((str
= strtok(NULL
, w_space
)));
568 strcat(buf1
, args
[x
++]);
572 if (CreateProcess(buf1
+ 4096, buf1
, NULL
, NULL
, TRUE
, CREATE_NO_WINDOW
,
573 NULL
, NULL
, &si
, &pi
)) {
574 pid
= pi
.dwProcessId
;
575 hProcess
= pi
.hProcess
;
578 WIN32_maperror(GetLastError());
591 debug(54, 0) ("ipcCreate: CHILD: %s: %s\n", params
->prog
, xstrerror());
592 ipcSend(cwfd
, err_string
, strlen(err_string
));
596 if (type
== IPC_UDP_SOCKET
) {
597 WSAPROTOCOL_INFO wpi
;
599 memset(&wpi
, 0, sizeof(wpi
));
601 if (SOCKET_ERROR
== WSADuplicateSocket(crfd_ipc
, pid
, &wpi
)) {
602 debug(54, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n",
604 ipcSend(cwfd
, err_string
, strlen(err_string
));
608 x
= write(c2p
[1], (const char *) &wpi
, sizeof(wpi
));
610 if (x
< (ssize_t
)sizeof(wpi
)) {
611 debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p
[1],
613 debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
615 ipcSend(cwfd
, err_string
, strlen(err_string
));
619 x
= read(p2c
[0], buf1
, 8192);
622 debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c
[0],
624 debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
626 ipcSend(cwfd
, err_string
, strlen(err_string
));
628 } else if (strncmp(buf1
, ok_string
, strlen(ok_string
))) {
629 debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
631 debug(54, 0) ("--> read returned %d\n", x
);
633 debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1
));
634 ipcSend(cwfd
, err_string
, strlen(err_string
));
638 x
= write(c2p
[1], (const char *) &PS_ipc
, sizeof(PS_ipc
));
640 if (x
< (ssize_t
)sizeof(PS_ipc
)) {
641 debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p
[1],
643 debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
645 ipcSend(cwfd
, err_string
, strlen(err_string
));
649 x
= read(p2c
[0], buf1
, 8192);
652 debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c
[0],
654 debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
656 ipcSend(cwfd
, err_string
, strlen(err_string
));
658 } else if (strncmp(buf1
, ok_string
, strlen(ok_string
))) {
659 debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
661 debug(54, 0) ("--> read returned %d\n", x
);
663 debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1
));
664 ipcSend(cwfd
, err_string
, strlen(err_string
));
668 x
= send(pwfd_ipc
, (const void *)ok_string
, strlen(ok_string
), 0);
669 x
= recv(prfd_ipc
, (void *)(buf1
+ 200), 8191 - 200, 0);
670 assert((size_t) x
== strlen(ok_string
)
671 && !strncmp(ok_string
, buf1
+ 200, strlen(ok_string
)));
672 } /* IPC_UDP_SOCKET */
674 snprintf(buf1
, 8191, "%s(%ld) CHILD socket", prog
, (long int) pid
);
678 if (prfd_ipc
!= -1) {
679 snprintf(buf1
, 8191, "%s(%ld) <-> ipc CHILD socket", prog
, (long int) pid
);
680 fd_note(crfd_ipc
, buf1
);
681 snprintf(buf1
, 8191, "%s(%ld) <-> ipc PARENT socket", prog
, (long int) pid
);
682 fd_note(prfd_ipc
, buf1
);
685 /* else { IPC_TCP_SOCKET */
686 /* commSetNoLinger(fd); */
688 thread_params
.prog
= prog
;
690 thread_params
.send_fd
= cwfd
;
692 thread_params
.pid
= pid
;
694 if ((thread_params
.type
= type
) == IPC_TCP_SOCKET
)
695 thread_params
.rfd
= p2c
[0];
697 thread_params
.rfd
= prfd_ipc
;
700 (HANDLE
) _beginthreadex(NULL
, 0, ipc_thread_2
, &thread_params
, 0, NULL
);
703 debug(54, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror());
704 ipcSend(cwfd
, err_string
, strlen(err_string
));
708 snprintf(buf1
, 8191, "%ld\n", (long int) pid
);
710 if (-1 == ipcSend(cwfd
, buf1
, strlen(buf1
)))
713 debug(54, 2) ("ipc(%s,%ld): started successfully\n", prog
, (long int) pid
);
717 x
= recv(crfd
, (void *)buf1
, 8192, 0);
720 debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n",
727 if (type
== IPC_UDP_SOCKET
&& !strcmp(buf1
, shutdown_string
)) {
729 ("ipc(%s,%d): request for shutdown received from parent. Exiting...\n",
731 TerminateProcess(hProcess
, 0);
735 debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", prog
, pid
,
736 rfc1738_escape_unescaped(buf1
));
738 if (type
== IPC_TCP_SOCKET
)
739 x
= write(c2p
[1], buf1
, x
);
741 x
= send(pwfd_ipc
, (const void *)buf1
, x
, 0);
744 debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n",
757 if (fd_table
[crfd
].flags
.open
)
758 ipcCloseAllFD(-1, -1, crfd
, cwfd
);
760 if (prfd_ipc
!= -1) {
761 send(crfd_ipc
, (const void *)shutdown_string
, strlen(shutdown_string
), 0);
762 shutdown(crfd_ipc
, SD_BOTH
);
763 shutdown(prfd_ipc
, SD_BOTH
);
766 ipcCloseAllFD(prfd_ipc
, pwfd_ipc
, crfd_ipc
, cwfd_ipc
);
768 if (hProcess
&& WAIT_OBJECT_0
!=
769 WaitForSingleObject(hProcess
, type
== IPC_UDP_SOCKET
? 12000 : 5000)) {
772 debug(54, 0) ("ipc(%s,%d): WARNING: %s didn't exit in %d seconds.\n",
773 prog
, pid
, prog
, type
== IPC_UDP_SOCKET
? 12 : 5);
776 if (thread
&& WAIT_OBJECT_0
!= WaitForSingleObject(thread
, 3000)) {
779 ("ipc(%s,%d): WARNING: ipc_thread_2 didn't exit in 3 seconds.\n",
786 debug(54, 2) ("ipc(%s,%d): normal exit\n", prog
, pid
);
798 CloseHandle(hProcess
);
806 static unsigned int __stdcall
807 ipc_thread_2(void *in_params
)
811 struct thread_params
*params
= (struct thread_params
*) in_params
;
812 int type
= params
->type
;
813 int rfd
= params
->rfd
;
814 int send_fd
= params
->send_fd
;
815 char *prog
= xstrdup(params
->prog
);
816 pid_t pid
= params
->pid
;
817 char *buf2
= (char *)xcalloc(1, 8192);
820 if (type
== IPC_TCP_SOCKET
)
821 x
= read(rfd
, buf2
, 8192);
823 x
= recv(rfd
, (void *)buf2
, 8192, 0);
825 if ((x
<= 0 && type
== IPC_TCP_SOCKET
) ||
826 (x
< 0 && type
== IPC_UDP_SOCKET
)) {
827 debug(54, 3) ("ipc(%s,%d): %d bytes read from %s. Exiting...\n",
834 if (type
== IPC_UDP_SOCKET
&& !strcmp(buf2
, shutdown_string
)) {
835 debug(54, 3) ("ipc(%s,%d): request for shutdown received. Exiting...\n",
841 if ((buf2
[x
- 1] == '\n') && (buf2
[x
- 2] == '\r')) {
848 debug(54, 5) ("ipc(%s,%d): received from child : %s\n", prog
, pid
,
849 rfc1738_escape_unescaped(buf2
));
850 x
= send(send_fd
, (const void *)buf2
, x
, 0);
852 if ((x
<= 0 && type
== IPC_TCP_SOCKET
) ||
853 (x
< 0 && type
== IPC_UDP_SOCKET
)) {
854 debug(54, 3) ("ipc(%s,%d): %d bytes sent to parent. Exiting...\n",