Hi,
Here there is the Squid 2.6 MinGW support patch and the three new files needed.
Regards
Guido
-
========================================================
Guido Serassio
Acme Consulting S.r.l. - Microsoft Certified Partner
Via Lucia Savarino, 1 10098 - Rivoli (TO) - ITALY
Tel. : +39.011.9530135 Fax. : +39.011.9781115
Email: guido.serassio@acmeconsulting.it
WWW: http://www.acmeconsulting.it/
/*
* $Id$
*
* DEBUG: section 54 Interprocess Communication
* AUTHOR: Duane Wessels
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
* Squid is the result of efforts by numerous individuals from
* the Internet community; see the CONTRIBUTORS file for full
* details. Many organizations have provided support for Squid's
* development; see the SPONSORS file for full details. Squid is
* Copyrighted (C) 2001 by the Regents of the University of
* California; see the COPYRIGHT file for full details. Squid
* incorporates software developed and/or copyrighted by other
* sources; see the CREDITS file for full details.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#include "squid.h"
#ifndef _MSWSOCK_
#include <mswsock.h>
#endif
#include <process.h>
struct ipc_params {
int type;
int crfd;
int cwfd;
struct sockaddr_in PS;
const char *prog;
char **args;
};
struct thread_params {
int type;
int rfd;
int send_fd;
const char *prog;
pid_t pid;
};
static unsigned int __stdcall ipc_thread_1(void *params);
static unsigned int __stdcall ipc_thread_2(void *params);
static const char *ok_string = "OK\n";
static const char *err_string = "ERR\n";
static const char *shutdown_string = "$shutdown\n";
static const char *hello_string = "hi there\n";
#define HELLO_BUF_SZ 32
static char hello_buf[HELLO_BUF_SZ];
static int
ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd)
{
if (prfd >= 0)
comm_close(prfd);
if (prfd != pwfd)
if (pwfd >= 0)
comm_close(pwfd);
if (crfd >= 0)
comm_close(crfd);
if (crfd != cwfd)
if (cwfd >= 0)
comm_close(cwfd);
return -1;
}
int
ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, HANDLE * hIpc, pid_t * ppid)
{
unsigned long thread;
struct ipc_params params;
int opt;
int optlen = sizeof(opt);
DWORD ecode = 0;
pid_t pid;
struct sockaddr_in CS;
struct sockaddr_in PS;
int crfd = -1;
int prfd = -1;
int cwfd = -1;
int pwfd = -1;
socklen_t len;
int x;
requirePathnameExists(name, prog);
if (rfd)
*rfd = -1;
if (wfd)
*wfd = -1;
if (hIpc)
*hIpc = NULL;
if (ppid)
*ppid = -1;
if (WIN32_OS_version != _WIN_OS_WINNT) {
getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen);
opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT);
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, sizeof(opt));
}
if (type == IPC_TCP_SOCKET) {
crfd = cwfd = comm_open(SOCK_STREAM,
IPPROTO_TCP,
local_addr,
0,
COMM_NOCLOEXEC,
name);
prfd = pwfd = comm_open(SOCK_STREAM,
IPPROTO_TCP, /* protocol */
local_addr,
0, /* port */
0, /* blocking */
name);
} else if (type == IPC_UDP_SOCKET) {
crfd = cwfd = comm_open(SOCK_DGRAM,
IPPROTO_UDP,
local_addr,
0,
COMM_NOCLOEXEC,
name);
prfd = pwfd = comm_open(SOCK_DGRAM,
IPPROTO_UDP,
local_addr,
0,
0,
name);
} else if (type == IPC_FIFO) {
debug(54, 0)
("ipcCreate: %s: use IPC_TCP_SOCKET instead of IP_FIFO on Windows\n",
prog);
assert(0);
} else {
assert(IPC_NONE);
}
debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd);
debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd);
debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd);
debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd);
if (WIN32_OS_version != _WIN_OS_WINNT) {
getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen);
opt = opt | SO_SYNCHRONOUS_NONALERT;
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen);
}
if (crfd < 0) {
debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
}
if (pwfd < 0) {
debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
}
if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
len = sizeof(PS);
memset(&PS, '\0', len);
if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) {
debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
}
debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port));
len = sizeof(CS);
memset(&CS, '\0', len);
if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) {
debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
}
debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port));
}
if (type == IPC_TCP_SOCKET) {
if (listen(crfd, 1) < 0) {
debug(54, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror());
return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
}
debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd);
}
/* flush or else we get dup data if unbuffered_logs is set */
logsFlush();
params.type = type;
params.crfd = crfd;
params.cwfd = cwfd;
params.PS = PS;
params.prog = prog;
params.args = (char **) args;
thread = _beginthreadex(NULL, 0, ipc_thread_1, ¶ms, 0, NULL);
if (thread == 0) {
debug(54, 1) ("ipcCreate: _beginthread: %s\n", xstrerror());
return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
}
if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) {
CloseHandle((HANDLE) thread);
return ipcCloseAllFD(prfd, pwfd, -1, -1);
}
memset(hello_buf, '\0', HELLO_BUF_SZ);
x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
if (x < 0) {
debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
debug(54, 0) ("--> read: %s\n", xstrerror());
CloseHandle((HANDLE) thread);
return ipcCloseAllFD(prfd, pwfd, -1, -1);
} else if (strcmp(hello_buf, hello_string)) {
debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
debug(54, 0) ("--> read returned %d\n", x);
debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
CloseHandle((HANDLE) thread);
return ipcCloseAllFD(prfd, pwfd, -1, -1);
}
x = send(pwfd, ok_string, strlen(ok_string), 0);
if (x < 0) {
debug(54, 0) ("ipcCreate: PARENT: OK write test failed\n");
debug(54, 0) ("--> read: %s\n", xstrerror());
CloseHandle((HANDLE) thread);
return ipcCloseAllFD(prfd, pwfd, -1, -1);
}
memset(hello_buf, '\0', HELLO_BUF_SZ);
x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
if (x < 0) {
debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
debug(54, 0) ("--> read: %s\n", xstrerror());
CloseHandle((HANDLE) thread);
return ipcCloseAllFD(prfd, pwfd, -1, -1);
} else if (!strcmp(hello_buf, err_string)) {
debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
debug(54, 0) ("--> read returned %d\n", x);
debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
CloseHandle((HANDLE) thread);
return ipcCloseAllFD(prfd, pwfd, -1, -1);
}
hello_buf[x] = '\0';
pid = atol(hello_buf);
commSetTimeout(prfd, -1, NULL, NULL);
commSetNonBlocking(prfd);
commSetNonBlocking(pwfd);
commSetCloseOnExec(prfd);
commSetCloseOnExec(pwfd);
if (rfd)
*rfd = prfd;
if (wfd)
*wfd = pwfd;
fd_table[prfd].flags.ipc = 1;
fd_table[pwfd].flags.ipc = 1;
fd_table[crfd].flags.ipc = 1;
fd_table[cwfd].flags.ipc = 1;
if (Config.sleep_after_fork) {
/* XXX emulation of usleep() */
DWORD sl;
sl = Config.sleep_after_fork / 1000;
if (sl == 0)
sl = 1;
Sleep(sl);
}
if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) {
if (hIpc)
*hIpc = (HANDLE) thread;
if (ppid)
*ppid = pid;
return pwfd;
} else {
CloseHandle((HANDLE) thread);
return ipcCloseAllFD(prfd, pwfd, -1, -1);
}
}
static int
ipcSend(int cwfd, const char *buf, int len)
{
int x;
x = send(cwfd, buf, len, 0);
if (x < 0) {
debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
}
return x;
}
static unsigned int __stdcall
ipc_thread_1(void *in_params)
{
int t1, t2, t3, retval = -1;
int p2c[2] =
{-1, -1};
int c2p[2] =
{-1, -1};
HANDLE hProcess = NULL, thread = NULL;
pid_t pid = -1;
struct thread_params thread_params;
int x, tmp_s, fd = -1;
char *str;
#if HAVE_PUTENV
char *env_str = NULL;
#endif
STARTUPINFO si;
PROCESS_INFORMATION pi;
long F;
int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1;
char *prog = NULL, *buf1 = NULL;
struct sockaddr_in CS_ipc, PS_ipc;
struct ipc_params *params = (struct ipc_params *) in_params;
int type = params->type;
int crfd = params->crfd;
int cwfd = params->cwfd;
char **args = params->args;
struct sockaddr_in PS = params->PS;
buf1 = xcalloc(1, 8192);
strcpy(buf1, params->prog);
prog = strtok(buf1, w_space);
if ((str = strrchr(prog, '/')))
prog = ++str;
if ((str = strrchr(prog, '\\')))
prog = ++str;
prog = xstrdup(prog);
if (type == IPC_TCP_SOCKET) {
debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
if ((fd = accept(crfd, NULL, NULL)) < 0) {
debug(54, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
goto cleanup;
}
debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
comm_close(crfd);
snprintf(buf1, 8191, "%s CHILD socket", prog);
fd_open(fd, FD_SOCKET, buf1);
fd_table[fd].flags.ipc = 1;
cwfd = crfd = fd;
} else if (type == IPC_UDP_SOCKET) {
if (comm_connect_addr(crfd, &PS) == COMM_ERROR)
goto cleanup;
}
x = send(cwfd, hello_string, strlen(hello_string) + 1, 0);
if (x < 0) {
debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
goto cleanup;
}
#if HAVE_PUTENV
env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
putenv(env_str);
#endif
memset(buf1, '\0', sizeof(buf1));
x = recv(crfd, buf1, 8191, 0);
if (x < 0) {
debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
debug(54, 0) ("--> read: %s\n", xstrerror());
goto cleanup;
} else if (strcmp(buf1, ok_string)) {
debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
debug(54, 0) ("--> read returned %d\n", x);
debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
goto cleanup;
}
/* assign file descriptors to child process */
if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
if (type == IPC_UDP_SOCKET) {
snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", prog, -1L);
crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1);
if (crfd_ipc < 0) {
debug(54, 0) ("ipcCreate: CHILD: Failed to create child FD for %s.\n",
prog);
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", prog, -1L);
prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1);
if (pwfd_ipc < 0) {
debug(54, 0) ("ipcCreate: CHILD: Failed to create server FD for %s.\n",
prog);
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
tmp_s = sizeof(PS_ipc);
memset(&PS_ipc, '\0', tmp_s);
if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) {
debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
pwfd_ipc, inet_ntoa(PS_ipc.sin_addr), ntohs(PS_ipc.sin_port));
tmp_s = sizeof(CS_ipc);
memset(&CS_ipc, '\0', tmp_s);
if (getsockname(crfd_ipc, (struct sockaddr *) &CS_ipc, &tmp_s) < 0) {
debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
crfd_ipc, inet_ntoa(CS_ipc.sin_addr), ntohs(CS_ipc.sin_port));
if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) {
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
fd = crfd;
if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) {
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
} /* IPC_UDP_SOCKET */
t1 = dup(0);
t2 = dup(1);
t3 = dup(2);
dup2(c2p[0], 0);
dup2(p2c[1], 1);
dup2(fileno(debug_log), 2);
close(c2p[0]);
close(p2c[1]);
commUnsetNonBlocking(fd);
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.hStdInput = (HANDLE) _get_osfhandle(0);
si.hStdOutput = (HANDLE) _get_osfhandle(1);
si.hStdError = (HANDLE) _get_osfhandle(2);
si.dwFlags = STARTF_USESTDHANDLES;
/* Make sure all other valid handles are not inerithable */
for (x = 3; x < Squid_MaxFD; x++) {
if ((F = _get_osfhandle(x)) == -1)
continue;
SetHandleInformation((HANDLE) F, HANDLE_FLAG_INHERIT, 0);
}
*buf1 = '\0';
strcpy(buf1 + 4096, params->prog);
str = strtok(buf1 + 4096, w_space);
do {
strcat(buf1, str);
strcat(buf1, " ");
} while ((str = strtok(NULL, w_space)));
x = 1;
while (args[x]) {
strcat(buf1, args[x++]);
strcat(buf1, " ");
}
if (CreateProcess(buf1 + 4096, buf1, NULL, NULL, TRUE, CREATE_NO_WINDOW,
NULL, NULL, &si, &pi)) {
pid = pi.dwProcessId;
hProcess = pi.hProcess;
} else {
pid = -1;
WIN32_maperror(GetLastError());
x = errno;
}
dup2(t1, 0);
dup2(t2, 1);
dup2(t3, 2);
close(t1);
close(t2);
close(t3);
if (pid == -1) {
errno = x;
debug(54, 0) ("ipcCreate: CHILD: %s: %s\n", params->prog, xstrerror());
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
if (type == IPC_UDP_SOCKET) {
WSAPROTOCOL_INFO wpi;
memset(&wpi, 0, sizeof(wpi));
if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc, pid, &wpi)) {
debug(54, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n",
xstrerror());
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
x = write(c2p[1], (const char *) &wpi, sizeof(wpi));
if (x < sizeof(wpi)) {
debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
xstrerror());
debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
prog);
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
x = read(p2c[0], buf1, 8192);
if (x < 0) {
debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
xstrerror());
debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
prog);
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
} else if (strncmp(buf1, ok_string, strlen(ok_string))) {
debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
prog);
debug(54, 0) ("--> read returned %d\n", x);
buf1[x] = '\0';
debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
x = write(c2p[1], (const char *) &PS_ipc, sizeof(PS_ipc));
if (x < sizeof(PS_ipc)) {
debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
xstrerror());
debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
prog);
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
x = read(p2c[0], buf1, 8192);
if (x < 0) {
debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
xstrerror());
debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
prog);
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
} else if (strncmp(buf1, ok_string, strlen(ok_string))) {
debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
prog);
debug(54, 0) ("--> read returned %d\n", x);
buf1[x] = '\0';
debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
x = send(pwfd_ipc, ok_string, strlen(ok_string), 0);
x = recv(prfd_ipc, buf1 + 200, 8191 - 200, 0);
assert((size_t) x == strlen(ok_string)
&& !strncmp(ok_string, buf1 + 200, strlen(ok_string)));
} /* IPC_UDP_SOCKET */
snprintf(buf1, 8191, "%s(%ld) CHILD socket", prog, (long int) pid);
fd_note(fd, buf1);
if (prfd_ipc != -1) {
snprintf(buf1, 8191, "%s(%ld) <-> ipc CHILD socket", prog, (long int) pid);
fd_note(crfd_ipc, buf1);
snprintf(buf1, 8191, "%s(%ld) <-> ipc PARENT socket", prog, (long int) pid);
fd_note(prfd_ipc, buf1);
} /* else { // IPC_TCP_SOCKET
* * * * commSetNoLinger(fd);
* * * * }
*/
thread_params.prog = prog;
thread_params.send_fd = cwfd;
thread_params.pid = pid;
if ((thread_params.type = type) == IPC_TCP_SOCKET)
thread_params.rfd = p2c[0];
else
thread_params.rfd = prfd_ipc;
thread =
(HANDLE) _beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL);
if (!thread) {
debug(54, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror());
ipcSend(cwfd, err_string, strlen(err_string));
goto cleanup;
}
snprintf(buf1, 8191, "%ld\n", (long int) pid);
if (-1 == ipcSend(cwfd, buf1, strlen(buf1)))
goto cleanup;
debug(54, 2) ("ipc(%s,%ld): started successfully\n", prog, (long int) pid);
/* cycle */
for (;;) {
x = recv(crfd, buf1, 8192, 0);
if (x <= 0) {
debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n",
prog, pid, x);
break;
}
buf1[x] = '\0';
if (type == IPC_UDP_SOCKET && !strcmp(buf1, shutdown_string)) {
debug(54, 3)
("ipc(%s,%d): request for shutdown received from parent. Exiting...\n",
prog, pid);
TerminateProcess(hProcess, 0);
break;
}
debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", prog, pid,
rfc1738_escape_unescaped(buf1));
if (type == IPC_TCP_SOCKET)
x = write(c2p[1], buf1, x);
else
x = send(pwfd_ipc, buf1, x, 0);
if (x <= 0) {
debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n",
prog, pid, x, prog);
break;
}
}
retval = 0;
cleanup:
if (c2p[1] != -1)
close(c2p[1]);
if (fd_table[crfd].flags.open)
ipcCloseAllFD(-1, -1, crfd, cwfd);
if (prfd_ipc != -1) {
send(crfd_ipc, shutdown_string, strlen(shutdown_string), 0);
shutdown(crfd_ipc, SD_BOTH);
shutdown(prfd_ipc, SD_BOTH);
}
ipcCloseAllFD(prfd_ipc, pwfd_ipc, crfd_ipc, cwfd_ipc);
if (hProcess && WAIT_OBJECT_0 !=
WaitForSingleObject(hProcess, type == IPC_UDP_SOCKET ? 12000 : 5000)) {
getCurrentTime();
debug(54, 0) ("ipc(%s,%d): WARNING: %s didn't exit in %d seconds.\n",
prog, pid, prog, type == IPC_UDP_SOCKET ? 12 : 5);
}
if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) {
getCurrentTime();
debug(54, 0)
("ipc(%s,%d): WARNING: ipc_thread_2 didn't exit in 3 seconds.\n",
prog, pid);
}
getCurrentTime();
if (!retval)
debug(54, 2) ("ipc(%s,%d): normal exit\n", prog, pid);
if (buf1)
xfree(buf1);
if (prog)
xfree(prog);
if (env_str)
xfree(env_str);
if (thread)
CloseHandle(thread);
if (hProcess)
CloseHandle(hProcess);
if (p2c[0] != -1)
close(p2c[0]);
return retval;
}
static unsigned int __stdcall
ipc_thread_2(void *in_params)
{
int x;
struct thread_params *params = (struct thread_params *) in_params;
int type = params->type;
int rfd = params->rfd;
int send_fd = params->send_fd;
char *prog = xstrdup(params->prog);
pid_t pid = params->pid;
char *buf2 = xcalloc(1, 8192);
for (;;) {
if (type == IPC_TCP_SOCKET)
x = read(rfd, buf2, 8192);
else
x = recv(rfd, buf2, 8192, 0);
if ((x <= 0 && type == IPC_TCP_SOCKET) ||
(x < 0 && type == IPC_UDP_SOCKET)) {
debug(54, 3) ("ipc(%s,%d): %d bytes read from %s. Exiting...\n",
prog, pid, x, prog);
break;
}
buf2[x] = '\0';
if (type == IPC_UDP_SOCKET && !strcmp(buf2, shutdown_string)) {
debug(54, 3) ("ipc(%s,%d): request for shutdown received. Exiting...\n",
prog, pid);
break;
}
if (x >= 2) {
if ((buf2[x - 1] == '\n') && (buf2[x - 2] == '\r')) {
buf2[x - 2] = '\n';
buf2[x - 1] = '\0';
x--;
}
}
debug(54, 5) ("ipc(%s,%d): received from child : %s\n", prog, pid,
rfc1738_escape_unescaped(buf2));
x = send(send_fd, buf2, x, 0);
if ((x <= 0 && type == IPC_TCP_SOCKET) ||
(x < 0 && type == IPC_UDP_SOCKET)) {
debug(54, 3) ("ipc(%s,%d): %d bytes sent to parent. Exiting...\n",
prog, pid, x);
break;
}
}
xfree(prog);
xfree(buf2);
return 0;
}
/*
* $Id$
*
* AUTHOR: Guido Serassio & Andrey Shorin
*
* SQUID Internet Object Cache http://squid.nlanr.net/Squid/
* ----------------------------------------------------------
*
* Squid is the result of efforts by numerous individuals from the
* Internet community. Development is led by Duane Wessels of the
* National Laboratory for Applied Network Research and funded by the
* National Science Foundation. Squid is Copyrighted (C) 1998 by
* the Regents of the University of California. Please see the
* COPYRIGHT file for full details. Squid incorporates software
* developed and/or copyrighted by other sources. Please see the
* CREDITS file for full details.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#ifndef STDC_HEADERS
#define STDC_HEADERS 1
#endif
#define _WIN32_WINNT 0x0500
#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
# define __USE_FILE_OFFSET64 1
#endif
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
typedef unsigned char u_char;
typedef int SOCKET;
typedef int ssize_t;
typedef int mode_t;
#if defined __USE_FILE_OFFSET64
typedef int64_t off_t;
typedef uint64_t ino_t;
#else
typedef long off_t;
typedef unsigned long ino_t;
#endif
#define INT64_MAX _I64_MAX
#define INT64_MIN _I64_MIN
#include "default_config_file.h"
/* Some tricks for MS Compilers */
#define __STDC__ 1
#pragma include_alias(<dirent.h>, <direct.h>)
#define THREADLOCAL __declspec(thread)
#elif defined(__GNUC__) /* gcc environment */
#define THREADLOCAL __attribute__((section(".tls")))
#endif
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#define alloca _alloca
#endif
#define chdir _chdir
#define dup _dup
#define dup2 _dup2
#define fdopen _fdopen
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#define fileno _fileno
#endif
#define ftruncate WIN32_ftruncate
#define getcwd _getcwd
#define getpid _getpid
#define getrusage WIN32_getrusage
#define ioctl ioctlsocket
#define memccpy _memccpy
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#define mkdir(p) _mkdir(p)
#endif
#define mktemp _mktemp
#define open _open
#define pclose _pclose
#define pipe WIN32_pipe
#define popen _popen
#define putenv _putenv
#define setmode _setmode
#define sleep(t) Sleep((t)*1000)
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#define snprintf _snprintf
#endif
#define strcasecmp _stricmp
#define strdup _strdup
#define strlwr _strlwr
#define strncasecmp _strnicmp
#define tempnam _tempnam
#define truncate WIN32_truncate
#define umask _umask
#define unlink _unlink
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#define vsnprintf _vsnprintf
#endif
#define O_RDONLY _O_RDONLY
#define O_WRONLY _O_WRONLY
#define O_RDWR _O_RDWR
#define O_APPEND _O_APPEND
#define O_CREAT _O_CREAT
#define O_TRUNC _O_TRUNC
#define O_EXCL _O_EXCL
#define O_TEXT _O_TEXT
#define O_BINARY _O_BINARY
#define O_RAW _O_BINARY
#define O_TEMPORARY _O_TEMPORARY
#define O_NOINHERIT _O_NOINHERIT
#define O_SEQUENTIAL _O_SEQUENTIAL
#define O_RANDOM _O_RANDOM
#define O_NDELAY 0
#define S_IRWXO 007
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR)
#endif
#ifndef SIGHUP
#define SIGHUP 1 /* hangup */
#endif
#ifndef SIGBUS
#define SIGBUS 7 /* bus error */
#endif
#ifndef SIGKILL
#define SIGKILL 9 /* kill (cannot be caught or ignored) */
#endif
#ifndef SIGSEGV
#define SIGSEGV 11 /* segment violation */
#endif
#ifndef SIGPIPE
#define SIGPIPE 13 /* write on a pipe with no one to read it */
#endif
#ifndef SIGCHLD
#define SIGCHLD 20 /* to parent on child stop or exit */
#endif
#ifndef SIGUSR1
#define SIGUSR1 30 /* user defined signal 1 */
#endif
#ifndef SIGUSR2
#define SIGUSR2 31 /* user defined signal 2 */
#endif
typedef unsigned short in_port_t;
typedef unsigned short int ushort;
typedef int uid_t;
typedef int gid_t;
#if defined __USE_FILE_OFFSET64
#define stat _stati64
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#define lseek _lseeki64
#endif
#define fstat _fstati64
#define tell _telli64
#else
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#define stat _stat
#define lseek _lseek
#define fstat _fstat
#define tell _tell
#endif
#endif
struct passwd {
char *pw_name; /* user name */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user id */
gid_t pw_gid; /* group id */
char *pw_gecos; /* real name */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group id */
char **gr_mem; /* group members */
};
struct statfs {
long f_type; /* type of filesystem (see below) */
long f_bsize; /* optimal transfer block size */
long f_blocks; /* total data blocks in file system */
long f_bfree; /* free blocks in fs */
long f_bavail; /* free blocks avail to non-superuser */
long f_files; /* total file nodes in file system */
long f_ffree; /* free file nodes in fs */
long f_fsid; /* file system id */
long f_namelen; /* maximum length of filenames */
long f_spare[6]; /* spare for later */
};
struct timezone
{
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of dst correction */
};
#define CHANGE_FD_SETSIZE 1
#if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE
#define FD_SETSIZE SQUID_MAXFD
#endif
#include <stddef.h>
#include <process.h>
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
/* Hack to suppress compiler warnings on FD_SET() & FD_CLR() */
#pragma warning (push)
#pragma warning (disable:4142)
#endif
/* prevent inclusion of wingdi.h */
#define NOGDI
#include <ws2spi.h>
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
#pragma warning (pop)
#include "readdir.h"
#else
#include <io.h>
#include <stdlib.h>
#include <sys/types.h>
#endif
typedef char * caddr_t;
#undef FD_CLOSE
#undef FD_OPEN
#undef FD_READ
#undef FD_WRITE
#define EISCONN WSAEISCONN
#define EINPROGRESS WSAEINPROGRESS
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EALREADY WSAEALREADY
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define ECONNRESET WSAECONNRESET
#define ERESTART WSATRY_AGAIN
#define ENOTCONN WSAENOTCONN
#undef h_errno
#define h_errno errno /* we'll set it ourselves */
#undef FD_CLR
#define FD_CLR(fd, set) do { \
u_int __i; \
SOCKET __sock = _get_osfhandle(fd); \
for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count ; __i++) { \
if (((fd_set FAR *)(set))->fd_array[__i] == __sock) { \
while (__i < ((fd_set FAR *)(set))->fd_count-1) { \
((fd_set FAR *)(set))->fd_array[__i] = \
((fd_set FAR *)(set))->fd_array[__i+1]; \
__i++; \
} \
((fd_set FAR *)(set))->fd_count--; \
break; \
} \
} \
} while(0)
#undef FD_SET
#define FD_SET(fd, set) do { \
u_int __i; \
SOCKET __sock = _get_osfhandle(fd); \
for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
if (((fd_set FAR *)(set))->fd_array[__i] == (__sock)) { \
break; \
} \
} \
if (__i == ((fd_set FAR *)(set))->fd_count) { \
if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \
((fd_set FAR *)(set))->fd_array[__i] = (__sock); \
((fd_set FAR *)(set))->fd_count++; \
} \
} \
} while(0)
#undef FD_ISSET
#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(_get_osfhandle(fd)), (fd_set FAR *)(set))
extern THREADLOCAL int ws32_result;
#define strerror(e) WIN32_strerror(e)
#define socket(f,t,p) \
(INVALID_SOCKET == ((SOCKET)(ws32_result = (int)socket(f,t,p))) ? \
((WSAEMFILE == (errno = WSAGetLastError()) ? errno = EMFILE : -1), -1) : \
(SOCKET)_open_osfhandle(ws32_result,0))
#define accept(s,a,l) \
(INVALID_SOCKET == ((SOCKET)(ws32_result = (int)accept(_get_osfhandle(s),a,l))) ? \
((WSAEMFILE == (errno = WSAGetLastError()) ? errno = EMFILE : -1), -1) : \
(SOCKET)_open_osfhandle(ws32_result,0))
#define bind(s,n,l) \
(SOCKET_ERROR == bind(_get_osfhandle(s),n,l) ? \
(errno = WSAGetLastError()), -1 : 0)
#define connect(s,n,l) \
(SOCKET_ERROR == connect(_get_osfhandle(s),n,l) ? \
(WSAEMFILE == (errno = WSAGetLastError()) ? errno = EMFILE : -1, -1) : 0)
#define listen(s,b) \
(SOCKET_ERROR == listen(_get_osfhandle(s),b) ? \
(WSAEMFILE == (errno = WSAGetLastError()) ? errno = EMFILE : -1, -1) : 0)
#define shutdown(s,h) \
(SOCKET_ERROR == shutdown(_get_osfhandle(s),h) ? \
(errno = WSAGetLastError()), -1 : 0)
#define select(n,r,w,e,t) \
(SOCKET_ERROR == (ws32_result = select(n,r,w,e,t)) ? \
(errno = WSAGetLastError()), -1 : ws32_result)
#define recv(s,b,l,f) \
(SOCKET_ERROR == (ws32_result = recv(_get_osfhandle(s),b,l,f)) ? \
(errno = WSAGetLastError()), -1 : ws32_result)
#define recvfrom(s,b,l,f,fr,frl) \
(SOCKET_ERROR == (ws32_result = recvfrom(_get_osfhandle(s),b,l,f,fr,frl)) ? \
(errno = WSAGetLastError()), -1 : ws32_result)
#define send(s,b,l,f) \
(SOCKET_ERROR == (ws32_result = send(_get_osfhandle(s),b,l,f)) ? \
(errno = WSAGetLastError()), -1 : ws32_result)
#define sendto(s,b,l,f,t,tl) \
(SOCKET_ERROR == (ws32_result = sendto(_get_osfhandle(s),b,l,f,t,tl)) ? \
(errno = WSAGetLastError()), -1 : ws32_result)
#define getsockname(s,n,l) \
(SOCKET_ERROR == getsockname(_get_osfhandle(s),n,l) ? \
(errno = WSAGetLastError()), -1 : 0)
#define getsockopt(s,l,o,v,n) \
(Sleep(1), SOCKET_ERROR == getsockopt(_get_osfhandle(s),l,o,(char*)v,n) ? \
(errno = WSAGetLastError()), -1 : 0)
#define setsockopt(s,l,o,v,n) \
(SOCKET_ERROR == setsockopt(_get_osfhandle(s),l,o,v,n) ? \
(errno = WSAGetLastError()), -1 : 0)
#define ioctlsocket(s,c,a) \
(SOCKET_ERROR == ioctlsocket(_get_osfhandle(s),c,a) ? \
(errno = WSAGetLastError()), -1 : 0)
#define gethostname(n,l) \
(SOCKET_ERROR == gethostname(n,l) ? \
(errno = WSAGetLastError()), -1 : 0)
#define gethostbyname(n) \
(NULL == ((HOSTENT FAR*)(ws32_result = (int)gethostbyname(n))) ? \
(errno = WSAGetLastError()), NULL : (HOSTENT FAR*)ws32_result)
#define getservbyname(n,p) \
(NULL == ((SERVENT FAR*)(ws32_result = (int)getservbyname(n,p))) ? \
(errno = WSAGetLastError()), NULL : (SERVENT FAR*)ws32_result)
#define gethostbyaddr(a,l,t) \
(NULL == ((HOSTENT FAR*)(ws32_result = (int)gethostbyaddr(a,l,t))) ? \
(errno = WSAGetLastError()), NULL : (HOSTENT FAR*)ws32_result)
#undef WSASocket
#ifdef UNICODE
#define WSASocket(a,t,p,i,g,f) \
(INVALID_SOCKET == ((SOCKET)(ws32_result = (int)WSASocketW(a,t,p,i,g,f))) ? \
((WSAEMFILE == (errno = WSAGetLastError()) ? errno = EMFILE : -1), -1) : \
(SOCKET)_open_osfhandle(ws32_result,0))
#else
#define WSASocket(a,t,p,i,g,f) \
(INVALID_SOCKET == ((SOCKET)(ws32_result = (int)WSASocketA(a,t,p,i,g,f))) ? \
((WSAEMFILE == (errno = WSAGetLastError()) ? errno = EMFILE : -1), -1) : \
(SOCKET)_open_osfhandle(ws32_result,0))
#endif /* !UNICODE */
#undef WSADuplicateSocket
#ifdef UNICODE
#define WSADuplicateSocket(s,n,l) \
(SOCKET_ERROR == WSADuplicateSocketW(_get_osfhandle(s),n,l) ? \
(errno = WSAGetLastError()), -1 : 0)
#else
#define WSADuplicateSocket(s,n,l) \
(SOCKET_ERROR == WSADuplicateSocketA(_get_osfhandle(s),n,l) ? \
(errno = WSAGetLastError()), -1 : 0)
#endif /* !UNICODE */
#if defined(UTIL_C)
#define read _read
#define write _write
#else
extern THREADLOCAL int _so_err;
extern THREADLOCAL int _so_err_siz;
#define read(fd,buf,siz) \
(_so_err_siz = sizeof(_so_err), \
getsockopt((fd),SOL_SOCKET,SO_ERROR,&_so_err,&_so_err_siz) \
== 0 ? recv((fd),(buf),(siz),0) : _read((fd),(buf),(siz)))
#define write(fd,buf,siz) \
(_so_err_siz = sizeof(_so_err), \
getsockopt((fd),SOL_SOCKET,SO_ERROR,&_so_err,&_so_err_siz) \
== 0 ? send((fd),(buf),(siz),0) : _write((fd),(buf),(siz)))
#endif
#if defined(COMM_C) || defined(TOOLS_C)
#define close WIN32_Close_FD_Socket
#else
#define close _close
#endif
#define RUSAGE_SELF 0 /* calling process */
#define RUSAGE_CHILDREN -1 /* terminated child processes */
struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
long ru_maxrss; /* integral max resident set size */
long ru_ixrss; /* integral shared text memory size */
long ru_idrss; /* integral unshared data size */
long ru_isrss; /* integral unshared stack size */
long ru_minflt; /* page reclaims */
long ru_majflt; /* page faults */
long ru_nswap; /* swaps */
long ru_inblock; /* block input operations */
long ru_oublock; /* block output operations */
long ru_msgsnd; /* messages sent */
long ru_msgrcv; /* messages received */
long ru_nsignals; /* signals received */
long ru_nvcsw; /* voluntary context switches */
long ru_nivcsw; /* involuntary context switches */
};
/*
* $Id$
*
* * * * * * * * Legal stuff * * * * * * *
*
* (C) 2001 Guido Serassio <serassio@libero.it>,
* inspired by previous work by Romeo Anghelache & Eric Stern.
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
* Squid is the result of efforts by numerous individuals from
* the Internet community; see the CONTRIBUTORS file for full
* details. Many organizations have provided support for Squid's
* development; see the SPONSORS file for full details. Squid is
* Copyrighted (C) 2001 by the Regents of the University of
* California; see the COPYRIGHT file for full details. Squid
* incorporates software developed and/or copyrighted by other
* sources; see the CREDITS file for full details.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#include "util.h"
/* The following code section is part of an EXPERIMENTAL native */
/* Windows NT/2000 Squid port - Compiles only on MS Visual C++ */
#if defined(_SQUID_MSWIN_)
#undef strerror
#define sys_nerr _sys_nerr
#undef assert
#include <assert.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#include <windows.h>
#include <string.h>
#include <sys/timeb.h>
#if HAVE_WIN32_PSAPI
#include <psapi.h>
#endif
THREADLOCAL int ws32_result;
THREADLOCAL int _so_err;
THREADLOCAL int _so_err_siz = sizeof(int);
LPCRITICAL_SECTION dbg_mutex = NULL;
/* internal to Microsoft CRTLIB */
#define FPIPE 0x08 /* file handle refers to a pipe */
typedef struct {
long osfhnd; /* underlying OS file HANDLE */
char osfile; /* attributes of file (e.g., open in text mode?) */
char pipech; /* one char buffer for handles opened on pipes */
#ifdef _MT
int lockinitflag;
CRITICAL_SECTION lock;
#endif /* _MT */
} ioinfo;
#define IOINFO_L2E 5
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
#define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - 1)) )
#define _osfile(i) ( _pioinfo(i)->osfile )
#define _osfhnd(i) ( _pioinfo(i)->osfhnd )
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
extern _CRTIMP ioinfo *__pioinfo[];
int __cdecl _free_osfhnd(int);
#define FOPEN 0x01 /* file handle open */
#elif defined(__MINGW32__) /* MinGW environment */
#define FOPEN 0x01 /* file handle open */
__MINGW_IMPORT ioinfo *__pioinfo[];
int _free_osfhnd(int);
#endif
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
size_t
getpagesize()
{
return 4096;
}
int64_t
WIN32_strtoll(const char *nptr, char **endptr, int base)
{
const char *s;
int64_t acc;
int64_t val;
int neg, any;
char c;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
s = nptr;
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
acc = any = 0;
if (base < 2 || base > 36) {
errno = EINVAL;
if (endptr != NULL)
*endptr = (char *) (any ? s - 1 : nptr);
return acc;
}
/* The classic bsd implementation requires div/mod operators
* to compute a cutoff. Benchmarking proves that is very, very
* evil to some 32 bit processors. Instead, look for underflow
* in both the mult and add/sub operation. Unlike the bsd impl,
* we also work strictly in a signed int64 word as we haven't
* implemented the unsigned type in win32.
*
* Set 'any' if any `digits' consumed; make it negative to indicate
* overflow.
*/
val = 0;
for (;; c = *s++) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'Z')
c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else
break;
if (c >= base)
break;
val *= base;
if ((any < 0) /* already noted an over/under flow - short circuit */
||(neg && (val > acc || (val -= c) > acc)) /* underflow */
||(!neg && (val < acc || (val += c) < acc))) { /* overflow */
any = -1; /* once noted, over/underflows never go away */
} else {
acc = val;
any = 1;
}
}
if (any < 0) {
acc = neg ? INT64_MIN : INT64_MAX;
errno = ERANGE;
} else if (!any) {
errno = EINVAL;
}
if (endptr != NULL)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
#endif
uid_t
geteuid(void)
{
return 100;
}
uid_t
getuid(void)
{
return 100;
}
int
setuid(uid_t uid)
{
return 0;
}
int
seteuid(uid_t euid)
{
return 0;
}
gid_t
getegid(void)
{
return 100;
}
gid_t
getgid(void)
{
return 100;
}
int
setgid(gid_t gid)
{
return 0;
}
int
setegid(gid_t egid)
{
return 0;
}
int
chroot(const char *dirname)
{
if (SetCurrentDirectory(dirname))
return 0;
else
return GetLastError();
}
/* Convert from "a.b.c.d" IP address string into
* an in_addr structure. Returns 0 on failure,
* and 1 on success.
*/
int
inet_aton(const char *cp, struct in_addr *addr)
{
if (cp == NULL || addr == NULL) {
return (0);
}
addr->s_addr = inet_addr(cp);
return (addr->s_addr == INADDR_NONE) ? 0 : 1;
}
void
GetProcessName(pid_t pid, char *ProcessName)
{
HANDLE hProcess;
strcpy(ProcessName, "unknown");
#if HAVE_WIN32_PSAPI
/* Get a handle to the process. */
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, pid);
/* Get the process name. */
if (NULL != hProcess) {
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
GetModuleBaseName(hProcess, hMod, ProcessName, sizeof(ProcessName));
else {
CloseHandle(hProcess);
return;
}
} else
return;
CloseHandle(hProcess);
#endif
}
int
kill(pid_t pid, int sig)
{
HANDLE hProcess;
char MyProcessName[MAX_PATH];
char ProcessNameToCheck[MAX_PATH];
if (sig == 0) {
if ((hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, pid)) == NULL)
return -1;
else {
CloseHandle(hProcess);
GetProcessName(getpid(), MyProcessName);
GetProcessName(pid, ProcessNameToCheck);
if (strcmp(MyProcessName, ProcessNameToCheck) == 0)
return 0;
return -1;
}
} else
return 0;
}
int
gettimeofday(struct timeval *pcur_time, struct timezone *tz)
{
struct _timeb current;
_ftime(¤t);
pcur_time->tv_sec = current.time;
pcur_time->tv_usec = current.millitm * 1000L;
if (tz) {
tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */
tz->tz_dsttime = current.dstflag; /* type of dst correction */
}
return 0;
}
int
statfs(const char *path, struct statfs *sfs)
{
char drive[4];
DWORD spc, bps, freec, totalc;
DWORD vsn, maxlen, flags;
if (!sfs) {
errno = EINVAL;
return -1;
}
strncpy(drive, path, 2);
drive[2] = '\0';
strcat(drive, "\\");
if (!GetDiskFreeSpace(drive, &spc, &bps, &freec, &totalc)) {
errno = ENOENT;
return -1;
}
if (!GetVolumeInformation(drive, NULL, 0, &vsn, &maxlen, &flags, NULL, 0)) {
errno = ENOENT;
return -1;
}
sfs->f_type = flags;
sfs->f_bsize = spc * bps;
sfs->f_blocks = totalc;
sfs->f_bfree = sfs->f_bavail = freec;
sfs->f_files = -1;
sfs->f_ffree = -1;
sfs->f_fsid = vsn;
sfs->f_namelen = maxlen;
return 0;
}
#if USE_TRUNCATE
int
WIN32_ftruncate(int fd, off_t size)
{
HANDLE file;
DWORD error;
LARGE_INTEGER size64;
LARGE_INTEGER test64;
if (fd < 0) {
errno = EBADF;
return -1;
}
size64.QuadPart = (__int64) size;
test64.QuadPart = 0;
file = (HANDLE) _get_osfhandle(fd);
/* Get current file position to check File Handle */
test64.LowPart = SetFilePointer(file, test64.LowPart, &test64.HighPart, FILE_CURRENT);
if ((test64.LowPart == INVALID_SET_FILE_POINTER) && ((error = GetLastError()) != NO_ERROR))
goto WIN32_ftruncate_error;
/* Set the current File Pointer position */
size64.LowPart = SetFilePointer(file, size64.LowPart, &size64.HighPart, FILE_BEGIN);
if ((size64.LowPart == INVALID_SET_FILE_POINTER) && ((error = GetLastError()) != NO_ERROR))
goto WIN32_ftruncate_error;
else if (!SetEndOfFile(file)) {
int error = GetLastError();
goto WIN32_ftruncate_error;
}
return 0;
WIN32_ftruncate_error:
switch (error) {
case ERROR_INVALID_HANDLE:
errno = EBADF;
break;
default:
errno = EIO;
break;
}
return -1;
}
int
WIN32_truncate(const char *pathname, off_t length)
{
int fd;
int res = -1;
fd = open(pathname, O_RDWR);
if (fd == -1)
errno = EBADF;
else {
res = WIN32_ftruncate(fd, length);
_close(fd);
}
return res;
}
#endif
static struct _wsaerrtext {
int err;
const char *errconst;
const char *errdesc;
} _wsaerrtext[] = {
{
WSA_E_CANCELLED, "WSA_E_CANCELLED", "Lookup cancelled."
},
{
WSA_E_NO_MORE, "WSA_E_NO_MORE", "No more data available."
},
{
WSAEACCES, "WSAEACCES", "Permission denied."
},
{
WSAEADDRINUSE, "WSAEADDRINUSE", "Address already in use."
},
{
WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", "Cannot assign requested address."
},
{
WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", "Address family not supported by protocol family."
},
{
WSAEALREADY, "WSAEALREADY", "Operation already in progress."
},
{
WSAEBADF, "WSAEBADF", "Bad file number."
},
{
WSAECANCELLED, "WSAECANCELLED", "Operation cancelled."
},
{
WSAECONNABORTED, "WSAECONNABORTED", "Software caused connection abort."
},
{
WSAECONNREFUSED, "WSAECONNREFUSED", "Connection refused."
},
{
WSAECONNRESET, "WSAECONNRESET", "Connection reset by peer."
},
{
WSAEDESTADDRREQ, "WSAEDESTADDRREQ", "Destination address required."
},
{
WSAEDQUOT, "WSAEDQUOT", "Disk quota exceeded."
},
{
WSAEFAULT, "WSAEFAULT", "Bad address."
},
{
WSAEHOSTDOWN, "WSAEHOSTDOWN", "Host is down."
},
{
WSAEHOSTUNREACH, "WSAEHOSTUNREACH", "No route to host."
},
{
WSAEINPROGRESS, "WSAEINPROGRESS", "Operation now in progress."
},
{
WSAEINTR, "WSAEINTR", "Interrupted function call."
},
{
WSAEINVAL, "WSAEINVAL", "Invalid argument."
},
{
WSAEINVALIDPROCTABLE, "WSAEINVALIDPROCTABLE", "Invalid procedure table from service provider."
},
{
WSAEINVALIDPROVIDER, "WSAEINVALIDPROVIDER", "Invalid service provider version number."
},
{
WSAEISCONN, "WSAEISCONN", "Socket is already connected."
},
{
WSAELOOP, "WSAELOOP", "Too many levels of symbolic links."
},
{
WSAEMFILE, "WSAEMFILE", "Too many open files."
},
{
WSAEMSGSIZE, "WSAEMSGSIZE", "Message too long."
},
{
WSAENAMETOOLONG, "WSAENAMETOOLONG", "File name is too long."
},
{
WSAENETDOWN, "WSAENETDOWN", "Network is down."
},
{
WSAENETRESET, "WSAENETRESET", "Network dropped connection on reset."
},
{
WSAENETUNREACH, "WSAENETUNREACH", "Network is unreachable."
},
{
WSAENOBUFS, "WSAENOBUFS", "No buffer space available."
},
{
WSAENOMORE, "WSAENOMORE", "No more data available."
},
{
WSAENOPROTOOPT, "WSAENOPROTOOPT", "Bad protocol option."
},
{
WSAENOTCONN, "WSAENOTCONN", "Socket is not connected."
},
{
WSAENOTEMPTY, "WSAENOTEMPTY", "Directory is not empty."
},
{
WSAENOTSOCK, "WSAENOTSOCK", "Socket operation on nonsocket."
},
{
WSAEOPNOTSUPP, "WSAEOPNOTSUPP", "Operation not supported."
},
{
WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", "Protocol family not supported."
},
{
WSAEPROCLIM, "WSAEPROCLIM", "Too many processes."
},
{
WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", "Protocol not supported."
},
{
WSAEPROTOTYPE, "WSAEPROTOTYPE", "Protocol wrong type for socket."
},
{
WSAEPROVIDERFAILEDINIT, "WSAEPROVIDERFAILEDINIT", "Unable to initialise a service provider."
},
{
WSAEREFUSED, "WSAEREFUSED", "Refused."
},
{
WSAEREMOTE, "WSAEREMOTE", "Too many levels of remote in path."
},
{
WSAESHUTDOWN, "WSAESHUTDOWN", "Cannot send after socket shutdown."
},
{
WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", "Socket type not supported."
},
{
WSAESTALE, "WSAESTALE", "Stale NFS file handle."
},
{
WSAETIMEDOUT, "WSAETIMEDOUT", "Connection timed out."
},
{
WSAETOOMANYREFS, "WSAETOOMANYREFS", "Too many references."
},
{
WSAEUSERS, "WSAEUSERS", "Too many users."
},
{
WSAEWOULDBLOCK, "WSAEWOULDBLOCK", "Resource temporarily unavailable."
},
{
WSANOTINITIALISED, "WSANOTINITIALISED", "Successful WSAStartup not yet performed."
},
{
WSASERVICE_NOT_FOUND, "WSASERVICE_NOT_FOUND", "Service not found."
},
{
WSASYSCALLFAILURE, "WSASYSCALLFAILURE", "System call failure."
},
{
WSASYSNOTREADY, "WSASYSNOTREADY", "Network subsystem is unavailable."
},
{
WSATYPE_NOT_FOUND, "WSATYPE_NOT_FOUND", "Class type not found."
},
{
WSAVERNOTSUPPORTED, "WSAVERNOTSUPPORTED", "Winsock.dll version out of range."
},
{
WSAEDISCON, "WSAEDISCON", "Graceful shutdown in progress."
}
};
/*
* wsastrerror() - description of WSAGetLastError()
*/
const char *
wsastrerror(int err)
{
static char xwsaerror_buf[BUFSIZ];
int i, errind = -1;
if (err == 0)
return "(0) No error.";
for (i = 0; i < sizeof(_wsaerrtext) / sizeof(struct _wsaerrtext); i++) {
if (_wsaerrtext[i].err != err)
continue;
errind = i;
break;
}
if (errind == -1)
snprintf(xwsaerror_buf, BUFSIZ, "Unknown");
else
snprintf(xwsaerror_buf, BUFSIZ, "%s, %s", _wsaerrtext[errind].errconst, _wsaerrtext[errind].errdesc);
return xwsaerror_buf;
}
struct passwd *
getpwnam(char *unused)
{
static struct passwd pwd =
{NULL, NULL, 100, 100, NULL, NULL, NULL};
return &pwd;
}
struct group *
getgrnam(char *unused)
{
static struct group grp =
{NULL, NULL, 100, NULL};
return &grp;
}
/*
* WIN32_strerror with argument for late notification */
const char *
WIN32_strerror(int err)
{
static char xbstrerror_buf[BUFSIZ];
if (err < 0 || err >= sys_nerr)
strncpy(xbstrerror_buf, wsastrerror(err), BUFSIZ);
else
strncpy(xbstrerror_buf, strerror(err), BUFSIZ);
return xbstrerror_buf;
}
int
WIN32_Close_FD_Socket(int fd)
{
int result = 0;
if (closesocket(_get_osfhandle(fd)) == SOCKET_ERROR) {
errno = WSAGetLastError();
result = 1;
}
_free_osfhnd(fd);
_osfile(fd) = 0;
return result;
}
#if defined(__MINGW32__) /* MinGW environment */
int
_free_osfhnd(int filehandle)
{
if (((unsigned) filehandle < SQUID_MAXFD) &&
(_osfile(filehandle) & FOPEN) &&
(_osfhnd(filehandle) != (long) INVALID_HANDLE_VALUE)) {
switch (filehandle) {
case 0:
SetStdHandle(STD_INPUT_HANDLE, NULL);
break;
case 1:
SetStdHandle(STD_OUTPUT_HANDLE, NULL);
break;
case 2:
SetStdHandle(STD_ERROR_HANDLE, NULL);
break;
}
_osfhnd(filehandle) = (long) INVALID_HANDLE_VALUE;
return (0);
} else {
errno = EBADF; /* bad handle */
_doserrno = 0L; /* not an OS error */
return -1;
}
}
#endif
struct errorentry {
unsigned long WIN32_code;
int POSIX_errno;
};
static struct errorentry errortable[] =
{
{ERROR_INVALID_FUNCTION, EINVAL},
{ERROR_FILE_NOT_FOUND, ENOENT},
{ERROR_PATH_NOT_FOUND, ENOENT},
{ERROR_TOO_MANY_OPEN_FILES, EMFILE},
{ERROR_ACCESS_DENIED, EACCES},
{ERROR_INVALID_HANDLE, EBADF},
{ERROR_ARENA_TRASHED, ENOMEM},
{ERROR_NOT_ENOUGH_MEMORY, ENOMEM},
{ERROR_INVALID_BLOCK, ENOMEM},
{ERROR_BAD_ENVIRONMENT, E2BIG},
{ERROR_BAD_FORMAT, ENOEXEC},
{ERROR_INVALID_ACCESS, EINVAL},
{ERROR_INVALID_DATA, EINVAL},
{ERROR_INVALID_DRIVE, ENOENT},
{ERROR_CURRENT_DIRECTORY, EACCES},
{ERROR_NOT_SAME_DEVICE, EXDEV},
{ERROR_NO_MORE_FILES, ENOENT},
{ERROR_LOCK_VIOLATION, EACCES},
{ERROR_BAD_NETPATH, ENOENT},
{ERROR_NETWORK_ACCESS_DENIED, EACCES},
{ERROR_BAD_NET_NAME, ENOENT},
{ERROR_FILE_EXISTS, EEXIST},
{ERROR_CANNOT_MAKE, EACCES},
{ERROR_FAIL_I24, EACCES},
{ERROR_INVALID_PARAMETER, EINVAL},
{ERROR_NO_PROC_SLOTS, EAGAIN},
{ERROR_DRIVE_LOCKED, EACCES},
{ERROR_BROKEN_PIPE, EPIPE},
{ERROR_DISK_FULL, ENOSPC},
{ERROR_INVALID_TARGET_HANDLE, EBADF},
{ERROR_INVALID_HANDLE, EINVAL},
{ERROR_WAIT_NO_CHILDREN, ECHILD},
{ERROR_CHILD_NOT_COMPLETE, ECHILD},
{ERROR_DIRECT_ACCESS_HANDLE, EBADF},
{ERROR_NEGATIVE_SEEK, EINVAL},
{ERROR_SEEK_ON_DEVICE, EACCES},
{ERROR_DIR_NOT_EMPTY, ENOTEMPTY},
{ERROR_NOT_LOCKED, EACCES},
{ERROR_BAD_PATHNAME, ENOENT},
{ERROR_MAX_THRDS_REACHED, EAGAIN},
{ERROR_LOCK_FAILED, EACCES},
{ERROR_ALREADY_EXISTS, EEXIST},
{ERROR_FILENAME_EXCED_RANGE, ENOENT},
{ERROR_NESTING_NOT_ALLOWED, EAGAIN},
{ERROR_NOT_ENOUGH_QUOTA, ENOMEM}
};
#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
void
WIN32_maperror(unsigned long WIN32_oserrno)
{
int i;
_doserrno = WIN32_oserrno;
for (i = 0; i < (sizeof(errortable) / sizeof(struct errorentry)); ++i) {
if (WIN32_oserrno == errortable[i].WIN32_code) {
errno = errortable[i].POSIX_errno;
return;
}
}
if (WIN32_oserrno >= MIN_EACCES_RANGE && WIN32_oserrno <= MAX_EACCES_RANGE)
errno = EACCES;
else if (WIN32_oserrno >= MIN_EXEC_ERROR && WIN32_oserrno <= MAX_EXEC_ERROR)
errno = ENOEXEC;
else
errno = EINVAL;
}
#endif
This archive was generated by hypermail pre-2.1.9 : Sun Oct 01 2006 - 12:00:06 MDT