Commit 0a6819ac authored by bbguimaraes's avatar bbguimaraes
Browse files

Initial commit

parents
This diff is collapsed.
custos
======
Quis custodiet?
Build
-----
```console
$ premake5 gmake2
$ make
```
workspace "custos"
configurations { "debug", "release" }
kind "ConsoleApp"
language "C"
cdialect "C11"
defines { "_POSIX_C_SOURCE=200112L" }
warnings "Extra"
filter "configurations:debug"
defines { "DEBUG" }
symbols "On"
filter "configurations:release"
defines { "NDEBUG" }
optimize "On"
filter "toolset:clang or gcc"
enablewarnings { "pedantic", "conversion" }
filter { "toolset:clang or gcc", "tags:test" }
buildoptions { "-fsanitize=address,undefined", "-fstack-protector" }
linkoptions { "-fsanitize=address,undefined", "-fstack-protector" }
include "src"
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include "test.h"
#include "utils.h"
#define DATE_FMT "%Y-%m-%dT%H:%M:%S"
#define DATE_SIZE sizeof("YYYY-MM-DDTHH:MM:SS")
struct config {
struct timespec t;
};
struct module {
const char *name;
void *data;
void *(*init)(void);
bool (*destroy)(void*);
bool (*update)(void*);
};
static sig_atomic_t interrupted = 0;
static struct module modules[] = {{
.name = "test",
.init = test_init,
.destroy = test_destroy,
.update = test_update,
}};
static void sigint_handler(int s) {
(void)s;
interrupted = 1;
}
static bool print_header(void) {
time_t t = {0};
if(time(&t) == -1)
return LOG_ERRNO("time"), false;
struct tm tm = {0};
if(!localtime_r(&t, &tm))
return LOG_ERRNO("localtime_r"), false;
char str[DATE_SIZE] = {0};
if(strftime(str, sizeof(str), DATE_FMT, &tm) != sizeof(str) - 1)
return LOG_ERR("strftime failed\n"), false;
printf("\n%s\n\n", str);
return true;
}
static bool sleep(struct config *config) {
struct timespec *t = &config->t;
++t->tv_sec;
while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, t, NULL) == -1)
if(errno != EINTR)
return LOG_ERRNO("clock_nanosleep"), false;
return true;
}
static bool init_config(struct config *c) {
struct sigaction sa = {.sa_handler = sigint_handler};
sigemptyset(&sa.sa_mask);
if(sigaction(SIGINT, &sa, NULL) == -1)
return LOG_ERRNO("signaction"), false;
if(clock_gettime(CLOCK_MONOTONIC, &c->t) == -1)
return LOG_ERRNO("clock_gettime"), false;
return true;
}
static bool init_modules(void) {
for(size_t i = 0; i != ARRAY_SIZE(modules); ++i) {
struct module *const m = modules + i;
if(!(m->data = m->init())) {
LOG_ERR("failed to initialize module \"%s\"\n", m->name);
return false;
}
}
return true;
}
static bool destroy_modules(void) {
bool ret = true;
for(size_t i = 0; i != ARRAY_SIZE(modules); ++i) {
struct module *const m = modules + i;
if(!m->destroy(m->data)) {
LOG_ERR("failed to destroy module \"%s\"\n", m->name);
ret = false;
}
}
return ret;
}
static bool update_modules(void) {
for(size_t i = 0; i != ARRAY_SIZE(modules); ++i) {
struct module *const m = modules + i;
if(!m->update(m->data)) {
LOG_ERR("failed to update module \"%s\"\n", m->name);
return false;
}
}
return true;
}
int main(void) {
struct config config = {0};
if(!(init_config(&config) && init_modules()))
return 1;
while(!interrupted)
if(!(print_header() && update_modules() && sleep(&config)))
goto err;
return !destroy_modules();
err:
destroy_modules();
return 1;
}
project "custos"
files {
"main.c",
"test.h",
"test.c",
"utils.c",
"utils.h",
}
configuration "debug"
#include "test.h"
#include <errno.h>
#include <stdio.h>
void *test_init(void) {
puts(__func__);
return &errno;
}
bool test_destroy(void *d) {
(void)d;
puts(__func__);
return true;
}
bool test_update(void *d) {
(void)d;
puts(__func__);
return true;
}
#ifndef CUSTOS_TEST_H
#define CUSTOS_TEST_H
#include <stdbool.h>
void *test_init(void);
bool test_destroy(void *d);
bool test_update(void *d);
#endif
#include "utils.h"
#ifndef CUSTOS_UTILS_H
#define CUSTOS_UTILS_H
#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
#define LOG_ERR(...) log_err(__func__, __LINE__, __VA_ARGS__)
#define LOG_ERRNO(...) log_errno(__func__, __LINE__, __VA_ARGS__)
static inline void log_err(
const char *restrict fn, int line, const char *restrict fmt, ...);
static inline void log_errno(
const char *restrict fn, int line, const char *restrict fmt, ...);
static inline void vlog_err(
const char *restrict fn, int line, const char *restrict fmt, va_list args);
static inline void vlog_errno(
const char *restrict fn, int line, const char *restrict fmt, va_list args);
inline void log_err(
const char *restrict fn, int line, const char *restrict fmt, ...)
{
va_list args;
va_start(args, fmt);
vlog_err(fn, line, fmt, args);
va_end(args);
}
inline void log_errno(
const char *restrict fn, int line, const char *restrict fmt, ...)
{
va_list args;
va_start(args, fmt);
vlog_errno(fn, line, fmt, args);
va_end(args);
}
inline void vlog_err(
const char *restrict fn, int line, const char *restrict fmt, va_list args)
{
fprintf(stderr, "%s:%d: ", fn, line);
vfprintf(stderr, fmt, args);
}
inline void vlog_errno(
const char *restrict fn, int line, const char *restrict fmt, va_list args)
{
vlog_err(fn, line, fmt, args);
fprintf(stderr, ": %s\n", strerror(errno));
}
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment