|
|
|
@ -163,99 +163,6 @@ void virusaction(const char *filename, const char *virname, const struct optstru |
|
|
|
|
} |
|
|
|
|
#endif /* C_WINDOWS */ |
|
|
|
|
|
|
|
|
|
int poll_fds(int *fds, int nfds, int timeout_sec, int check_signals) |
|
|
|
|
{ |
|
|
|
|
int retval; |
|
|
|
|
int i; |
|
|
|
|
#ifdef HAVE_POLL |
|
|
|
|
struct pollfd poll_1[1]; |
|
|
|
|
struct pollfd *poll_data = poll_1; |
|
|
|
|
|
|
|
|
|
if (nfds>1) { |
|
|
|
|
poll_data = malloc(nfds*sizeof(*poll_data)); |
|
|
|
|
if(!poll_data) { |
|
|
|
|
logg("!poll_fds: Can't allocate memory for poll_data\n"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i=0; i<nfds; i++) { |
|
|
|
|
poll_data[i].fd = fds[i]; |
|
|
|
|
poll_data[i].events = POLLIN; |
|
|
|
|
poll_data[i].revents = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (timeout_sec > 0) { |
|
|
|
|
timeout_sec *= 1000; |
|
|
|
|
} |
|
|
|
|
while (1) { |
|
|
|
|
retval = poll(poll_data, nfds, timeout_sec); |
|
|
|
|
if (retval == -1) { |
|
|
|
|
if (errno == EINTR && !check_signals) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (nfds>1) |
|
|
|
|
free(poll_data); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
if (nfds>1) { |
|
|
|
|
if (retval>0) { |
|
|
|
|
for (i=0; i<nfds; i++) { |
|
|
|
|
if (poll_data[i].revents) { |
|
|
|
|
retval = i+1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
free(poll_data); |
|
|
|
|
} |
|
|
|
|
return retval; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
fd_set rfds; |
|
|
|
|
struct timeval tv; |
|
|
|
|
int maxfd = 0; |
|
|
|
|
|
|
|
|
|
for (i=0; i<nfds; i++) { |
|
|
|
|
#ifndef C_WINDOWS |
|
|
|
|
if (fds[i] >= DEFAULT_FD_SETSIZE) { |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
if (fds[i] > maxfd) |
|
|
|
|
maxfd = fds[i]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (1) { |
|
|
|
|
FD_ZERO(&rfds); |
|
|
|
|
for (i=0; i<nfds; i++) |
|
|
|
|
FD_SET(fds[i], &rfds); |
|
|
|
|
tv.tv_sec = timeout_sec; |
|
|
|
|
tv.tv_usec = 0; |
|
|
|
|
|
|
|
|
|
retval = select(maxfd+1, &rfds, NULL, NULL, |
|
|
|
|
(timeout_sec>0 ? &tv : NULL)); |
|
|
|
|
if (retval == -1) { |
|
|
|
|
if (errno == EINTR && !check_signals) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
if ((nfds>1) && (retval>0)) { |
|
|
|
|
for (i=0; i<nfds; i++) { |
|
|
|
|
if (FD_ISSET(fds[i],&rfds)) { |
|
|
|
|
retval = i+1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return retval; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int is_fd_connected(int fd) |
|
|
|
|
{ |
|
|
|
@ -340,103 +247,6 @@ int writen(int fd, void *buff, unsigned int count) |
|
|
|
|
return count; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* FD Support Submitted by Richard Lyons <frob-clamav*webcentral.com.au> */ |
|
|
|
|
/*
|
|
|
|
|
This procedure does timed clamd command and delimited input processing.
|
|
|
|
|
It is complex for several reasons: |
|
|
|
|
2) Newline delimited commands are indicated by a command which is prefixed by an 'n' character.
|
|
|
|
|
This character serves to indicate that the command will contain a newline which will cause |
|
|
|
|
command data to be read until the command input buffer is full or a newline is encountered. |
|
|
|
|
Once the delimiter is encountered, the data is returned without the prefixing 'n' byte. |
|
|
|
|
3) Legacy clamd clients presented commands which may or may not have been delimited by a newline. |
|
|
|
|
If a command happens to be delimted by a newline, then only that command (and its newline) is |
|
|
|
|
read and passed back, otherwise, all data read (in a single read) which fits in the specified |
|
|
|
|
buffer will be returned. |
|
|
|
|
*/ |
|
|
|
|
int readsock(int sockfd, char *buf, size_t size, unsigned char delim, int timeout_sec, int force_delim, int read_command) |
|
|
|
|
{ |
|
|
|
|
ssize_t n; |
|
|
|
|
size_t boff = 0; |
|
|
|
|
char *pdelim; |
|
|
|
|
time_t starttime, timenow; |
|
|
|
|
|
|
|
|
|
time(&starttime); |
|
|
|
|
while(1) { |
|
|
|
|
time(&timenow); |
|
|
|
|
switch(poll_fd(sockfd, (timeout_sec && ((timeout_sec-(timenow-starttime)) > 0)) ? timeout_sec-(timenow-starttime) : 0, 0)) { |
|
|
|
|
case 0: /* timeout */ |
|
|
|
|
return -2; |
|
|
|
|
case -1: |
|
|
|
|
if(errno == EINTR) |
|
|
|
|
continue; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
n = recv(sockfd, buf, size, MSG_PEEK); |
|
|
|
|
if(n < 0) |
|
|
|
|
return -1; |
|
|
|
|
if(read_command) { |
|
|
|
|
if((n >= 1) && (buf[0] == 'n')) { /* Newline delimited command */ |
|
|
|
|
force_delim = 1; |
|
|
|
|
delim = '\n'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
while(boff < size) { |
|
|
|
|
if(force_delim) { |
|
|
|
|
pdelim = memchr(buf, delim, n+boff); |
|
|
|
|
if(pdelim) { |
|
|
|
|
n = recv(sockfd, buf+boff, pdelim-buf+1-boff, 0); |
|
|
|
|
break; |
|
|
|
|
} else { |
|
|
|
|
n = recv(sockfd, buf+boff, n, 0); |
|
|
|
|
if(n < 0) |
|
|
|
|
return -1; |
|
|
|
|
if((boff+n) == size) |
|
|
|
|
break; |
|
|
|
|
boff += n; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
pdelim = memchr(buf, delim, n+boff); |
|
|
|
|
if(pdelim) |
|
|
|
|
n = recv(sockfd, buf+boff, pdelim-buf+1-boff, 0); |
|
|
|
|
else |
|
|
|
|
n = recv(sockfd, buf+boff, size-boff, 0); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
while(1) { |
|
|
|
|
time(&timenow); |
|
|
|
|
switch(poll_fd(sockfd, ((timeout_sec-(timenow-starttime)) > 0) ? timeout_sec-(timenow-starttime) : 0, 0)) { |
|
|
|
|
case 0: /* timeout */ |
|
|
|
|
return -2; |
|
|
|
|
case -1: |
|
|
|
|
if(errno == EINTR) |
|
|
|
|
continue; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
n = recv(sockfd, buf+boff, size-boff, MSG_PEEK); |
|
|
|
|
if(n < 0) |
|
|
|
|
return -1; |
|
|
|
|
if(n == 0) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if(n < 0) |
|
|
|
|
return -1; |
|
|
|
|
n += boff; |
|
|
|
|
if(read_command) { |
|
|
|
|
if((n >= 1) && (buf[0] == 'n')) { /* Need to strip leading 'n' from command to attain standard command */ |
|
|
|
|
--n; |
|
|
|
|
memcpy(buf, buf+1, n); |
|
|
|
|
buf[n] = '\0'; |
|
|
|
|
} |
|
|
|
|
return !strncmp(buf, "FD", 2) ? -1 : n; /* an explicit FD command is invalid */ |
|
|
|
|
} |
|
|
|
|
return n; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int realloc_polldata(struct fd_data *data) |
|
|
|
|
{ |
|
|
|
|
#ifdef HAVE_POLL |
|
|
|
|