rcscripts.c
1 /*- 2 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/wait.h> 28 29 #include <errno.h> 30 #include <fcntl.h> 31 #include <spawn.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 #include "pkg.h" 36 #include "private/pkg.h" 37 #include "private/event.h" 38 39 static int rc_stop(const char *); 40 static int rc_start(const char *); 41 42 extern char **environ; 43 44 int 45 pkg_start_stop_rc_scripts(struct pkg *pkg, pkg_rc_attr attr) 46 { 47 struct pkg_file *file = NULL; 48 char rc_d_path[PATH_MAX]; 49 const char *rcfile; 50 size_t len = 0; 51 int ret = 0; 52 bool handle_rc; 53 54 handle_rc = pkg_object_bool(pkg_config_get("HANDLE_RC_SCRIPTS")); 55 if (!handle_rc) 56 return (ret); 57 58 snprintf(rc_d_path, sizeof(rc_d_path), "%s/etc/rc.d/", pkg->prefix); 59 len = strlen(rc_d_path); 60 61 while (pkg_files(pkg, &file) == EPKG_OK) { 62 if (strncmp(rc_d_path, file->path, len) == 0) { 63 rcfile = file->path; 64 rcfile += len; 65 switch (attr) { 66 case PKG_RC_START: 67 ret += rc_start(rcfile); 68 break; 69 case PKG_RC_STOP: 70 ret += rc_stop(rcfile); 71 break; 72 } 73 } 74 } 75 76 return (ret); 77 } 78 79 static int 80 rc_stop(const char *rc_file) 81 { 82 int error, pstat; 83 pid_t pid; 84 posix_spawn_file_actions_t actions; 85 const char *argv[4]; 86 87 if (rc_file == NULL) 88 return (0); 89 90 argv[0] = "service"; 91 argv[1] = rc_file; 92 argv[2] = "onestatus"; 93 argv[3] = NULL; 94 95 if ((error = posix_spawn_file_actions_init(&actions)) != 0 || 96 (error = posix_spawn_file_actions_addopen(&actions, 97 STDOUT_FILENO, "/dev/null", O_RDONLY, 0)) != 0 || 98 (error = posix_spawn_file_actions_addopen(&actions, 99 STDERR_FILENO, "/dev/null", O_RDONLY, 0)) != 0 || 100 (error = posix_spawn(&pid, "/usr/sbin/service", &actions, NULL, 101 __DECONST(char **, argv), environ)) != 0) { 102 errno = error; 103 pkg_errno("Cannot query service '%s'", rc_file); 104 return (-1); 105 } 106 107 while (waitpid(pid, &pstat, 0) == -1) { 108 if (errno != EINTR) 109 return (-1); 110 } 111 112 if (WEXITSTATUS(pstat) != 0) 113 return (0); 114 115 posix_spawn_file_actions_destroy(&actions); 116 117 argv[2] = "stop"; 118 119 if ((error = posix_spawn(&pid, "/usr/sbin/service", NULL, NULL, 120 __DECONST(char **, argv), environ)) != 0) { 121 errno = error; 122 pkg_errno("Cannot stop service '%s'", rc_file); 123 return (-1); 124 } 125 126 while (waitpid(pid, &pstat, 0) == -1) { 127 if (errno != EINTR) 128 return (-1); 129 } 130 131 return (WEXITSTATUS(pstat)); 132 } 133 134 static int 135 rc_start(const char *rc_file) 136 { 137 int error, pstat; 138 pid_t pid; 139 const char *argv[4]; 140 141 if (rc_file == NULL) 142 return (0); 143 144 argv[0] = "service"; 145 argv[1] = rc_file; 146 argv[2] = "quietstart"; 147 argv[3] = NULL; 148 149 if ((error = posix_spawn(&pid, "/usr/sbin/service", NULL, NULL, 150 __DECONST(char **, argv), environ)) != 0) { 151 errno = error; 152 pkg_errno("Cannot start service '%s'", rc_file); 153 return (-1); 154 } 155 156 while (waitpid(pid, &pstat, 0) == -1) { 157 if (errno != EINTR) 158 return (-1); 159 } 160 161 return (WEXITSTATUS(pstat)); 162 } 163 164