sm

sysmgr implemented in C
git clone git://git.ckyln.com/sm
Log | Files | Refs | README | LICENSE

commit 1c8258c9fcacd27b958fb42c3f4df7e88864d8a8
parent fcfc94b29c3b6ea367a5dca19aefe7904fbf296b
Author: Cem Keylan <cem@ckyln.com>
Date:   Fri,  2 Oct 2020 21:19:51 +0300

update

Diffstat:
A.gitignore | 8++++++++
MMakefile | 23++++++++++++++++-------
MREADME | 11++++++++---
Aconfig.def.h | 3+++
Aconfig.mk | 8++++++++
Mlibutil/env.c | 10++++++----
Alibutil/mkdirp.c | 44++++++++++++++++++++++++++++++++++++++++++++
Mlibutil/proc.c | 3---
Mlibutil/service.c | 1+
Alibutil/strlcpy.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arunsyssv.c | 39+++++++++++++++++++++++++++++++++++++++
Msysmgr.c | 42+++++++++++++++++++++++++++++++++---------
Mutil.h | 26++++++++++++++++++--------
13 files changed, 243 insertions(+), 34 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,7 @@ +# C Objects/binaries +*.a +*.o +config.h +sysmgr +runsyssv +svctl+ \ No newline at end of file diff --git a/Makefile b/Makefile @@ -1,10 +1,8 @@ +include config.mk + .SUFFIXES: .SUFFIXES: .o .c -CC = cc -AR = ar -RANLIB = ranlib - HDR = \ util.h @@ -12,18 +10,24 @@ LIBUTILSRC = \ libutil/enprintf.c \ libutil/env.c \ libutil/io.c \ + libutil/mkdirp.c \ libutil/proc.c \ libutil/service.c \ + libutil/strlcpy.c \ libutil/strtonum.c \ + BIN = \ - sysmgr + sysmgr \ + runsyssv + +SRC = ${BIN:=.c} +BINOBJ = ${SRC:.c=.o} LIBUTILOBJ = ${LIBUTILSRC:.c=.o} LIBUTIL = libutil.a -SRC = ${BIN:=.c} -OBJ = ${SRC:.c=.o} ${LIBUTILOBJ} +OBJ = ${BINOBJ} ${LIBUTILOBJ} all: ${BIN} @@ -31,6 +35,8 @@ ${BIN}: ${LIBUTIL} ${OBJ}: ${HDR} +${BINOBJ}: config.h + ${LIBUTIL}: ${LIBUTILOBJ} ${AR} rc $@ $? ${RANLIB} $@ @@ -41,6 +47,9 @@ ${LIBUTIL}: ${LIBUTILOBJ} .c.o: ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ -c $< +config.h: + cp config.def.h $@ + clean: rm -f ${BIN} ${OBJ} ${LIBUTIL} diff --git a/README b/README @@ -1,2 +1,7 @@ -sysmgr in C ------------- \ No newline at end of file +sysmgr +------ + +sysmgr implemented in C. Doesn't work at the moment. Most of the stuff are tests +to make sure functions are running correctly + +POSIX shell / C hybrid here: https://git.ckyln.com/sysmgr+ \ No newline at end of file diff --git a/config.def.h b/config.def.h @@ -0,0 +1,3 @@ +/* See LICENSE for copyright details */ +static char *rundir_default = "/run/sysmgr" ; +static char *sysdir_default = "/var/sysmgr" ; diff --git a/config.mk b/config.mk @@ -0,0 +1,8 @@ +CC = cc +AR = ar +RANLIB = ranlib + +CPPFLAGS = -D_XOPEN_SOURCE=700 -D_GNU_SOURCE +CFLAGS = -std=c99 -Wpedantic -Wall -Wextra +LDFLAGS = -static + diff --git a/libutil/env.c b/libutil/env.c @@ -1,3 +1,4 @@ +#include <stdio.h> #include <stdlib.h> #include "../util.h" @@ -5,8 +6,9 @@ char* getenv_fallback(char *name, char *fallback) { - char *value = getenv(name); - if (!value) - value = fallback; - return value; + if (setenv(name, fallback, 0) == -1) { + perror(name); + return NULL; + } + return getenv(name); } diff --git a/libutil/mkdirp.c b/libutil/mkdirp.c @@ -0,0 +1,44 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/stat.h> + +#include <errno.h> +#include <limits.h> + +#include "../util.h" + +int +mkdirp(const char *path) +{ + mode_t mode, pmode, mask; + mask = umask(0); + mode = 0777 & ~mask; + pmode = 0777 & ( ~mask | 0300); + + char tmp[PATH_MAX], *p; + struct stat st; + + if (stat(path, &st) == 0) { + if (S_ISDIR(st.st_mode)) + return 0; + errno = ENOTDIR; + weprintf("%s:", path); + return -1; + } + + estrlcpy(tmp, path, sizeof(tmp)); + for (p = tmp + (tmp[0] == '/'); *p; p++) { + if (*p != '/') + continue; + *p = '\0'; + if (mkdir(tmp, pmode) < 0 && errno != EEXIST) { + weprintf("mkdir %s:", tmp); + return -1; + } + *p = '/'; + } + if (mkdir(tmp, mode) < 0 && errno != EEXIST) { + weprintf("mkdir %s:", tmp); + return -1; + } + return 0; +} diff --git a/libutil/proc.c b/libutil/proc.c @@ -27,9 +27,6 @@ getsvpid(service *sv) int writesvpid(char *file, pid_t pid) { - if (access(file, W_OK) == -1) - return -1; - FILE *pidfile; pidfile = fopen(file, "w"); diff --git a/libutil/service.c b/libutil/service.c @@ -10,6 +10,7 @@ sv_init(service *sv, char *sv_name) sprintf(sv->rundir, "%s", getenv_fallback("RUNDIR", "/run/sysmgr")); sprintf(sv->pidfile, "%s/%s/pid", sv->rundir, sv->name); sprintf(sv->svfile, "%s/%s", sv->sysdir, sv_name); + sprintf(sv->svrundir, "%s/%s", sv->rundir, sv_name); return sv; } diff --git a/libutil/strlcpy.c b/libutil/strlcpy.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <string.h> +#include <sys/types.h> + +#include "../util.h" + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + return(s - src - 1); /* count does not include NUL */ +} + +size_t +estrlcpy(char *dst, const char *src, size_t siz) +{ + size_t ret; + + if ((ret = strlcpy(dst, src, siz)) >= siz) + eprintf("strlcpy: input string too long\n"); + + return ret; +} diff --git a/runsyssv.c b/runsyssv.c @@ -0,0 +1,39 @@ +#include <sys/types.h> +#include <sys/stat.h> + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> + +#include "util.h" +#include "config.h" +static char *argv0; + +void +usage(int exitnum) +{ + printf("usage: %s [svfile]\n", argv0); + exit(exitnum); +} + +int +main(int argc, char *argv[]) +{ + argv0 = argv[0]; + char *sysdir, *rundir; + sysdir = getenv_fallback("SYSDIR", sysdir_default); + rundir = getenv_fallback("RUNDIR", rundir_default); + + if (argc == 2) { + if (strncmp(argv[1], "-", 1) == 0) + usage(0); + } else + usage(1); + + struct service sv; + sv_init(&sv, argv[1]); + mkdirp(sv.svrundir); + +} diff --git a/sysmgr.c b/sysmgr.c @@ -1,37 +1,61 @@ #include <sys/types.h> +#include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> -#include <libgen.h> +#include <dirent.h> +#include <string.h> #include "util.h" +#include "config.h" static char *argv0; void usage(void) { printf("usage: %s\n\nSee sysmgr(8) for detailed information.\n\nVersion: %s\n", argv0, VERSION); - exit(0); + exit(1); } int main(int argc, char *argv[]) { - argv0 = basename(argv[0]); + argv0 = argv[0]; + char *sysdir, *rundir; + char sysmgr_pidfile[PATH_MAX]; if (argc > 1) usage(); - if (setenv("SYSDIR", "/var/sysmgr", 0) == -1) - die("setenv:"); - if (setenv("RUNDIR", "/run/sysmgr", 0) == -1) - die("setenv:"); + sysdir = getenv_fallback("SYSDIR", sysdir_default); + rundir = getenv_fallback("RUNDIR", rundir_default); + snprintf(sysmgr_pidfile, PATH_MAX, "%s/pid", rundir); - char *rundir = getenv("RUNDIR"); - char *sysdir = getenv("SYSDIR"); + mkdirp(rundir); pid_t pid = getpid(); + printf("RUNDIR: %s\nSYSDIR: %s\nselfpid: %d\n", rundir, sysdir, pid); + if (writesvpid(sysmgr_pidfile, pid) != 0) + die("%s:", sysmgr_pidfile); + + /* Go to the service directory and get all the service entries. */ + DIR *dir; + struct dirent *ent; + if ((dir = opendir(sysdir)) == NULL) + die("%s:", sysdir); + while ((ent = readdir(dir)) != NULL) { + if (strncmp(ent->d_name, ".", 1) == 0) + continue; + printf("%s\n", ent->d_name); + + struct service sv; + sv_init(&sv, ent->d_name); + + } + closedir(dir); + + return 0; } diff --git a/util.h b/util.h @@ -1,5 +1,7 @@ /* See LICENSE for copyright information */ +#ifndef _UTIL_H +#define _UTIL_H #ifndef _LIMITS_H #include <limits.h> #endif @@ -13,16 +15,15 @@ #endif typedef struct service { - char name[NAME_MAX]; - char sysdir[PATH_MAX]; - char rundir[PATH_MAX]; - char pidfile[PATH_MAX]; - char svfile[PATH_MAX]; + char name[NAME_MAX]; + char sysdir[PATH_MAX]; + char rundir[PATH_MAX]; + char pidfile[PATH_MAX]; + char svfile[PATH_MAX]; + char svrundir[PATH_MAX]; } service; -/* - * Get information about the service. - */ +/* service.c */ service *sv_init(service *sv, char *sv_name); /* proc.c */ @@ -47,3 +48,12 @@ void weprintf(const char *, ...); long long strtonum(const char *, long long, long long, const char **); long long enstrtonum(int, const char *, long long, long long); long long estrtonum(const char *, long long, long long); + +/* mkdirp.c */ +int mkdirp(const char *path); + +/* estrlcpy.c */ +size_t strlcpy(char *, const char *, size_t); +size_t estrlcpy(char *, const char *, size_t); + +#endif