hooks.c revision 204076
1221888Sadrian/*- 2221888Sadrian * Copyright (c) 2010 The FreeBSD Foundation 3221888Sadrian * All rights reserved. 4221888Sadrian * 5221888Sadrian * This software was developed by Pawel Jakub Dawidek under sponsorship from 6221888Sadrian * the FreeBSD Foundation. 7221888Sadrian * 8221888Sadrian * Redistribution and use in source and binary forms, with or without 9221888Sadrian * modification, are permitted provided that the following conditions 10221888Sadrian * are met: 11221888Sadrian * 1. Redistributions of source code must retain the above copyright 12221888Sadrian * notice, this list of conditions and the following disclaimer. 13221888Sadrian * 2. Redistributions in binary form must reproduce the above copyright 14221888Sadrian * notice, this list of conditions and the following disclaimer in the 15221888Sadrian * documentation and/or other materials provided with the distribution. 16221888Sadrian * 17221888Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18221888Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19221888Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20221888Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21221888Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22221888Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23221888Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24221888Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25221888Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26221888Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27221888Sadrian * SUCH DAMAGE. 28221888Sadrian */ 29221888Sadrian 30221888Sadrian#include <sys/cdefs.h> 31221888Sadrian__FBSDID("$FreeBSD: head/sbin/hastd/hooks.c 204076 2010-02-18 23:16:19Z pjd $"); 32221888Sadrian 33221888Sadrian#include <sys/types.h> 34223615Sadrian#include <sys/wait.h> 35223615Sadrian 36221888Sadrian#include <assert.h> 37221888Sadrian#include <fcntl.h> 38221888Sadrian#include <stdio.h> 39221888Sadrian#include <stdlib.h> 40221888Sadrian#include <unistd.h> 41221888Sadrian#include <string.h> 42221888Sadrian#include <syslog.h> 43221888Sadrian#include <libgen.h> 44221888Sadrian#include <paths.h> 45221888Sadrian 46221888Sadrian#include <pjdlog.h> 47221888Sadrian 48221888Sadrian#include "hooks.h" 49221888Sadrian 50221888Sadrianstatic void 51221888Sadriandescriptors(void) 52221888Sadrian{ 53221888Sadrian long maxfd; 54221888Sadrian int fd; 55221888Sadrian 56221888Sadrian /* 57221888Sadrian * Close all descriptors. 58221888Sadrian */ 59221888Sadrian maxfd = sysconf(_SC_OPEN_MAX); 60221888Sadrian if (maxfd < 0) { 61221888Sadrian pjdlog_errno(LOG_WARNING, "sysconf(_SC_OPEN_MAX) failed"); 62221888Sadrian maxfd = 1024; 63221888Sadrian } 64221888Sadrian for (fd = 0; fd <= maxfd; fd++) 65221888Sadrian close(fd); 66221888Sadrian /* 67221888Sadrian * Redirect stdin, stdout and stderr to /dev/null. 68221888Sadrian */ 69221888Sadrian fd = open(_PATH_DEVNULL, O_RDONLY); 70221888Sadrian if (fd < 0) { 71221888Sadrian pjdlog_errno(LOG_WARNING, "Unable to open %s for reading", 72221888Sadrian _PATH_DEVNULL); 73221888Sadrian } else if (fd != STDIN_FILENO) { 74221888Sadrian if (dup2(fd, STDIN_FILENO) < 0) { 75221888Sadrian pjdlog_errno(LOG_WARNING, 76221888Sadrian "Unable to duplicate descriptor for stdin"); 77221888Sadrian } 78221888Sadrian close(fd); 79221888Sadrian } 80221888Sadrian fd = open(_PATH_DEVNULL, O_WRONLY); 81221888Sadrian if (fd < 0) { 82221888Sadrian pjdlog_errno(LOG_WARNING, "Unable to open %s for writing", 83221888Sadrian _PATH_DEVNULL); 84221888Sadrian } else { 85221888Sadrian if (fd != STDOUT_FILENO && dup2(fd, STDOUT_FILENO) < 0) { 86221888Sadrian pjdlog_errno(LOG_WARNING, 87221888Sadrian "Unable to duplicate descriptor for stdout"); 88221888Sadrian } 89221888Sadrian if (fd != STDERR_FILENO && dup2(fd, STDERR_FILENO) < 0) { 90221888Sadrian pjdlog_errno(LOG_WARNING, 91221888Sadrian "Unable to duplicate descriptor for stderr"); 92221888Sadrian } 93221888Sadrian if (fd != STDOUT_FILENO && fd != STDERR_FILENO) 94221888Sadrian close(fd); 95221888Sadrian } 96221888Sadrian} 97221888Sadrian 98221888Sadrianint 99221888Sadrianhook_exec(const char *path, ...) 100221888Sadrian{ 101221888Sadrian va_list ap; 102221888Sadrian int ret; 103221888Sadrian 104221888Sadrian va_start(ap, path); 105221888Sadrian ret = hook_execv(path, ap); 106221888Sadrian va_end(ap); 107221888Sadrian return (ret); 108221888Sadrian} 109221888Sadrian 110221888Sadrianint 111221888Sadrianhook_execv(const char *path, va_list ap) 112221888Sadrian{ 113221888Sadrian char *args[64]; 114221888Sadrian unsigned int ii; 115221888Sadrian pid_t pid, wpid; 116221888Sadrian int status; 117221888Sadrian 118221888Sadrian if (path == NULL || path[0] == '\0') 119221888Sadrian return (0); 120221888Sadrian 121221888Sadrian memset(args, 0, sizeof(args)); 122221888Sadrian args[0] = basename(path); 123221888Sadrian for (ii = 1; ii < sizeof(args) / sizeof(args[0]); ii++) { 124221888Sadrian args[ii] = va_arg(ap, char *); 125221888Sadrian if (args[ii] == NULL) 126221888Sadrian break; 127221888Sadrian } 128221888Sadrian assert(ii < sizeof(args) / sizeof(args[0])); 129221888Sadrian 130221888Sadrian pid = fork(); 131221888Sadrian switch (pid) { 132221888Sadrian case -1: /* Error. */ 133221888Sadrian pjdlog_errno(LOG_ERR, "Unable to fork %s", path); 134221888Sadrian return (-1); 135221888Sadrian case 0: /* Child. */ 136221888Sadrian descriptors(); 137221888Sadrian execv(path, args); 138221888Sadrian pjdlog_errno(LOG_ERR, "Unable to execute %s", path); 139221888Sadrian exit(EX_SOFTWARE); 140221888Sadrian default: /* Parent. */ 141221888Sadrian break; 142221888Sadrian } 143221888Sadrian 144221888Sadrian wpid = waitpid(pid, &status, 0); 145221888Sadrian assert(wpid == pid); 146221888Sadrian 147221888Sadrian return (WEXITSTATUS(status)); 148221888Sadrian} 149221888Sadrian