diff options
Diffstat (limited to 'initd')
| -rw-r--r-- | initd/Makemodule.am | 4 | ||||
| -rw-r--r-- | initd/env.c | 137 | ||||
| -rw-r--r-- | initd/init.h | 39 | ||||
| -rw-r--r-- | initd/main.c | 14 | ||||
| -rw-r--r-- | initd/runlst.c | 120 | ||||
| -rw-r--r-- | initd/runsvc.c | 66 | 
6 files changed, 80 insertions, 300 deletions
diff --git a/initd/Makemodule.am b/initd/Makemodule.am index 67515cc..f188c80 100644 --- a/initd/Makemodule.am +++ b/initd/Makemodule.am @@ -1,5 +1,5 @@ -init_SOURCES = initd/main.c initd/runlst.c initd/init.h initd/signal_linux.c -init_SOURCES += initd/status.c initd/mksock.c initd/svclist.c initd/env.c +init_SOURCES = initd/main.c initd/init.h initd/signal_linux.c initd/runsvc.c +init_SOURCES += initd/status.c initd/mksock.c initd/svclist.c  init_CPPFLAGS = $(AM_CPPFLAGS)  init_CFLAGS = $(AM_CFLAGS)  init_LDFLAGS = $(AM_LDFLAGS) diff --git a/initd/env.c b/initd/env.c deleted file mode 100644 index c6a9e65..0000000 --- a/initd/env.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * Copyright (C) 2018 - David Oberhollenzer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> - -#include "init.h" -#include "util.h" - -struct entry { -	struct entry *next; -	char data[]; -}; - -extern char **environ; - -static void free_list(struct entry *list) -{ -	struct entry *e; - -	while (list != NULL) { -		e = list; -		list = list->next; -		free(e); -	} -} - -static struct entry *parse_list(rdline_t *rd) -{ -	struct entry *e, *list = NULL; -	char *ptr; - -	while (rdline(rd) == 0) { -		ptr = rd->buffer; - -		while (*ptr != '\0' && *ptr != ' ' && *ptr != '=') -			++ptr; - -		if (*ptr == ' ') -			memmove(ptr, ptr + 1, strlen(ptr + 1) + 1); - -		if (*(ptr++) != '=') { -			fprintf(stderr, "%s: %zu: line is not of the shape " -					"'key = value', skipping\n", -				rd->filename, rd->lineno); -			continue; -		} - -		if (*ptr == ' ') -			memmove(ptr, ptr + 1, strlen(ptr + 1) + 1); - -		if (unescape(ptr)) { -			fprintf(stderr, "%s: %zu: malformed string constant, " -					"skipping\n", -				rd->filename, rd->lineno); -			continue; -		} - -		e = calloc(1, sizeof(*e) + strlen(rd->buffer) + 1); -		if (e == NULL) -			goto fail_oom; - -		strcpy(e->data, rd->buffer); -		e->next = list; -		list = e; -	} - -	return list; -fail_oom: -	fputs("out of memory\n", stderr); -	free_list(list); -	return NULL; -} - -static struct entry *list_from_file(void) -{ -	struct entry *list; -	rdline_t rd; -	int fd; - -	fd = open(ENVFILE, O_RDONLY); -	if (fd < 0) { -		perror(ENVFILE); -		return NULL; -	} - -	rdline_init(&rd, fd, ENVFILE, 0, NULL); -	list = parse_list(&rd); -	close(fd); -	return list; -} - -int initenv(void) -{ -	struct entry *list, *e; -	int i, count; -	char **envp; - -	list = list_from_file(); -	if (list == NULL) -		return -1; - -	for (count = 0, e = list; e != NULL; e = e->next) -		++count; - -	envp = malloc((count + 1) * sizeof(char *)); -	if (envp == NULL) { -		fputs("out of memory\n", stderr); -		free_list(list); -		return -1; -	} - -	for (i = 0, e = list; e != NULL; e = e->next) -		envp[i] = e->data; - -	envp[i] = NULL; - -	environ = envp; -	return 0; -} diff --git a/initd/init.h b/initd/init.h index 3510073..d07f310 100644 --- a/initd/init.h +++ b/initd/init.h @@ -27,7 +27,7 @@  #include "telinit.h"  #include "util.h" -#define ENVFILE ETCPATH "/initd.env" +#define RUNSVCBIN SCRIPTDIR "/runsvc"  enum {  	STATUS_OK = 0, @@ -36,35 +36,20 @@ enum {  	STATUS_STARTED,  }; -/********** runlst.c **********/ +/********** runsvc.c **********/  /* -	Plow through an array of strings and execute each one, i.e. do -	a fork() and exec(). +	Invoke the runsvc command to execute the comands of a service. -	In the parent process, wait() until the child is done before -	continuing through the list. - -	If ctty is not NULL, open it and redirect all I/O of the child -	process to that file. - -	If everyhing works, the function returns EXIT_SUCCESS. If one child -	does not exit with EXIT_SUCCESS, processing of the list is aborted -	and the function returns the exit status of the failed process. +	Returns the pid of the child process containing the runsvc instance.  */ -int runlst_wait(exec_t *list, const char *ctty); +pid_t runsvc(service_t *svc);  /* -	Does basically the same as runlst_wait, but asynchronously. - -	A child process is created that calls runlst_wait exits with the -	result of runlst_wait. In the parent process, the function returns -	immediately with the PID of the child process. - -	Alternatively, if num is 1, the child process directly exec()s the -	given command. +	Start a service using runsvc, but wait until the child process +	terminats and return its exit status.  */ -pid_t runlst(exec_t *list, const char *ctty); +int runsvc_wait(service_t *svc);  /********** status.c **********/ @@ -111,14 +96,6 @@ void svclist_add(service_t *svc);  */  service_t *svclist_remove(pid_t pid); -/********** env.c **********/ - -/* -	Read /etc/initd.env (actually ENVFILE defined above) -	and setup environment variables for init. -*/ -int initenv(void); -  /********** signal_<platform>.c **********/  /* diff --git a/initd/main.c b/initd/main.c index a1d6906..8adbe2f 100644 --- a/initd/main.c +++ b/initd/main.c @@ -48,7 +48,7 @@ static void handle_exited(service_t *svc)  			}  		} -		svc->pid = runlst(svc->exec, svc->ctty); +		svc->pid = runsvc(svc);  		if (svc->pid == -1) {  			print_status(svc->desc, STATUS_FAIL, false);  			break; @@ -104,16 +104,10 @@ static void start_runlevel(int level)  		svc = cfg.targets[level];  		cfg.targets[level] = svc->next; -		if (svc->exec == NULL) { -			print_status(svc->desc, STATUS_OK, false); -			delsvc(svc); -			continue; -		} -  		if (svc->type == SVC_WAIT) {  			print_status(svc->desc, STATUS_WAIT, false); -			status = runlst_wait(svc->exec, svc->ctty); +			status = runsvc_wait(svc);  			print_status(svc->desc,  				     status == EXIT_SUCCESS ? @@ -121,7 +115,7 @@ static void start_runlevel(int level)  				     true);  			delsvc(svc);  		} else { -			svc->pid = runlst(svc->exec, svc->ctty); +			svc->pid = runsvc(svc);  			if (svc->pid == -1) {  				print_status(svc->desc, STATUS_FAIL, false);  				delsvc(svc); @@ -193,7 +187,7 @@ int main(void)  		return EXIT_FAILURE;  	} -	if (svcscan(SVCDIR, &cfg, 0)) { +	if (svcscan(SVCDIR, &cfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY)) {  		fputs("Error reading service list from " SVCDIR "\n"  			"Trying to continue anyway\n", stderr);  	} diff --git a/initd/runlst.c b/initd/runlst.c deleted file mode 100644 index 83823f9..0000000 --- a/initd/runlst.c +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * Copyright (C) 2018 - David Oberhollenzer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ -#include <sys/wait.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <fcntl.h> - -#include "init.h" - -static int child_setup(const char *ctty) -{ -	int fd; - -	sigreset(); - -	if (ctty != NULL) { -		fd = open(ctty, O_RDWR); -		if (fd < 0) { -			perror(ctty); -			return -1; -		} - -		close(STDIN_FILENO); -		close(STDOUT_FILENO); -		close(STDERR_FILENO); - -		setsid(); - -		dup2(fd, STDIN_FILENO); -		dup2(fd, STDOUT_FILENO); -		dup2(fd, STDERR_FILENO); -		close(fd); -	} - -	return 0; -} - -static NORETURN void argv_exec(exec_t *e) -{ -	char **argv = alloca(e->argc + 1), *ptr; -	int i; - -	for (ptr = e->args, i = 0; i < e->argc; ++i, ptr += strlen(ptr) + 1) -		argv[i] = ptr; - -	argv[i] = NULL; -	execvp(argv[0], argv); -	perror(argv[0]); -	exit(EXIT_FAILURE); -} - -int runlst_wait(exec_t *list, const char *ctty) -{ -	pid_t ret, pid; -	int status; - -	for (; list != NULL; list = list->next) { -		pid = fork(); - -		if (pid == 0) { -			if (child_setup(ctty)) -				exit(EXIT_FAILURE); -			argv_exec(list); -		} - -		if (pid == -1) { -			perror("fork"); -			return EXIT_FAILURE; -		} - -		do { -			ret = waitpid(pid, &status, 0); -		} while (ret != pid); - -		if (!WIFEXITED(status)) -			return EXIT_FAILURE; - -		if (WEXITSTATUS(status) != EXIT_SUCCESS) -			return WEXITSTATUS(status); -	} - -	return EXIT_SUCCESS; -} - -pid_t runlst(exec_t *list, const char *ctty) -{ -	pid_t pid = fork(); - -	if (pid == 0) { -		if (child_setup(ctty)) -			exit(EXIT_FAILURE); - -		if (list->next != NULL) -			exit(runlst_wait(list, NULL)); - -		argv_exec(list); -	} - -	if (pid == -1) -		perror("fork"); - -	return pid; -} diff --git a/initd/runsvc.c b/initd/runsvc.c new file mode 100644 index 0000000..aba83b1 --- /dev/null +++ b/initd/runsvc.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * Copyright (C) 2018 - David Oberhollenzer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> + +#include "init.h" + +pid_t runsvc(service_t *svc) +{ +	char *argv[4], *envp[1]; +	pid_t pid; + +	argv[0] = (char *)RUNSVCBIN; +	argv[1] = (char *)SVCDIR; +	argv[2] = svc->fname; +	argv[3] = NULL; + +	envp[0] = NULL; + +	pid = fork(); + +	if (pid == -1) +		perror("fork"); + +	if (pid == 0) { +		sigreset(); +		execve(argv[0], argv, envp); +		perror(argv[0]); +		exit(EXIT_FAILURE); +	} + +	return pid; +} + +int runsvc_wait(service_t *svc) +{ +	pid_t ret, pid = runsvc(svc); +	int status; + +	if (pid == -1) +		return EXIT_FAILURE; + +	do { +		ret = waitpid(pid, &status, 0); +	} while (ret != pid); + +	return WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE; +}  | 
