#include "service.h" #include "log.h" #include #include #include #include #include #include #include #include #include #include #include #include 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_HASHTABLE)) { return -1; } const fx_value *service_v = fx_hashtable_get(in, &FX_CSTR("service")); if (!service_v || !fx_value_is_type(service_v, FX_TYPE_HASHTABLE)) { return -1; } fx_hashtable *in_service = NULL; fx_value_get_object(service_v, &in_service); const fx_value *unit_v = fx_hashtable_get(in, &FX_CSTR("unit")); if (!unit_v || !fx_value_is_type(unit_v, FX_TYPE_HASHTABLE)) { return -1; } fx_hashtable *in_unit = NULL; fx_value_get_object(unit_v, &in_unit); const fx_value *name_v = fx_hashtable_get(in_unit, &FX_CSTR("name")); if (!name_v || !fx_value_is_type(name_v, FX_TYPE_STRING)) { return -1; } fx_string *name = NULL; fx_value_get_object(name_v, &name); const fx_value *description_v = fx_hashtable_get(in_unit, &FX_CSTR("description")); if (!description_v || !fx_value_is_type(description_v, FX_TYPE_STRING)) { return -1; } fx_string *description = NULL; fx_value_get_object(description_v, &description); const fx_value *exec_v = fx_hashtable_get(in_service, &FX_CSTR("exec")); if (!exec_v || !fx_value_is_type(exec_v, FX_TYPE_STRING)) { return -1; } fx_string *exec = NULL; fx_value_get_object(exec_v, &exec); const fx_value *roles_v = fx_hashtable_get(in_service, &FX_CSTR("roles")); if (roles_v && !fx_value_is_type(roles_v, FX_TYPE_ARRAY)) { return -1; } fx_array *roles = NULL; fx_value_get_object(roles_v, &roles); int ret = 0; const fx_iterator *it = fx_iterator_begin(roles); fx_foreach(v, it) { if (!fx_value_is_type(v, 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(role, it) { const char *role_cstr = NULL; fx_value_get_cstr(role, &role_cstr); 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_value 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 (!fx_value_is_type(&data, FX_TYPE_HASHTABLE)) { fx_value_unset(&data); free(rl); errno = EFTYPE; return -1; } if (parse_service_data(data.v_object, rl) != 0) { free(rl); errno = EFTYPE; return -1; } fx_stream_unref(in); fx_value_unset(&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; }