/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "str.h"
#include "strescape.h"
#include "env-util.h"
#include "execv-const.h"
#include "write-full.h"
#include "restrict-access.h"
#include "master-interface.h"
#include "master-service.h"
#include <unistd.h>
static const char **accepted_envs;
{
i_fatal("Client not compatible with this binary "
"(connecting to wrong socket?)");
}
}
static void
{
unsigned int i, socket_count;
i_fatal("dup2() failed: %m");
i_fatal("dup2() failed: %m");
/* close all fds */
for (i = 0; i < socket_count; i++) {
if (close(MASTER_LISTEN_FD_FIRST + i) < 0)
i_error("close(listener) failed: %m");
}
if (close(MASTER_STATUS_FD) < 0)
i_error("close(status) failed: %m");
i_error("close(conn->fd) failed: %m");
}
env_clean();
}
}
{
const char *const *args;
void *buf;
int status;
/* Input contains:
VERSION .. <lf>
[alarm=<secs> <lf>]
"noreply" | "-" (or anything really) <lf>
arg 1 <lf>
arg 2 <lf>
...
<lf>
DATA
This is quite a horrible protocol. If alarm is specified, it MUST be
before "noreply". If "noreply" isn't given, something other string
(typically "-") must be given which is eaten away.
*/
scanpos = 1;
while (!header_complete) {
/* peek in socket input buffer */
if (ret <= 0) {
if (ret < 0)
i_fatal("recv(MSG_PEEK) failed: %m");
i_fatal("recv(MSG_PEEK) failed: disconnected");
}
/* scan for final \n\n */
pos++;
break;
}
}
/* read data for real (up to and including \n\n) */
if (ret < 0)
i_fatal("recv() failed: %m");
if (ret == 0)
i_fatal("recv() failed: disconnected");
i_fatal("recv() failed: size of definitive recv() differs from peek");
}
}
alarm(0);
/* drop the last two LFs */
const char *p;
unsigned int seconds;
i_fatal("invalid alarm option");
args++;
}
if (p == NULL)
i_fatal("invalid environment variable");
args++;
}
}
if (**args == '\0')
i_fatal("empty options");
args++;
}
if (noreply) {
/* no need to fork and check exit status */
i_unreached();
}
i_error("fork() failed: %m");
return FALSE;
}
if (pid == 0) {
/* child */
i_unreached();
}
/* parent */
/* check script exit status */
i_error("waitpid() failed: %m");
return FALSE;
if (ret != 0) {
return FALSE;
}
} else if (WIFSIGNALED(status)) {
return FALSE;
} else if (WIFSTOPPED(status)) {
return FALSE;
} else {
return FALSE;
}
return TRUE;
}
{
i_error("write(response) failed: %m");
}
{
const char *binary;
const char *const *envs;
int c, i;
while ((c = master_getopt(master_service)) > 0) {
switch (c) {
case 'e':
envs++;
}
break;
default:
return FATAL_DEFAULT;
}
}
i_fatal("Missing script path");
if (argv[0][0] == '/')
else
for (i = 1; i < argc; i++) {
}
return 0;
}