156 lines
3.0 KiB
C
156 lines
3.0 KiB
C
#include "service.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include <errno.h>
|
|
#include <fx/core/stringstream.h>
|
|
#include <fx/ds/array.h>
|
|
#include <fx/ds/dict.h>
|
|
#include <fx/serial.h>
|
|
#include <launch.h>
|
|
#include <mango/log.h>
|
|
#include <rosetta/bootstrap.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static struct queue services = QUEUE_INIT;
|
|
|
|
struct queue *global_services(void)
|
|
{
|
|
return &services;
|
|
}
|
|
|
|
static int parse_service_data(fx_object *in, struct service *out)
|
|
{
|
|
if (!fx_object_is_type(in, FX_TYPE_DICT)) {
|
|
return -1;
|
|
}
|
|
|
|
fx_dict *in_service = fx_dict_at(in, "service");
|
|
if (!in_service || !fx_object_is_type(in_service, FX_TYPE_DICT)) {
|
|
return -1;
|
|
}
|
|
|
|
fx_dict *in_unit = fx_dict_at(in, "unit");
|
|
if (!in_unit || !fx_object_is_type(in_unit, FX_TYPE_DICT)) {
|
|
return -1;
|
|
}
|
|
|
|
fx_string *name = fx_dict_at(in_unit, "name");
|
|
if (!name || !fx_object_is_type(name, FX_TYPE_STRING)) {
|
|
return -1;
|
|
}
|
|
|
|
fx_string *description = fx_dict_at(in_unit, "description");
|
|
if (!description || !fx_object_is_type(description, FX_TYPE_STRING)) {
|
|
return -1;
|
|
}
|
|
|
|
fx_string *exec = fx_dict_at(in_service, "exec");
|
|
if (!description || !fx_object_is_type(description, FX_TYPE_STRING)) {
|
|
return -1;
|
|
}
|
|
|
|
fx_array *roles = fx_dict_at(in_service, "roles");
|
|
if (roles && !fx_object_is_type(roles, FX_TYPE_ARRAY)) {
|
|
return -1;
|
|
}
|
|
|
|
int ret = 0;
|
|
fx_iterator *it = fx_iterator_begin(roles);
|
|
fx_foreach_ptr(fx_string, role, it)
|
|
{
|
|
if (!fx_object_is_type(role, FX_TYPE_STRING)) {
|
|
ret = -1;
|
|
break;
|
|
}
|
|
}
|
|
fx_iterator_unref(it);
|
|
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
it = fx_iterator_begin(roles);
|
|
size_t i = 0;
|
|
fx_foreach_ptr(fx_string, role, it)
|
|
{
|
|
const char *role_cstr = fx_string_get_cstr(role);
|
|
if (!strcmp(role_cstr, "NamespaceProvider")) {
|
|
out->s_roles |= SVC_ROLE_NAMESPACE_PROVIDER;
|
|
}
|
|
}
|
|
fx_iterator_unref(it);
|
|
|
|
out->s_name = fx_string_steal(name);
|
|
out->s_description = fx_string_steal(description);
|
|
out->s_exec = fx_string_steal(exec);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int service_load(const char *path, struct service **out)
|
|
{
|
|
struct service *rl = malloc(sizeof *rl);
|
|
if (!rl) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
|
|
FILE *fp = fopen(path, "r");
|
|
if (!fp) {
|
|
free(rl);
|
|
return -1;
|
|
}
|
|
|
|
fx_stream *in = fx_stream_open_fp(fp);
|
|
fx_serial_ctx *ctx = fx_toml_serial_ctx_create();
|
|
fx_object *data;
|
|
fx_result result = fx_serial_ctx_deserialise(ctx, in, &data, 0);
|
|
if (fx_result_is_error(result)) {
|
|
fx_throw(result);
|
|
free(rl);
|
|
errno = EFTYPE;
|
|
return -1;
|
|
}
|
|
|
|
if (parse_service_data(data, rl) != 0) {
|
|
free(rl);
|
|
errno = EFTYPE;
|
|
return -1;
|
|
}
|
|
|
|
fx_stream_unref(in);
|
|
fx_object_unref(data);
|
|
|
|
fclose(fp);
|
|
|
|
*out = rl;
|
|
return 0;
|
|
}
|
|
|
|
struct service *service_find(const char *name)
|
|
{
|
|
struct queue_entry *cur = queue_first(&services);
|
|
while (cur) {
|
|
struct service *s
|
|
= QUEUE_CONTAINER(struct service, s_entry, cur);
|
|
if (!strcmp(s->s_name, name)) {
|
|
return s;
|
|
}
|
|
|
|
cur = queue_next(cur);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int service_start(struct service *svc)
|
|
{
|
|
log("Starting %s...", svc->s_description);
|
|
|
|
log_ok("Started %s.", svc->s_description);
|
|
return 0;
|
|
}
|