log(2, "detaching\n");
log(2, "detaching %d\n", getpid());
static void setup(struct config *config, int *randomfdp, int *sockfdp) {    int ret, sockfd;#ifndef DISABLE_DAEMON_CODE    int parentfd = -1, loggerfd = -1;    pid_t logger_pid = -1;#endif    struct sigaction sa;    /* random device */    *randomfdp = open(RANDOM_DEVICE, O_RDONLY);    if (*randomfdp < 0) {        fprintf(stderr, "failed to open %s: %s\n",                RANDOM_DEVICE, strerror(errno));        exit(1);    }    /* server socket stuff */    sockfd = socket(PF_INET, SOCK_STREAM, 0);    if (sockfd < 0) {        fprintf(stderr, "failed to create socket: %s\n",                strerror(errno));        exit(1);    }    ret = bind(sockfd, config->bind_address->ai_addr,               config->bind_address->ai_addrlen);    if (ret < 0) {        fprintf(stderr, "failed to bind: %s\n",                strerror(errno));        exit(1);    }    ret = listen(sockfd, 4);    if (ret < 0) {        fprintf(stderr, "listen failed: %s\n",                strerror(errno));        exit(1);    }    *sockfdp = sockfd;#ifndef DISABLE_DAEMON_CODE    /* daemonize */    if (!config->no_daemon && getppid() != 1) {        int fds[2];        pid_t pid;        ret = pipe(fds);        if (ret < 0) {            fprintf(stderr, "pipe failed: %s\n", strerror(errno));            exit(1);        }        pid = fork();        if (pid < 0) {            fprintf(stderr, "fork failed: %s\n", strerror(errno));            exit(1);        }        if (pid > 0) {            int status;            fd_set rfds;            char buffer[256];            struct timeval tv;            close(fds[1]);            log(4, "waiting for daemon process\n");            do {                FD_ZERO(&rfds);                FD_SET(fds[0], &rfds);                tv.tv_sec = 0;                tv.tv_usec = 100000;                ret = select(fds[0] + 1, &rfds, NULL, NULL, &tv);                if (ret > 0 && read(fds[0], buffer, sizeof(buffer)) > 0) {                    log(2, "detaching\n");                    exit(0);                }                pid = waitpid(pid, &status, WNOHANG);            } while (pid <= 0);            log(3, "daemon process exited with %d\n",                WEXITSTATUS(status));            exit(WEXITSTATUS(status));        }        close(fds[0]);        parentfd = fds[1];        setsid();        close(0);        signal(SIGTSTP, SIG_IGN);        signal(SIGTTOU, SIG_IGN);        signal(SIGTTIN, SIG_IGN);        log(3, "daemonized as pid %d\n", getpid());    }    /* write PID file */    if (config->pidfile != NULL) {        FILE *file;        file = fopen(config->pidfile, "w");        if (file == NULL) {            fprintf(stderr, "failed to create '%s': %s\n",                    config->pidfile, strerror(errno));            exit(1);        }        fprintf(file, "%d\n", getpid());        fclose(file);    }    /* start logger process */    if (config->logger != NULL) {        int fds[2];        log(3, "starting logger '%s'\n", config->logger);        ret = pipe(fds);        if (ret < 0) {            fprintf(stderr, "pipe failed: %s\n", strerror(errno));            exit(1);        }        logger_pid = fork();        if (logger_pid < 0) {            fprintf(stderr, "fork failed: %s\n", strerror(errno));            exit(1);        } else if (logger_pid == 0) {            if (fds[0] != 0) {                dup2(fds[0], 0);                close(fds[0]);            }            close(fds[1]);            close(1);            close(2);            close(sockfd);            execl("/bin/sh", "sh", "-c", config->logger, NULL);            exit(1);        }        log(2, "logger started as pid %d\n", logger_pid);        close(fds[0]);        loggerfd = fds[1];        log(3, "logger connected\n");    }    /* chroot */    if (config->chroot_dir != NULL) {        ret = chroot(config->chroot_dir);        if (ret < 0) {            fprintf(stderr, "chroot '%s' failed: %s\n",                    config->chroot_dir, strerror(errno));            exit(1);        }    }    chdir("/");    /* setuid */    if (config->uid > 0) {        ret = setgroups(0, NULL);        if (ret < 0) {            fprintf(stderr, "setgroups failed: %s\n", strerror(errno));            exit(1);        }        ret = setregid(config->gid, config->gid);        if (ret < 0) {            fprintf(stderr, "setgid failed: %s\n", strerror(errno));            exit(1);        }        ret = setreuid(config->uid, config->uid);        if (ret < 0) {            fprintf(stderr, "setuid failed: %s\n", strerror(errno));            exit(1);        }    } else if (getuid() == 0) {        /* drop a real_uid root */        setuid(geteuid());    }#endif /* DISABLE_DAEMON_CODE */    /* signals */    memset(&sa, 0, sizeof(sa));    sa.sa_handler = exit_signal_handler;    sigaction(SIGHUP, &sa, NULL);    sigaction(SIGTERM, &sa, NULL);    sigaction(SIGINT, &sa, NULL);    sigaction(SIGQUIT, &sa, NULL);    sa.sa_handler = SIG_IGN;    sigaction(SIGUSR1, &sa, NULL);    sigaction(SIGUSR2, &sa, NULL);#ifndef DISABLE_DAEMON_CODE    /* send parent process a signal */    if (parentfd >= 0) {        log(4, "closing parent pipe\n");        write(parentfd, &parentfd, sizeof(parentfd));        close(parentfd);    }    /* now connect logger */    if (loggerfd >= 0) {        dup2(loggerfd, 1);        dup2(loggerfd, 2);        close(loggerfd);    }#endif /* DISABLE_DAEMON_CODE */}