ipc.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:8k
源码类别:

代理服务器

开发平台:

Unix_Linux

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