mirror of
https://github.com/pygos/init.git
synced 2024-11-05 04:07:10 +01:00
cleanup: merge runsvc back into initd
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
parent
0975ed0fb7
commit
5f28289731
5 changed files with 156 additions and 216 deletions
|
@ -3,12 +3,6 @@ shutdown_CPPFLAGS = $(AM_CPPFLAGS)
|
|||
shutdown_CFLAGS = $(AM_CFLAGS)
|
||||
shutdown_LDFLAGS = $(AM_LDFLAGS)
|
||||
|
||||
runsvc_SOURCES = cmd/runsvc.c
|
||||
runsvc_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
runsvc_CFLAGS = $(AM_CFLAGS)
|
||||
runsvc_LDFLAGS = $(AM_LDFLAGS)
|
||||
runsvc_LDADD = libinit.a libcfg.a
|
||||
|
||||
killall5_SOURCES = cmd/killall5.c
|
||||
killall5_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
killall5_CFLAGS = $(AM_CFLAGS)
|
||||
|
@ -37,4 +31,4 @@ dist_man8_MANS += cmd/shutdown.8 cmd/service/service.8
|
|||
EXTRA_DIST += $(SRVHEADERS)
|
||||
|
||||
sbin_PROGRAMS += service shutdown
|
||||
helper_PROGRAMS += killall5 runsvc waitfile
|
||||
helper_PROGRAMS += killall5 waitfile
|
||||
|
|
195
cmd/runsvc.c
195
cmd/runsvc.c
|
@ -1,195 +0,0 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "service.h"
|
||||
#include "libcfg.h"
|
||||
#include "config.h"
|
||||
|
||||
#define ENVFILE ETCPATH "/initd.env"
|
||||
#define PROCFDDIR "/proc/self/fd"
|
||||
|
||||
static int setup_env(void)
|
||||
{
|
||||
int status = -1;
|
||||
ssize_t ret;
|
||||
FILE *fp;
|
||||
|
||||
clearenv();
|
||||
|
||||
fp = fopen(ENVFILE, "r");
|
||||
if (fp == NULL) {
|
||||
perror(ENVFILE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
char *line = NULL;
|
||||
size_t n = 0;
|
||||
|
||||
errno = 0;
|
||||
ret = getline(&line, &n, fp);
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == 0) {
|
||||
status = 0;
|
||||
} else {
|
||||
perror(ENVFILE);
|
||||
}
|
||||
} else if (ret > 0 && putenv(line) != 0) {
|
||||
perror("putenv");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free(line);
|
||||
} while (ret >= 0);
|
||||
|
||||
fclose(fp);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int close_all_files(void)
|
||||
{
|
||||
struct dirent *ent;
|
||||
DIR *dir;
|
||||
int fd;
|
||||
|
||||
dir = opendir(PROCFDDIR);
|
||||
if (dir == NULL) {
|
||||
perror(PROCFDDIR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
if (!isdigit(ent->d_name[0]))
|
||||
continue;
|
||||
|
||||
fd = atoi(ent->d_name);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_tty(const char *tty, bool truncate)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (tty == NULL)
|
||||
return 0;
|
||||
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror(tty);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (truncate)
|
||||
ftruncate(fd, 0);
|
||||
|
||||
setsid();
|
||||
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((noreturn)) void argv_exec(exec_t *e)
|
||||
{
|
||||
char **argv = alloca(sizeof(char *) * (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);
|
||||
}
|
||||
|
||||
static int run_sequentially(exec_t *list)
|
||||
{
|
||||
pid_t ret, pid;
|
||||
int status;
|
||||
|
||||
for (; list != NULL; list = list->next) {
|
||||
if (list->next == NULL)
|
||||
argv_exec(list);
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
service_t *svc = NULL;
|
||||
int dirfd;
|
||||
|
||||
if (argc != 3) {
|
||||
fputs("usage: runsvc <directory> <filename>\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (getppid() != 1) {
|
||||
fputs("must be run by init!\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
dirfd = open(argv[1], O_RDONLY | O_DIRECTORY);
|
||||
if (dirfd < 0) {
|
||||
perror(argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
svc = rdsvc(dirfd, argv[2], RDSVC_NO_FNAME | RDSVC_NO_DEPS);
|
||||
close(dirfd);
|
||||
if (svc == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (setup_env())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (close_all_files())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (setup_tty(svc->ctty, (svc->flags & SVC_FLAG_TRUNCATE_OUT) != 0))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
return run_sequentially(svc->exec);
|
||||
}
|
|
@ -24,7 +24,8 @@
|
|||
#include "service.h"
|
||||
#include "config.h"
|
||||
|
||||
#define RUNSVCBIN SCRIPTDIR "/runsvc"
|
||||
#define ENVFILE ETCPATH "/initd.env"
|
||||
#define PROCFDDIR "/proc/self/fd"
|
||||
|
||||
enum {
|
||||
STATUS_OK = 0,
|
||||
|
|
162
initd/runsvc.c
162
initd/runsvc.c
|
@ -3,23 +3,154 @@
|
|||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "init.h"
|
||||
|
||||
static int setup_env(void)
|
||||
{
|
||||
int status = -1;
|
||||
ssize_t ret;
|
||||
FILE *fp;
|
||||
|
||||
clearenv();
|
||||
|
||||
fp = fopen(ENVFILE, "r");
|
||||
if (fp == NULL) {
|
||||
perror(ENVFILE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
char *line = NULL;
|
||||
size_t n = 0;
|
||||
|
||||
errno = 0;
|
||||
ret = getline(&line, &n, fp);
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == 0) {
|
||||
status = 0;
|
||||
} else {
|
||||
perror(ENVFILE);
|
||||
}
|
||||
} else if (ret > 0 && putenv(line) != 0) {
|
||||
perror("putenv");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free(line);
|
||||
} while (ret >= 0);
|
||||
|
||||
fclose(fp);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int close_all_files(void)
|
||||
{
|
||||
struct dirent *ent;
|
||||
DIR *dir;
|
||||
int fd;
|
||||
|
||||
dir = opendir(PROCFDDIR);
|
||||
if (dir == NULL) {
|
||||
perror(PROCFDDIR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
if (!isdigit(ent->d_name[0]))
|
||||
continue;
|
||||
|
||||
fd = atoi(ent->d_name);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_tty(const char *tty, bool truncate)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (tty == NULL)
|
||||
return 0;
|
||||
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror(tty);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (truncate)
|
||||
ftruncate(fd, 0);
|
||||
|
||||
setsid();
|
||||
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((noreturn)) void argv_exec(exec_t *e)
|
||||
{
|
||||
char **argv = alloca(sizeof(char *) * (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);
|
||||
}
|
||||
|
||||
static int run_sequentially(exec_t *list)
|
||||
{
|
||||
pid_t ret, pid;
|
||||
int status;
|
||||
|
||||
for (; list != NULL; list = list->next) {
|
||||
if (list->next == NULL)
|
||||
argv_exec(list);
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0)
|
||||
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 runsvc(service_t *svc)
|
||||
{
|
||||
char *argv[4], *envp[1];
|
||||
sigset_t mask;
|
||||
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)
|
||||
|
@ -29,9 +160,18 @@ pid_t runsvc(service_t *svc)
|
|||
sigemptyset(&mask);
|
||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
|
||||
execve(argv[0], argv, envp);
|
||||
perror(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
if (setup_env())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (close_all_files())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (setup_tty(svc->ctty,
|
||||
(svc->flags & SVC_FLAG_TRUNCATE_OUT) != 0)) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit(run_sequentially(svc->exec));
|
||||
}
|
||||
|
||||
return pid;
|
||||
|
|
|
@ -175,7 +175,7 @@ void supervisor_init(void)
|
|||
{
|
||||
int status = STATUS_OK;
|
||||
|
||||
if (svcscan(SVCDIR, &cfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY))
|
||||
if (svcscan(SVCDIR, &cfg, 0))
|
||||
status = STATUS_FAIL;
|
||||
|
||||
target = TGT_BOOT;
|
||||
|
@ -191,7 +191,7 @@ void supervisor_reload_config(void)
|
|||
service_t *svc;
|
||||
int i;
|
||||
|
||||
if (svcscan(SVCDIR, &newcfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY))
|
||||
if (svcscan(SVCDIR, &newcfg, 0))
|
||||
return;
|
||||
|
||||
for (i = 0; i < TGT_MAX; ++i) {
|
||||
|
|
Loading…
Reference in a new issue