1
0
Fork 0
mirror of https://github.com/pygos/init.git synced 2024-11-14 15:57:10 +01:00

Compare commits

...

10 commits

Author SHA1 Message Date
5307b95b93 Cleanup: remove flag mechanism from config parser entirely
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2020-04-24 12:28:06 +02:00
70ea16b0b4 Cleanup: remove rdsvc flags
With the previous changes, there were only used by the status
command.

Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2020-04-24 12:26:26 +02:00
5f28289731 cleanup: merge runsvc back into initd
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2020-04-24 12:09:18 +02:00
0975ed0fb7 runsvc: make sure we close all fds before running a service
Just in case initd leaks anything. Also, the service has no
buisness writing all over /dev/console. It's a system service, it
better use syslog or its own internal logging service.

Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2020-04-06 15:55:47 +02:00
9b43890591 cleanup: simplify runsvc environment config parsing
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2020-04-06 15:44:15 +02:00
87a524d931 cleanup: delete remains of libutil
- exec_t belongs to service.h, the main place where it is used/needed
 - code for executing exec_t is moved to runsvc for the same reason
 - what is left are NORETURN and ARRAY_SIZE
   - the former can be replaced with direct attribute usage since
     the only relevant compilers all support the attribute.
   - the later is only used in 3 places and can be trivially replaced
     with direct usage of sizeof().

Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2020-03-31 18:19:27 +02:00
9f9807d4d3 cleanup: initd: simplify and merge linux specific code into main.c
Targetting anything else than Linux isn't really relevant. All
other systems ($BSD and other Unices) are a closed ecosystem
where kernel & userspace are developed together. They don't need
something like a third party init system, so compatibillity can
be largely ignored.

Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2020-03-31 13:09:04 +02:00
0d985a7430 Add RDSVC_NO_DESC flag
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2019-06-16 20:51:23 +02:00
60efd9dc33 Remove unused SOCK_FLAG_* enum
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2019-06-16 18:20:26 +02:00
1c72dd2c2f Fix remove by id
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
2019-06-16 16:09:49 +02:00
28 changed files with 233 additions and 460 deletions

View file

@ -3,12 +3,6 @@ shutdown_CPPFLAGS = $(AM_CPPFLAGS)
shutdown_CFLAGS = $(AM_CFLAGS) shutdown_CFLAGS = $(AM_CFLAGS)
shutdown_LDFLAGS = $(AM_LDFLAGS) shutdown_LDFLAGS = $(AM_LDFLAGS)
runsvc_SOURCES = cmd/runsvc/runsvc.c cmd/runsvc/env.c cmd/runsvc/runsvc.h
runsvc_CPPFLAGS = $(AM_CPPFLAGS)
runsvc_CFLAGS = $(AM_CFLAGS)
runsvc_LDFLAGS = $(AM_LDFLAGS)
runsvc_LDADD = libinit.a libcfg.a libutil.a
killall5_SOURCES = cmd/killall5.c killall5_SOURCES = cmd/killall5.c
killall5_CPPFLAGS = $(AM_CPPFLAGS) killall5_CPPFLAGS = $(AM_CPPFLAGS)
killall5_CFLAGS = $(AM_CFLAGS) killall5_CFLAGS = $(AM_CFLAGS)
@ -30,11 +24,11 @@ service_SOURCES += $(SRVHEADERS)
service_CPPFLAGS = $(AM_CPPFLAGS) service_CPPFLAGS = $(AM_CPPFLAGS)
service_CFLAGS = $(AM_CFLAGS) service_CFLAGS = $(AM_CFLAGS)
service_LDFLAGS = $(AM_LDFLAGS) service_LDFLAGS = $(AM_LDFLAGS)
service_LDADD = libinit.a libcfg.a libutil.a service_LDADD = libinit.a libcfg.a
dist_man8_MANS += cmd/shutdown.8 cmd/service/service.8 dist_man8_MANS += cmd/shutdown.8 cmd/service/service.8
EXTRA_DIST += $(SRVHEADERS) EXTRA_DIST += $(SRVHEADERS)
sbin_PROGRAMS += service shutdown sbin_PROGRAMS += service shutdown
helper_PROGRAMS += killall5 runsvc waitfile helper_PROGRAMS += killall5 waitfile

View file

@ -9,9 +9,7 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include "util.h" static __attribute__((noreturn)) void usage_and_exit(void)
static NORETURN void usage_and_exit(void)
{ {
fputs("Usage: killall5 SIGNAL\n", stderr); fputs("Usage: killall5 SIGNAL\n", stderr);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View file

@ -1,109 +0,0 @@
/* SPDX-License-Identifier: ISC */
#include "runsvc.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->line;
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->line) + 1);
if (e == NULL)
goto fail_oom;
strcpy(e->data, rd->line);
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;
if (rdline_init(&rd, AT_FDCWD, ENVFILE, 0, NULL))
return NULL;
list = parse_list(&rd);
rdline_cleanup(&rd);
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;
}

View file

@ -1,72 +0,0 @@
/* SPDX-License-Identifier: ISC */
#include "runsvc.h"
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 (initenv())
return EXIT_FAILURE;
if (setup_tty(svc->ctty, (svc->flags & SVC_FLAG_TRUNCATE_OUT) != 0))
return EXIT_FAILURE;
return run_sequentially(svc->exec);
}

View file

@ -1,21 +0,0 @@
/* SPDX-License-Identifier: ISC */
#ifndef RUNSVC_H
#define RUNSVC_H
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include "service.h"
#include "libcfg.h"
#include "util.h"
#define ENVFILE ETCPATH "/initd.env"
int initenv(void);
#endif /* RUNSVC_H */

View file

@ -93,7 +93,7 @@ static int cmd_dumpscript(int argc, char **argv)
strcat(filename, argv[i]); strcat(filename, argv[i]);
} }
svc = loadsvc(SVCDIR, filename, 0); svc = loadsvc(SVCDIR, filename);
if (svc == NULL) { if (svc == NULL) {
fprintf(stderr, "Could not load service '%s'\n", filename); fprintf(stderr, "Could not load service '%s'\n", filename);

View file

@ -24,7 +24,7 @@ static int cmd_list(int argc, char **argv)
if (check_arguments(argv[0], argc, 1, 2)) if (check_arguments(argv[0], argc, 1, 2))
return EXIT_FAILURE; return EXIT_FAILURE;
if (svcscan(SVCDIR, &list, 0)) { if (svcscan(SVCDIR, &list)) {
fprintf(stderr, "Error while reading services from %s\n", fprintf(stderr, "Error while reading services from %s\n",
SVCDIR); SVCDIR);
ret = EXIT_FAILURE; ret = EXIT_FAILURE;

View file

@ -5,7 +5,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
service_t *loadsvc(const char *directory, const char *filename, int flags) service_t *loadsvc(const char *directory, const char *filename)
{ {
service_t *svc; service_t *svc;
int dirfd; int dirfd;
@ -17,7 +17,7 @@ service_t *loadsvc(const char *directory, const char *filename, int flags)
return NULL; return NULL;
} }
svc = rdsvc(dirfd, filename, flags); svc = rdsvc(dirfd, filename);
close(dirfd); close(dirfd);
return svc; return svc;
} }

View file

@ -5,7 +5,6 @@
#include "servicecmd.h" #include "servicecmd.h"
#include "service.h" #include "service.h"
#include "config.h" #include "config.h"
#include "util.h"
command_t *commands; command_t *commands;

View file

@ -2,13 +2,14 @@
#ifndef SERVICECMD_H #ifndef SERVICECMD_H
#define SERVICECMD_H #define SERVICECMD_H
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include "service.h" #include "service.h"
#include "util.h" #include "config.h"
/* /*
Describes a command that can be launched by passing its name as Describes a command that can be launched by passing its name as
@ -39,13 +40,13 @@ typedef struct command_t {
/* Global list of available commands */ /* Global list of available commands */
extern command_t *commands; extern command_t *commands;
service_t *loadsvc(const char *directory, const char *filename, int flags); service_t *loadsvc(const char *directory, const char *filename);
/* /*
Implemented in servicecmd.c. Prints program usage message and Implemented in servicecmd.c. Prints program usage message and
terminates with the given exit status. terminates with the given exit status.
*/ */
void usage(int status) NORETURN; void usage(int status) __attribute__((noreturn));
/* /*
Write a message to stderr that advises the user how to consult the Write a message to stderr that advises the user how to consult the

View file

@ -128,9 +128,7 @@ static int cmd_status(int argc, char **argv)
printf("\tTemplate name: %s\n", resp.service_name); printf("\tTemplate name: %s\n", resp.service_name);
printf("\tExit status: %d\n", resp.exit_status); printf("\tExit status: %d\n", resp.exit_status);
svc = loadsvc(SVCDIR, resp.filename, svc = loadsvc(SVCDIR, resp.filename);
RDSVC_NO_EXEC | RDSVC_NO_DEPS |
RDSVC_NO_CTTY | RDSVC_NO_FNAME);
if (svc == NULL) { if (svc == NULL) {
fputs("\tError loading service file\n", stdout); fputs("\tError loading service file\n", stdout);

View file

@ -10,8 +10,6 @@
#include <sys/reboot.h> #include <sys/reboot.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include "util.h"
#define FL_FORCE 0x01 #define FL_FORCE 0x01
#define FL_NOSYNC 0x02 #define FL_NOSYNC 0x02
@ -29,7 +27,7 @@ static const char *shortopt = "hprfn";
static const char *defact_str = "power-off"; static const char *defact_str = "power-off";
static int defact = RB_POWER_OFF; static int defact = RB_POWER_OFF;
static NORETURN void usage(const char *progname, int status) static __attribute__((noreturn)) void usage(const char *progname, int status)
{ {
fprintf(status == EXIT_SUCCESS ? stdout : stderr, fprintf(status == EXIT_SUCCESS ? stdout : stderr,
"%s [OPTIONS...]\n\n" "%s [OPTIONS...]\n\n"

View file

@ -1,8 +1,8 @@
init_SOURCES = initd/main.c initd/init.h initd/signal_linux.c initd/runsvc.c init_SOURCES = initd/main.c initd/init.h initd/runsvc.c
init_SOURCES += initd/status.c initd/supervisor.c initd/initsock.c init_SOURCES += initd/status.c initd/supervisor.c initd/initsock.c
init_CPPFLAGS = $(AM_CPPFLAGS) init_CPPFLAGS = $(AM_CPPFLAGS)
init_CFLAGS = $(AM_CFLAGS) init_CFLAGS = $(AM_CFLAGS)
init_LDFLAGS = $(AM_LDFLAGS) init_LDFLAGS = $(AM_LDFLAGS)
init_LDADD = libinit.a libcfg.a libutil.a init_LDADD = libinit.a libcfg.a
sbin_PROGRAMS += init sbin_PROGRAMS += init

View file

@ -17,13 +17,15 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <sys/signalfd.h> #include <sys/signalfd.h>
#include <sys/reboot.h> #include <sys/reboot.h>
#include <stdbool.h>
#include <signal.h> #include <signal.h>
#include "initsock.h" #include "initsock.h"
#include "service.h" #include "service.h"
#include "util.h" #include "config.h"
#define RUNSVCBIN SCRIPTDIR "/runsvc" #define ENVFILE ETCPATH "/initd.env"
#define PROCFDDIR "/proc/self/fd"
enum { enum {
STATUS_OK = 0, STATUS_OK = 0,
@ -77,29 +79,6 @@ void supervisor_start(int id);
void supervisor_stop(int id); void supervisor_stop(int id);
/********** signal_<platform>.c **********/
/*
Setup signal handling. Returns -1 on error, a file descriptor on
success.
The returned file descriptor can be polled and becomes readable
when a signal arrives. Reading from it returns a signalfd_siginfo
structure.
The returned file descriptor has the close on exec flag set.
The kernel is also told to send us SIGINT signals if a user presses
the local equivalent of CTRL+ALT+DEL.
*/
int sigsetup(void);
/*
Undo everything that sigsetup() changed about signal handling and
restore the default.
*/
void sigreset(void);
/********** initsock.c **********/ /********** initsock.c **********/
int init_socket_create(void); int init_socket_create(void);

View file

@ -96,6 +96,29 @@ void target_completed(int target)
} }
} }
static int sigsetup(void)
{
sigset_t mask;
int sfd;
sigfillset(&mask);
if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) {
perror("sigprocmask");
return -1;
}
sfd = signalfd(-1, &mask, SFD_CLOEXEC);
if (sfd == -1) {
perror("signalfd");
return -1;
}
if (reboot(LINUX_REBOOT_CMD_CAD_OFF))
perror("cannot disable CTRL+ALT+DEL");
return sfd;
}
int main(void) int main(void)
{ {
int i, ret, count; int i, ret, count;

View file

@ -3,32 +3,175 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <dirent.h>
#include <stdio.h> #include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include "init.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) pid_t runsvc(service_t *svc)
{ {
char *argv[4], *envp[1]; sigset_t mask;
pid_t pid; pid_t pid;
argv[0] = (char *)RUNSVCBIN;
argv[1] = (char *)SVCDIR;
argv[2] = svc->fname;
argv[3] = NULL;
envp[0] = NULL;
pid = fork(); pid = fork();
if (pid == -1) if (pid == -1)
perror("fork"); perror("fork");
if (pid == 0) { if (pid == 0) {
sigreset(); sigemptyset(&mask);
execve(argv[0], argv, envp); sigprocmask(SIG_SETMASK, &mask, NULL);
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; return pid;

View file

@ -1,42 +0,0 @@
/* SPDX-License-Identifier: ISC */
#include <stdio.h>
#include "init.h"
int sigsetup(void)
{
sigset_t mask;
int sfd;
sigfillset(&mask);
if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) {
perror("sigprocmask");
return -1;
}
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGUSR1);
sigaddset(&mask, SIGHUP);
sfd = signalfd(-1, &mask, SFD_CLOEXEC);
if (sfd == -1) {
perror("signalfd");
return -1;
}
if (reboot(LINUX_REBOOT_CMD_CAD_OFF))
perror("cannot disable CTRL+ALT+DEL");
return sfd;
}
void sigreset(void)
{
sigset_t mask;
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
}

View file

@ -175,7 +175,7 @@ void supervisor_init(void)
{ {
int status = STATUS_OK; int status = STATUS_OK;
if (svcscan(SVCDIR, &cfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY)) if (svcscan(SVCDIR, &cfg))
status = STATUS_FAIL; status = STATUS_FAIL;
target = TGT_BOOT; target = TGT_BOOT;
@ -191,7 +191,7 @@ void supervisor_reload_config(void)
service_t *svc; service_t *svc;
int i; int i;
if (svcscan(SVCDIR, &newcfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY)) if (svcscan(SVCDIR, &newcfg))
return; return;
for (i = 0; i < TGT_MAX; ++i) { for (i = 0; i < TGT_MAX; ++i) {
@ -317,7 +317,7 @@ static service_t *remove_by_id(service_t **list, int id)
if (prev == NULL) { if (prev == NULL) {
*list = svc->next; *list = svc->next;
} else { } else {
prev = svc->next; prev->next = svc->next;
} }
} }

View file

@ -7,13 +7,9 @@ libinit_a_SOURCES += lib/init/init_socket_recv_status.c
libinit_a_CPPFLAGS = $(AM_CPPFLAGS) libinit_a_CPPFLAGS = $(AM_CPPFLAGS)
libinit_a_CFLAGS = $(AM_CFLAGS) libinit_a_CFLAGS = $(AM_CFLAGS)
libutil_a_SOURCES = lib/util/argv_exec.c lib/include/util.h
libutil_a_CPPFLAGS = $(AM_CPPFLAGS)
libutil_a_CFLAGS = $(AM_CFLAGS)
libcfg_a_SOURCES = lib/libcfg/rdline.c lib/libcfg/unescape.c lib/libcfg/rdcfg.c libcfg_a_SOURCES = lib/libcfg/rdline.c lib/libcfg/unescape.c lib/libcfg/rdcfg.c
libcfg_a_SOURCES += lib/libcfg/pack_argv.c lib/include/libcfg.h libcfg_a_SOURCES += lib/libcfg/pack_argv.c lib/include/libcfg.h
libcfg_a_CPPFLAGS = $(AM_CPPFLAGS) libcfg_a_CPPFLAGS = $(AM_CPPFLAGS)
libcfg_a_CFLAGS = $(AM_CFLAGS) libcfg_a_CFLAGS = $(AM_CFLAGS)
noinst_LIBRARIES += libinit.a libcfg.a libutil.a noinst_LIBRARIES += libinit.a libcfg.a

View file

@ -27,7 +27,7 @@ typedef struct {
*/ */
unsigned int allow_block : 1; unsigned int allow_block : 1;
int (*handle)(void *obj, char *arg, rdline_t *rd, int flags); int (*handle)(void *obj, char *arg, rdline_t *rd);
} cfg_param_t; } cfg_param_t;
/* /*
@ -92,11 +92,10 @@ int pack_argv(char *str);
/* /*
Parse a configuration file containing '<keyword> [arguments...]' lines. Parse a configuration file containing '<keyword> [arguments...]' lines.
The cfgobj and flags are passed to the callback in the params array. The cfgobj is passed to the callback in the params array.
Returns zero on success. Returns zero on success.
*/ */
int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count, int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count);
int flags);
#endif /* LIBCONFIG_H */ #endif /* LIBCONFIG_H */

View file

@ -4,7 +4,11 @@
#include <sys/types.h> #include <sys/types.h>
#include "util.h" typedef struct exec_t {
struct exec_t *next;
int argc; /* number of elements in argument vector */
char args[]; /* argument vectot string blob */
} exec_t;
enum { enum {
/* /*
@ -31,13 +35,6 @@ enum {
TGT_MAX TGT_MAX
}; };
enum {
RDSVC_NO_FNAME = 0x01, /* do not store a copy of the filename */
RDSVC_NO_EXEC = 0x02, /* do not store executable script */
RDSVC_NO_CTTY = 0x04, /* do not store the controlling tty */
RDSVC_NO_DEPS = 0x08, /* do not store dependencies */
};
enum { enum {
/* truncate stdout */ /* truncate stdout */
SVC_FLAG_TRUNCATE_OUT = 0x01, SVC_FLAG_TRUNCATE_OUT = 0x01,
@ -82,7 +79,7 @@ typedef struct {
/* /*
Read a service from a file. Read a service from a file.
*/ */
service_t *rdsvc(int dirfd, const char *filename, int flags); service_t *rdsvc(int dirfd, const char *filename);
void delsvc(service_t *svc); void delsvc(service_t *svc);
@ -93,7 +90,7 @@ void delsvc(service_t *svc);
Returns 0 on success, -1 on failure. The function takes care of Returns 0 on success, -1 on failure. The function takes care of
printing error messages on failure. printing error messages on failure.
*/ */
int svcscan(const char *directory, service_list_t *list, int flags); int svcscan(const char *directory, service_list_t *list);
void del_svc_list(service_list_t *list); void del_svc_list(service_list_t *list);

View file

@ -1,39 +0,0 @@
/* SPDX-License-Identifier: ISC */
#ifndef UTIL_H
#define UTIL_H
#include <sys/types.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include "config.h"
#ifdef __GNUC__
#define NORETURN __attribute__((noreturn))
#endif
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
typedef struct exec_t {
struct exec_t *next;
int argc; /* number of elements in argument vector */
char args[]; /* argument vectot string blob */
} exec_t;
enum {
/* only allow root to connect */
SOCK_FLAG_ROOT_ONLY = 0x01,
/* allow everyone to connect */
SOCK_FLAG_EVERYONE = 0x02,
/* create a datagram socket, otherwise use a stream socket */
SOCK_FLAG_DGRAM = 0x04,
};
int setup_tty(const char *tty, bool truncate);
NORETURN void argv_exec(exec_t *e);
#endif /* UTIL_H */

View file

@ -11,7 +11,6 @@
#include "service.h" #include "service.h"
#include "libcfg.h" #include "libcfg.h"
#include "util.h"
static int try_unescape(char *arg, rdline_t *rd) static int try_unescape(char *arg, rdline_t *rd)
{ {
@ -44,10 +43,9 @@ static int try_pack_argv(char *str, rdline_t *rd)
return count; return count;
} }
static int svc_desc(void *user, char *arg, rdline_t *rd, int flags) static int svc_desc(void *user, char *arg, rdline_t *rd)
{ {
service_t *svc = user; service_t *svc = user;
(void)flags;
if (try_unescape(arg, rd)) if (try_unescape(arg, rd))
return -1; return -1;
@ -55,13 +53,10 @@ static int svc_desc(void *user, char *arg, rdline_t *rd, int flags)
return svc->desc == NULL ? -1 : 0; return svc->desc == NULL ? -1 : 0;
} }
static int svc_tty(void *user, char *arg, rdline_t *rd, int flags) static int svc_tty(void *user, char *arg, rdline_t *rd)
{ {
service_t *svc = user; service_t *svc = user;
if (flags & RDSVC_NO_CTTY)
return 0;
if (strncmp(arg, "truncate", 8) == 0 && isspace(arg[8])) { if (strncmp(arg, "truncate", 8) == 0 && isspace(arg[8])) {
svc->flags |= SVC_FLAG_TRUNCATE_OUT; svc->flags |= SVC_FLAG_TRUNCATE_OUT;
arg += 8; arg += 8;
@ -76,16 +71,13 @@ static int svc_tty(void *user, char *arg, rdline_t *rd, int flags)
return svc->ctty == NULL ? -1 : 0; return svc->ctty == NULL ? -1 : 0;
} }
static int svc_exec(void *user, char *arg, rdline_t *rd, int flags) static int svc_exec(void *user, char *arg, rdline_t *rd)
{ {
service_t *svc = user; service_t *svc = user;
exec_t *e, *end; exec_t *e, *end;
svc->flags |= SVC_FLAG_HAS_EXEC; svc->flags |= SVC_FLAG_HAS_EXEC;
if (flags & RDSVC_NO_EXEC)
return 0;
e = calloc(1, sizeof(*e) + strlen(arg) + 1); e = calloc(1, sizeof(*e) + strlen(arg) + 1);
if (e == NULL) { if (e == NULL) {
fprintf(stderr, "%s: %zu: out of memory\n", fprintf(stderr, "%s: %zu: out of memory\n",
@ -109,13 +101,10 @@ static int svc_exec(void *user, char *arg, rdline_t *rd, int flags)
return 0; return 0;
} }
static int svc_before(void *user, char *arg, rdline_t *rd, int flags) static int svc_before(void *user, char *arg, rdline_t *rd)
{ {
service_t *svc = user; service_t *svc = user;
if (flags & RDSVC_NO_DEPS)
return 0;
if (svc->before != NULL) { if (svc->before != NULL) {
fprintf(stderr, "%s: %zu: 'before' dependencies respecified\n", fprintf(stderr, "%s: %zu: 'before' dependencies respecified\n",
rd->filename, rd->lineno); rd->filename, rd->lineno);
@ -130,13 +119,10 @@ static int svc_before(void *user, char *arg, rdline_t *rd, int flags)
return (svc->num_before < 0) ? -1 : 0; return (svc->num_before < 0) ? -1 : 0;
} }
static int svc_after(void *user, char *arg, rdline_t *rd, int flags) static int svc_after(void *user, char *arg, rdline_t *rd)
{ {
service_t *svc = user; service_t *svc = user;
if (flags & RDSVC_NO_DEPS)
return 0;
if (svc->after != NULL) { if (svc->after != NULL) {
fprintf(stderr, "%s: %zu: 'after' dependencies respecified\n", fprintf(stderr, "%s: %zu: 'after' dependencies respecified\n",
rd->filename, rd->lineno); rd->filename, rd->lineno);
@ -151,11 +137,10 @@ static int svc_after(void *user, char *arg, rdline_t *rd, int flags)
return (svc->num_after < 0) ? -1 : 0; return (svc->num_after < 0) ? -1 : 0;
} }
static int svc_type(void *user, char *arg, rdline_t *rd, int flags) static int svc_type(void *user, char *arg, rdline_t *rd)
{ {
service_t *svc = user; service_t *svc = user;
int count = try_pack_argv(arg, rd); int count = try_pack_argv(arg, rd);
(void)flags;
if (count < 1) if (count < 1)
return -1; return -1;
@ -199,11 +184,10 @@ fail_limit:
return -1; return -1;
} }
static int svc_target(void *user, char *arg, rdline_t *rd, int flags) static int svc_target(void *user, char *arg, rdline_t *rd)
{ {
service_t *svc = user; service_t *svc = user;
int target; int target;
(void)flags;
if (try_unescape(arg, rd)) if (try_unescape(arg, rd))
return -1; return -1;
@ -230,7 +214,7 @@ static const cfg_param_t svc_params[] = {
{ "after", 0, svc_after }, { "after", 0, svc_after },
}; };
service_t *rdsvc(int dirfd, const char *filename, int flags) service_t *rdsvc(int dirfd, const char *filename)
{ {
const char *arg, *args[1]; const char *arg, *args[1];
service_t *svc = NULL; service_t *svc = NULL;
@ -254,17 +238,17 @@ service_t *rdsvc(int dirfd, const char *filename, int flags)
if (svc == NULL) if (svc == NULL)
goto fail_oom; goto fail_oom;
if (!(flags & RDSVC_NO_FNAME)) { svc->fname = strdup(filename);
svc->fname = strdup(filename); if (svc->fname == NULL)
if (svc->fname == NULL) goto fail_oom;
goto fail_oom;
}
memcpy(svc->name, filename, nlen); memcpy(svc->name, filename, nlen);
svc->id = -1; svc->id = -1;
if (rdcfg(svc, &rd, svc_params, ARRAY_SIZE(svc_params), flags)) if (rdcfg(svc, &rd, svc_params,
sizeof(svc_params) / sizeof(svc_params[0]))) {
goto fail; goto fail;
}
out: out:
rdline_cleanup(&rd); rdline_cleanup(&rd);

View file

@ -23,7 +23,7 @@ int svc_type_from_string(const char *type)
{ {
size_t i; size_t i;
for (i = 0; i < ARRAY_SIZE(type_map); ++i) { for (i = 0; i < sizeof(type_map) / sizeof(type_map[0]); ++i) {
if (strcmp(type_map[i], type) == 0) if (strcmp(type_map[i], type) == 0)
return i; return i;
} }
@ -40,7 +40,7 @@ int svc_target_from_string(const char *target)
{ {
size_t i; size_t i;
for (i = 0; i < ARRAY_SIZE(target_map); ++i) { for (i = 0; i < sizeof(target_map) / sizeof(target_map[0]); ++i) {
if (strcmp(target_map[i], target) == 0) if (strcmp(target_map[i], target) == 0)
return i; return i;
} }

View file

@ -11,7 +11,7 @@
#include "service.h" #include "service.h"
int svcscan(const char *directory, service_list_t *list, int flags) int svcscan(const char *directory, service_list_t *list)
{ {
int i, dfd, type, ret = 0; int i, dfd, type, ret = 0;
struct dirent *ent; struct dirent *ent;
@ -66,7 +66,7 @@ int svcscan(const char *directory, service_list_t *list, int flags)
if (type != S_IFREG && type != S_IFLNK) if (type != S_IFREG && type != S_IFLNK)
continue; continue;
svc = rdsvc(dfd, ent->d_name, flags); svc = rdsvc(dfd, ent->d_name);
if (svc == NULL) { if (svc == NULL) {
ret = -1; ret = -1;
continue; continue;

View file

@ -47,8 +47,7 @@ static int splitkv(rdline_t *rd, char **k, char **v)
return 0; return 0;
} }
int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count, int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count)
int flags)
{ {
const cfg_param_t *p; const cfg_param_t *p;
char *key, *value; char *key, *value;
@ -67,7 +66,7 @@ int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count,
; ;
if (*value != '\0') { if (*value != '\0') {
ret = p->handle(cfgobj, value, rd, flags); ret = p->handle(cfgobj, value, rd);
if (ret) if (ret)
return -1; return -1;
} }
@ -75,7 +74,7 @@ int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count,
while ((ret = rdline(rd)) == 0) { while ((ret = rdline(rd)) == 0) {
if (strcmp(rd->line, "}") == 0) if (strcmp(rd->line, "}") == 0)
break; break;
if (p->handle(cfgobj, rd->line, rd, flags)) if (p->handle(cfgobj, rd->line, rd))
return -1; return -1;
} }
@ -83,7 +82,7 @@ int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count,
return -1; return -1;
if (ret > 0) if (ret > 0)
goto fail_bra; goto fail_bra;
} else if (p->handle(cfgobj, value, rd, flags)) { } else if (p->handle(cfgobj, value, rd)) {
return -1; return -1;
} }
} }

View file

@ -8,7 +8,6 @@
#include <fcntl.h> #include <fcntl.h>
#include "libcfg.h" #include "libcfg.h"
#include "util.h"
int rdline_init(rdline_t *t, int dirfd, const char *filename, int rdline_init(rdline_t *t, int dirfd, const char *filename,
int argc, const char *const *argv) int argc, const char *const *argv)

View file

@ -1,51 +0,0 @@
/* SPDX-License-Identifier: ISC */
#include "service.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
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);
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;
}
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);
}