97
93
void virusaction(const char *filename, const char *virname, const struct cfgstruct *copt)
100
96
const struct cfgstruct *cpt;
102
if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled)
105
/* NB: we need to fork here since this function modifies the environment.
106
(Modifications to the env. are not reentrant, but we need to be.) */
111
char *buffer, *pt, *cmd;
97
char *buffer, *pt, *cmd, *buffer_file, *buffer_vir;
101
if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled)
104
env[0] = getenv("PATH");
106
/* Allocate env vars.. to be portable env vars should not be freed */
107
buffer_file = (char *) malloc(strlen(ENV_FILE) + strlen(filename) + 2);
109
sprintf(buffer_file, "%s=%s", ENV_FILE, filename);
110
env[j++] = buffer_file;
113
buffer_vir = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2);
115
sprintf(buffer_vir, "%s=%s", ENV_VIRUS, virname);
116
env[j++] = buffer_vir;
113
120
cmd = strdup(cpt->strarg);
115
if((pt = strstr(cmd, "%v"))) {
116
buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10);
119
strcat(buffer, virname);
122
cmd = strdup(buffer);
126
/* Allocate env vars.. to be portable env vars should not be freed */
127
buffer = (char *) malloc(strlen(ENV_FILE) + strlen(filename) + 2);
128
sprintf(buffer, "%s=%s", ENV_FILE, filename);
131
buffer = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2);
132
sprintf(buffer, "%s=%s", ENV_VIRUS, virname);
135
/* WARNING: this is uninterruptable ! */
138
/* The below is not reached but is here for completeness to remind
139
maintainers that this buffer is still allocated.. */
122
if(cmd && (pt = strstr(cmd, "%v"))) {
123
buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10);
127
strcat(buffer, virname);
130
cmd = strdup(buffer);
140
/* We can only call async-signal-safe functions after fork(). */
145
/* WARNING: this is uninterruptable ! */
146
exit(execle("/bin/sh", "sh", "-c", cmd, NULL, env));
147
} else if (pid > 0) {
149
waitpid(pid, NULL, 0);
152
logg("!VirusAction: fork failed.\n");
141
} else if (pid > 0) {
143
waitpid(pid, NULL, 0);
146
logg("!VirusAction: fork failed.\n");
149
158
#endif /* C_WINDOWS */
335
344
This procedure does timed clamd command and delimited input processing.
336
345
It is complex for several reasons:
337
1) FD commands are delivered on Unix domain sockets via recvnsg() on platforms which can do this.
338
These command messages are accompanied by a single byte of data which is a NUL character.
339
346
2) Newline delimited commands are indicated by a command which is prefixed by an 'n' character.
340
347
This character serves to indicate that the command will contain a newline which will cause
341
348
command data to be read until the command input buffer is full or a newline is encountered.
348
355
int readsock(int sockfd, char *buf, size_t size, unsigned char delim, int timeout_sec, int force_delim, int read_command)
358
#ifdef HAVE_CONTROL_IN_MSGHDR
360
#define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
363
#define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
365
struct cmsghdr *cmsg;
366
char tmp[CMSG_SPACE(sizeof(fd))];
368
360
time_t starttime, timenow;
370
362
time(&starttime);
386
378
if(read_command) {
387
if((n >= 1) && (buf[0] == 0)) { /* FD message */
389
iov[0].iov_base = buf;
390
iov[0].iov_len = size;
391
memset(&msg, 0, sizeof(msg));
395
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
396
msg.msg_accrights = (caddr_t)&fd;
397
msg.msg_accrightslen = sizeof(fd);
399
#ifdef HAVE_CONTROL_IN_MSGHDR
400
msg.msg_control = tmp;
401
msg.msg_controllen = sizeof(tmp);
403
#if defined(HAVE_RECVMSG) && !defined(C_OS2) && !defined(INCOMPLETE_CMSG)
404
n = recvmsg(sockfd, &msg, 0);
406
n = recv(sockfd, buf, size, 0);
411
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
412
if(msg.msg_accrightslen != sizeof(fd))
415
#ifdef HAVE_CONTROL_IN_MSGHDR
416
cmsg = CMSG_FIRSTHDR(&msg);
419
if(cmsg->cmsg_type != SCM_RIGHTS)
421
if(cmsg->cmsg_len != CMSG_LEN(sizeof(fd)))
423
fd = *(int *)CMSG_DATA(cmsg);
427
n = snprintf(buf, size, "FD %d", fd);
428
if((size_t) n >= size)
432
379
if((n >= 1) && (buf[0] == 'n')) { /* Newline delimited command */