hooks.c revision 204076
1238384Sjkim/*- 2280304Sjkim * Copyright (c) 2010 The FreeBSD Foundation 3280304Sjkim * All rights reserved. 4238384Sjkim * 5238384Sjkim * This software was developed by Pawel Jakub Dawidek under sponsorship from 6238384Sjkim * the FreeBSD Foundation. 7238384Sjkim * 8238384Sjkim * Redistribution and use in source and binary forms, with or without 9238384Sjkim * modification, are permitted provided that the following conditions 10238384Sjkim * are met: 11238384Sjkim * 1. Redistributions of source code must retain the above copyright 12238384Sjkim * notice, this list of conditions and the following disclaimer. 13238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer in the 15238384Sjkim * documentation and/or other materials provided with the distribution. 16238384Sjkim * 17238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18238384Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20238384Sjkim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21238384Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22238384Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23238384Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25238384Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26238384Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27238384Sjkim * SUCH DAMAGE. 28238384Sjkim */ 29238384Sjkim 30238384Sjkim#include <sys/cdefs.h> 31238384Sjkim__FBSDID("$FreeBSD: head/sbin/hastd/hooks.c 204076 2010-02-18 23:16:19Z pjd $"); 32238384Sjkim 33238384Sjkim#include <sys/types.h> 34238384Sjkim#include <sys/wait.h> 35238384Sjkim 36238384Sjkim#include <assert.h> 37238384Sjkim#include <fcntl.h> 38238384Sjkim#include <stdio.h> 39238384Sjkim#include <stdlib.h> 40238384Sjkim#include <unistd.h> 41238384Sjkim#include <string.h> 42238384Sjkim#include <syslog.h> 43238384Sjkim#include <libgen.h> 44238384Sjkim#include <paths.h> 45238384Sjkim 46238384Sjkim#include <pjdlog.h> 47238384Sjkim 48238384Sjkim#include "hooks.h" 49238384Sjkim 50238384Sjkimstatic void 51238384Sjkimdescriptors(void) 52238384Sjkim{ 53238384Sjkim long maxfd; 54238384Sjkim int fd; 55238384Sjkim 56238384Sjkim /* 57238384Sjkim * Close all descriptors. 58280304Sjkim */ 59238384Sjkim maxfd = sysconf(_SC_OPEN_MAX); 60280304Sjkim if (maxfd < 0) { 61280304Sjkim pjdlog_errno(LOG_WARNING, "sysconf(_SC_OPEN_MAX) failed"); 62280304Sjkim maxfd = 1024; 63280304Sjkim } 64238384Sjkim for (fd = 0; fd <= maxfd; fd++) 65280304Sjkim close(fd); 66280304Sjkim /* 67280304Sjkim * Redirect stdin, stdout and stderr to /dev/null. 68280304Sjkim */ 69238384Sjkim fd = open(_PATH_DEVNULL, O_RDONLY); 70280304Sjkim if (fd < 0) { 71280304Sjkim pjdlog_errno(LOG_WARNING, "Unable to open %s for reading", 72280304Sjkim _PATH_DEVNULL); 73280304Sjkim } else if (fd != STDIN_FILENO) { 74238384Sjkim if (dup2(fd, STDIN_FILENO) < 0) { 75280304Sjkim pjdlog_errno(LOG_WARNING, 76280304Sjkim "Unable to duplicate descriptor for stdin"); 77280304Sjkim } 78280304Sjkim close(fd); 79280304Sjkim } 80280304Sjkim fd = open(_PATH_DEVNULL, O_WRONLY); 81280304Sjkim if (fd < 0) { 82280304Sjkim pjdlog_errno(LOG_WARNING, "Unable to open %s for writing", 83280304Sjkim _PATH_DEVNULL); 84280304Sjkim } else { 85280304Sjkim if (fd != STDOUT_FILENO && dup2(fd, STDOUT_FILENO) < 0) { 86280304Sjkim pjdlog_errno(LOG_WARNING, 87280304Sjkim "Unable to duplicate descriptor for stdout"); 88280304Sjkim } 89280304Sjkim if (fd != STDERR_FILENO && dup2(fd, STDERR_FILENO) < 0) { 90280304Sjkim pjdlog_errno(LOG_WARNING, 91280304Sjkim "Unable to duplicate descriptor for stderr"); 92280304Sjkim } 93280304Sjkim if (fd != STDOUT_FILENO && fd != STDERR_FILENO) 94280304Sjkim close(fd); 95280304Sjkim } 96280304Sjkim} 97280304Sjkim 98280304Sjkimint 99280304Sjkimhook_exec(const char *path, ...) 100280304Sjkim{ 101280304Sjkim va_list ap; 102280304Sjkim int ret; 103280304Sjkim 104280304Sjkim va_start(ap, path); 105280304Sjkim ret = hook_execv(path, ap); 106280304Sjkim va_end(ap); 107280304Sjkim return (ret); 108280304Sjkim} 109280304Sjkim 110280304Sjkimint 111280304Sjkimhook_execv(const char *path, va_list ap) 112280304Sjkim{ 113280304Sjkim char *args[64]; 114280304Sjkim unsigned int ii; 115280304Sjkim pid_t pid, wpid; 116280304Sjkim int status; 117280304Sjkim 118280304Sjkim if (path == NULL || path[0] == '\0') 119280304Sjkim return (0); 120280304Sjkim 121280304Sjkim memset(args, 0, sizeof(args)); 122280304Sjkim args[0] = basename(path); 123280304Sjkim for (ii = 1; ii < sizeof(args) / sizeof(args[0]); ii++) { 124280304Sjkim args[ii] = va_arg(ap, char *); 125280304Sjkim if (args[ii] == NULL) 126280304Sjkim break; 127280304Sjkim } 128280304Sjkim assert(ii < sizeof(args) / sizeof(args[0])); 129280304Sjkim 130280304Sjkim pid = fork(); 131280304Sjkim switch (pid) { 132280304Sjkim case -1: /* Error. */ 133280304Sjkim pjdlog_errno(LOG_ERR, "Unable to fork %s", path); 134280304Sjkim return (-1); 135280304Sjkim case 0: /* Child. */ 136280304Sjkim descriptors(); 137280304Sjkim execv(path, args); 138280304Sjkim pjdlog_errno(LOG_ERR, "Unable to execute %s", path); 139280304Sjkim exit(EX_SOFTWARE); 140280304Sjkim default: /* Parent. */ 141280304Sjkim break; 142280304Sjkim } 143280304Sjkim 144280304Sjkim wpid = waitpid(pid, &status, 0); 145280304Sjkim assert(wpid == pid); 146280304Sjkim 147280304Sjkim return (WEXITSTATUS(status)); 148280304Sjkim} 149280304Sjkim