sm

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

commit fcfc94b29c3b6ea367a5dca19aefe7904fbf296b
Author: Cem Keylan <cem@ckyln.com>
Date:   Thu, 17 Sep 2020 11:23:05 +0300

initial commit

Diffstat:
AMakefile | 47+++++++++++++++++++++++++++++++++++++++++++++++
AREADME | 3+++
Alibutil/enprintf.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibutil/env.c | 12++++++++++++
Alibutil/io.c | 35+++++++++++++++++++++++++++++++++++
Alibutil/proc.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibutil/service.c | 15+++++++++++++++
Alibutil/strtonum.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asysmgr.c | 37+++++++++++++++++++++++++++++++++++++
Autil.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 414 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,47 @@ +.SUFFIXES: +.SUFFIXES: .o .c + +CC = cc +AR = ar +RANLIB = ranlib + +HDR = \ + util.h + +LIBUTILSRC = \ + libutil/enprintf.c \ + libutil/env.c \ + libutil/io.c \ + libutil/proc.c \ + libutil/service.c \ + libutil/strtonum.c \ + +BIN = \ + sysmgr + +LIBUTILOBJ = ${LIBUTILSRC:.c=.o} +LIBUTIL = libutil.a + +SRC = ${BIN:=.c} +OBJ = ${SRC:.c=.o} ${LIBUTILOBJ} + +all: ${BIN} + +${BIN}: ${LIBUTIL} + +${OBJ}: ${HDR} + +${LIBUTIL}: ${LIBUTILOBJ} + ${AR} rc $@ $? + ${RANLIB} $@ + +.o: + ${CC} ${LDFLAGS} -o $@ $< ${LIBUTIL} ${LIBS} + +.c.o: + ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ -c $< + +clean: + rm -f ${BIN} ${OBJ} ${LIBUTIL} + +.PHONY: all clean diff --git a/README b/README @@ -0,0 +1,2 @@ +sysmgr in C +-----------+ \ No newline at end of file diff --git a/libutil/enprintf.c b/libutil/enprintf.c @@ -0,0 +1,64 @@ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../util.h" + +char *argv0; + +static void venprintf(int, const char *, va_list); + +void +eprintf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + venprintf(1, fmt, ap); + va_end(ap); +} + +void +enprintf(int status, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + venprintf(status, fmt, ap); + va_end(ap); +} + +void +venprintf(int status, const char *fmt, va_list ap) +{ + if (strncmp(fmt, "usage", strlen("usage"))) + fprintf(stderr, "%s: ", argv0); + + vfprintf(stderr, fmt, ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } + + exit(status); +} + +void +weprintf(const char *fmt, ...) +{ + va_list ap; + + if (strncmp(fmt, "usage", strlen("usage"))) + fprintf(stderr, "%s: ", argv0); + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } +} diff --git a/libutil/env.c b/libutil/env.c @@ -0,0 +1,12 @@ +#include <stdlib.h> + +#include "../util.h" + +char* +getenv_fallback(char *name, char *fallback) +{ + char *value = getenv(name); + if (!value) + value = fallback; + return value; +} diff --git a/libutil/io.c b/libutil/io.c @@ -0,0 +1,35 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "../util.h" + +void +out(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fputc('\n', stderr); +} + +void +die(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + + if (msg[0] && msg[strlen(msg)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + exit(1); +} diff --git a/libutil/proc.c b/libutil/proc.c @@ -0,0 +1,67 @@ +#include <unistd.h> +#include <stdio.h> +#include <signal.h> +#include <errno.h> + +#include "../util.h" + +pid_t +getsvpid(service *sv) +{ + pid_t pid; + + if (access(sv->pidfile, R_OK) == -1) + return -1; + FILE *pidfile; + + pidfile = fopen(sv->pidfile, "r"); + if (pidfile == NULL) + return -2; + + fscanf(pidfile, "%d", &pid); + fclose(pidfile); + + return pid; +} + +int +writesvpid(char *file, pid_t pid) +{ + if (access(file, W_OK) == -1) + return -1; + + FILE *pidfile; + + pidfile = fopen(file, "w"); + if (pidfile == NULL) + /* perror(file); */ + return -2; + + fprintf(pidfile, "%d\n", pid); + fclose(pidfile); + + return 0; +} + +int +checkprocess(int pid) +{ + if (kill(pid, 0) == 0) return 0; + else { + switch (errno) { + case 1: + /* EPERM is only produced if the process exists, but the + * user running the program doesn't have the permissions + * to kill the process. We can safely assume that the + * process exists in this case and return 0. + */ + return 0; + break; + default: + perror("kill"); + break; + } + + return 1; + } +} diff --git a/libutil/service.c b/libutil/service.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +#include "../util.h" + +service* +sv_init(service *sv, char *sv_name) +{ + sprintf(sv->name, "%s", sv_name); + sprintf(sv->sysdir, "%s", getenv_fallback("SYSDIR", "/var/sysmgr")); + 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); + + return sv; +} diff --git a/libutil/strtonum.c b/libutil/strtonum.c @@ -0,0 +1,85 @@ +/* $OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $ */ + +/* + * Copyright (c) 2004 Ted Unangst and Todd Miller + * All rights reserved. + * + * 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 <errno.h> +#include <limits.h> +#include <stdlib.h> + +#include "../util.h" + +#define INVALID 1 +#define TOOSMALL 2 +#define TOOLARGE 3 + +long long +strtonum(const char *numstr, long long minval, long long maxval, + const char **errstrp) +{ + long long ll = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + ll = strtoll(numstr, &ep, 10); + if (numstr == ep || *ep != '\0') + error = INVALID; + else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + error = TOOSMALL; + else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + ll = 0; + + return (ll); +} + +long long +enstrtonum(int status, const char *numstr, long long minval, long long maxval) +{ + const char *errstr; + long long ll; + + ll = strtonum(numstr, minval, maxval, &errstr); + if (errstr) + enprintf(status, "strtonum %s: %s\n", numstr, errstr); + return ll; +} + +long long +estrtonum(const char *numstr, long long minval, long long maxval) +{ + return enstrtonum(1, numstr, minval, maxval); +} diff --git a/sysmgr.c b/sysmgr.c @@ -0,0 +1,37 @@ +#include <sys/types.h> + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <libgen.h> + +#include "util.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); +} + + +int main(int argc, char *argv[]) +{ + argv0 = basename(argv[0]); + + if (argc > 1) + usage(); + + if (setenv("SYSDIR", "/var/sysmgr", 0) == -1) + die("setenv:"); + if (setenv("RUNDIR", "/run/sysmgr", 0) == -1) + die("setenv:"); + + char *rundir = getenv("RUNDIR"); + char *sysdir = getenv("SYSDIR"); + + pid_t pid = getpid(); + +} diff --git a/util.h b/util.h @@ -0,0 +1,49 @@ +/* See LICENSE for copyright information */ + +#ifndef _LIMITS_H +#include <limits.h> +#endif + +#ifndef _TYPES_H +#include <sys/types.h> +#endif + +#ifndef VERSION +#define VERSION "git" +#endif + +typedef struct service { + char name[NAME_MAX]; + char sysdir[PATH_MAX]; + char rundir[PATH_MAX]; + char pidfile[PATH_MAX]; + char svfile[PATH_MAX]; +} service; + +/* + * Get information about the service. + */ +service *sv_init(service *sv, char *sv_name); + +/* proc.c */ +int getsvpid(service *sv); +int checkprocess(int pid); +int writesvpid(char *file, pid_t pid); + +/* env.c */ +char *getenv_fallback(char *name, char *fallback); +void *setenv_fallback(char *name, char *fallback); + +/* io.c */ +void die(const char *msg, ...); + + +/* enprintf.c */ +void enprintf(int, const char *, ...); +void eprintf(const char *, ...); +void weprintf(const char *, ...); + +/* strtonum.c */ +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);