diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am index 6606c972..af19cdcf 100644 --- a/src/confd/src/Makefile.am +++ b/src/confd/src/Makefile.am @@ -6,4 +6,4 @@ plugin_LTLIBRARIES = confd-plugin.la confd_plugin_la_CFLAGS = $(augeas_CFLAGS) $(sysrepo_CFLAGS) $(CFLAGS) confd_plugin_la_LIBADD = $(augeas_LIBS) $(sysrepo_LIBS) $(CFLAGS) confd_plugin_la_LDFLAGS = -module -avoid-version -shared -confd_plugin_la_SOURCES = ietf-system.c +confd_plugin_la_SOURCES = core.c core.h run.c ietf-system.c diff --git a/src/confd/src/core.c b/src/confd/src/core.c new file mode 100644 index 00000000..1727cace --- /dev/null +++ b/src/confd/src/core.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include "core.h" + +static struct confd confd; + +int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) +{ + int rc = SR_ERR_SYS; + + openlog("confd", LOG_USER, 0); + + confd.session = session; + confd.conn = sr_session_get_connection(session); + confd.sub = NULL; + + if (!confd.conn) + goto err; + + confd.aug = aug_init(NULL, "", 0); + if (!confd.aug) + goto err; + + *priv = (void *)&confd; + + if (ietf_system_init(&confd)) + goto err; + + return SR_ERR_OK; +err: + ERROR("init failed: %s", sr_strerror(rc)); + sr_unsubscribe(confd.sub); + + return rc; +} + +void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *priv) +{ + sr_unsubscribe((sr_subscription_ctx_t *)priv); + closelog(); +} diff --git a/src/confd/src/core.h b/src/confd/src/core.h new file mode 100644 index 00000000..9b708a0f --- /dev/null +++ b/src/confd/src/core.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +#ifndef CONFD_CORE_H_ +#define CONFD_CORE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +#define DEBUG(frmt, ...) +//#define DEBUG(frmt, ...) syslog(LOG_DEBUG, "%s: "frmt, __func__, ##__VA_ARGS__) +#define ERROR(frmt, ...) syslog(LOG_ERR, "%s: " frmt, __func__, ##__VA_ARGS__) +#define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: " frmt ": %s", __func__, ##__VA_ARGS__, strerror(errno)) + +#define REGISTER_CHANGE(s,x,c,a,u) \ + if (rc = register_change(s, x, c, a, u))\ + goto err + +#define REGISTER_RPC(s,x,c,a,u) \ + if (rc = register_rpc(s, x, c, a, u)) \ + goto err + +struct confd { + sr_session_ctx_t *session; + sr_conn_ctx_t *conn; + sr_subscription_ctx_t *sub; + + augeas *aug; +}; + +static inline int register_change(sr_session_ctx_t *session, const char *xpath, + sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub) +{ + int rc = sr_module_change_subscribe(session, "ietf-system", xpath, cb, arg, 0, + SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, sub); + if (rc) + ERROR("failed subscribing to changes of %s: %s", xpath, sr_strerror(rc)); + return rc; +} + +static inline int register_rpc(sr_session_ctx_t *session, const char *xpath, + sr_rpc_cb cb, void *arg, sr_subscription_ctx_t **sub) +{ + int rc = sr_rpc_subscribe(session, xpath, cb, arg, 0, SR_SUBSCR_DEFAULT, sub); + if (rc) + ERROR("failed subscribing to %s rpc: %s", xpath, sr_strerror(rc)); + return rc; +} + + +/* core.c */ +int run(const char *fmt, ...); + +/* ietf-syste.c */ +int ietf_system_init(struct confd *confd); + +#endif /* CONFD_CORE_H_ */ diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 183b34dc..ed0ffa55 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -1,87 +1,13 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -#include -#include -#include -#include -#include +#include "core.h" #include -#include -#include -#include -#include - -/* Linux specific */ #include -#include -#include -#include -#include - #define CLOCK_PATH_ "/ietf-system:system-state/clock" #define PLATFORM_PATH_ "/ietf-system:system-state/platform" -#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) - -#define DEBUG(frmt, ...) -//#define DEBUG(frmt, ...) syslog(LOG_DEBUG, "%s: "frmt, __func__, ##__VA_ARGS__) -#define ERROR(frmt, ...) syslog(LOG_ERR, "%s: " frmt, __func__, ##__VA_ARGS__) -#define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: " frmt ": %s", __func__, ##__VA_ARGS__, strerror(errno)) - -static augeas *aug; - - -/** - * Like system(), but takes a formatted string as argument. - * @param fmt printf style format list to command to run - * - * This system() wrapper greatly simplifies operations that usually - * consist of composing a command from parts into a dynamic buffer - * before calling it. The return value from system() is also parsed, - * checking for proper exit and signals. - * - * @returns If the command exits normally, the return code of the command - * is returned. Otherwise, if the command is signalled, the return code - * is -1 and @a errno is set to @c EINTR. - */ -static int run(const char *fmt, ...) -{ - va_list ap; - char *cmd; - int len; - int rc; - - va_start(ap, fmt); - len = vsnprintf(NULL, 0, fmt, ap); - va_end(ap); - - cmd = alloca(++len); - if (!cmd) { - errno = ENOMEM; - return -1; - } - - va_start(ap, fmt); - vsnprintf(cmd, len, fmt, ap); - va_end(ap); - - rc = system(cmd); - if (rc == -1) - return -1; - - if (WIFEXITED(rc)) { - errno = 0; - rc = WEXITSTATUS(rc); - } else if (WIFSIGNALED(rc)) { - errno = EINTR; - rc = -1; - } - - return rc; -} - /* Return seconds since boot */ static long get_uptime(void) { @@ -344,6 +270,7 @@ fail: static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { + struct confd *confd = (struct confd *)priv; const char *fn = CHRONY_NEXT; int valid = -1; sr_data_t *sdt; @@ -453,6 +380,7 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { + struct confd *confd = (struct confd *)priv; const char *host, *nm, *tmp; char **hosts, *current; int err, i, nhosts; @@ -479,18 +407,18 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha } ERROR("Got hostname %s", nm); - aug_get(aug, "etc/hostname/hostname", &tmp); + aug_get(confd->aug, "etc/hostname/hostname", &tmp); current = strdup(tmp); ERROR("Current hostname %s", current); err = sethostname(nm, strlen(nm)); - err = err ? : aug_set(aug, "etc/hostname/hostname", nm); + err = err ? : aug_set(confd->aug, "etc/hostname/hostname", nm); - nhosts = aug_match(aug, "etc/hosts/*/canonical", &hosts); + nhosts = aug_match(confd->aug, "etc/hosts/*/canonical", &hosts); for (i = 0; i < nhosts; i++) { - aug_get(aug, hosts[i], &host); + aug_get(confd->aug, hosts[i], &host); if (!strcmp(host, current)) - err = err ? : aug_set(aug, hosts[i], nm); + err = err ? : aug_set(confd->aug, hosts[i], nm); free(hosts[i]); } free(hosts); @@ -502,44 +430,15 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha } ERROR("Reload hostname-dependent services ..."); - err = err ? : aug_save(aug); + err = err ? : aug_save(confd->aug); if (sys_reload_services()) return SR_ERR_SYS; return SR_ERR_OK; } -static int register_change(sr_session_ctx_t *session, const char *xpath, - sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub) +int ietf_system_init(struct confd *confd) { - int rc = sr_module_change_subscribe(session, "ietf-system", xpath, cb, arg, 0, - SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, sub); - if (rc) - ERROR("failed subscribing to changes of %s: %s", xpath, sr_strerror(rc)); - return rc; -} - -static int register_rpc(sr_session_ctx_t *session, const char *xpath, - sr_rpc_cb cb, void *arg, sr_subscription_ctx_t **sub) -{ - int rc = sr_rpc_subscribe(session, xpath, cb, arg, 0, SR_SUBSCR_DEFAULT, sub); - if (rc) - ERROR("failed subscribing to %s rpc: %s", xpath, sr_strerror(rc)); - return rc; -} - -#define REGISTER_CHANGE(s,x,c,a,u) \ - if (rc = register_change(s, x, c, a, u))\ - goto err - -#define REGISTER_RPC(s,x,c,a,u) \ - if (rc = register_rpc(s, x, c, a, u)) \ - goto err - -int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) -{ - sr_subscription_ctx_t *sub = NULL; - sr_conn_ctx_t *conn; const char *features[] = { "ntp", "ntp-udp-port", @@ -548,50 +447,38 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) }; int rc; - aug = aug_init(NULL, "", 0); - if (!aug || - aug_load_file(aug, "/etc/hostname") || - aug_load_file(aug, "/etc/hosts")) { + if (aug_load_file(confd->aug, "/etc/hostname") || + aug_load_file(confd->aug, "/etc/hosts")) { ERROR("ietf-system: Augeas initialization failed"); goto err; } - openlog("ietf-system", LOG_USER, 0); - conn = sr_session_get_connection(session); - sr_install_module(conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features); + if (rc = sr_install_module(confd->conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features)) + goto err; - rc = sr_oper_get_subscribe(session, "ietf-system", CLOCK_PATH_, - clock_cb, NULL, SR_SUBSCR_DEFAULT, &sub); + rc = sr_oper_get_subscribe(confd->session, "ietf-system", CLOCK_PATH_, + clock_cb, NULL, SR_SUBSCR_DEFAULT, &confd->sub); if (rc != SR_ERR_OK) goto err; - rc = sr_oper_get_subscribe(session, "ietf-system", PLATFORM_PATH_, - platform_cb, NULL, SR_SUBSCR_DEFAULT, &sub); + rc = sr_oper_get_subscribe(confd->session, "ietf-system", PLATFORM_PATH_, + platform_cb, NULL, SR_SUBSCR_DEFAULT, &confd->sub); if (rc != SR_ERR_OK) goto err; - REGISTER_RPC(session, "/ietf-system:system-restart", rpc_exec, "reboot", &sub); - REGISTER_RPC(session, "/ietf-system:system-shutdown", rpc_exec, "poweroff", &sub); - REGISTER_RPC(session, "/ietf-system:set-current-datetime", rpc_set_datetime, NULL, &sub); + REGISTER_RPC(confd->session, "/ietf-system:system-restart", rpc_exec, "reboot", &confd->sub); + REGISTER_RPC(confd->session, "/ietf-system:system-shutdown", rpc_exec, "poweroff", &confd->sub); + REGISTER_RPC(confd->session, "/ietf-system:set-current-datetime", rpc_set_datetime, NULL, &confd->sub); - REGISTER_CHANGE(session, "/ietf-system:system/hostname", change_hostname, NULL, &sub); - REGISTER_CHANGE(session, "/ietf-system:system/ntp", change_ntp, NULL, &sub); + REGISTER_CHANGE(confd->session, "/ietf-system:system/hostname", change_hostname, NULL, &confd->sub); + REGISTER_CHANGE(confd->session, "/ietf-system:system/ntp", change_ntp, NULL, &confd->sub); - *(sr_subscription_ctx_t **)priv = sub; DEBUG("init ok"); return SR_ERR_OK; - err: ERROR("init failed: %s", sr_strerror(rc)); - sr_unsubscribe(sub); + sr_unsubscribe(confd->sub); return rc; } - -void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *priv) -{ - sr_unsubscribe((sr_subscription_ctx_t *)priv); - - DEBUG("cleanup ok"); -} diff --git a/src/confd/src/run.c b/src/confd/src/run.c new file mode 100644 index 00000000..1a809c68 --- /dev/null +++ b/src/confd/src/run.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include "core.h" + +/** + * Like system(), but takes a formatted string as argument. + * @param fmt printf style format list to command to run + * + * This system() wrapper greatly simplifies operations that usually + * consist of composing a command from parts into a dynamic buffer + * before calling it. The return value from system() is also parsed, + * checking for proper exit and signals. + * + * @returns If the command exits normally, the return code of the command + * is returned. Otherwise, if the command is signalled, the return code + * is -1 and @a errno is set to @c EINTR. + */ +int run(const char *fmt, ...) +{ + va_list ap; + char *cmd; + int len; + int rc; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + cmd = alloca(++len); + if (!cmd) { + errno = ENOMEM; + return -1; + } + + va_start(ap, fmt); + vsnprintf(cmd, len, fmt, ap); + va_end(ap); + + rc = system(cmd); + if (rc == -1) + return -1; + + if (WIFEXITED(rc)) { + errno = 0; + rc = WEXITSTATUS(rc); + } else if (WIFSIGNALED(rc)) { + errno = EINTR; + rc = -1; + } + + return rc; +}