/ libpkg / rcscripts.c
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