Fixed proper restore of cttl-C in msg rcv

Rename and move plugin_context_check to clixon_resource_check
This commit is contained in:
Olof hagsand 2023-12-21 15:00:12 +01:00
parent f25a77734e
commit 558a0df1f3
9 changed files with 268 additions and 261 deletions

View file

@ -48,7 +48,6 @@
#include <dirent.h>
#include <syslog.h>
#include <unistd.h>
#include <termios.h>
#include <sys/stat.h>
#include <sys/param.h>
@ -72,21 +71,12 @@
#include "clixon_yang_module.h"
#include "clixon_netconf_lib.h"
#include "clixon_validate.h"
#include "clixon_proc.h"
#include "clixon_plugin.h"
/*
* Private types
*/
/*! Structure for checking status before and after a plugin call
*
* Currently signal settings: blocked and handlers, and termios
* @see plugin_context_check
*/
struct plugin_context {
sigset_t pc_sigset; /* See sigprocmask(2) */
struct sigaction pc_sigaction_vec[32]; /* See sigaction(2) */
struct termios pc_termios; /* See termios(3) */
};
/* Internal plugin structure with dlopen() handle and plugin_api
* This is an internal type, not exposed in the API
@ -356,7 +346,7 @@ plugin_load_one(clixon_handle h,
}
clixon_err_reset();
wh = NULL;
if (plugin_context_check(h, &wh, file, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, file, __FUNCTION__) < 0)
goto done;
if ((api = initfn(h)) == NULL) {
if (!clixon_err_category()){ /* if clixon_err() is not called then log and continue */
@ -369,7 +359,7 @@ plugin_load_one(clixon_handle h,
goto done;
}
}
if (plugin_context_check(h, &wh, file, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, file, __FUNCTION__) < 0)
goto done;
/* Note: sizeof clixon_plugin_api which is largest of clixon_plugin_api:s */
@ -504,184 +494,6 @@ done:
return retval;
}
/*! Get system context, eg signal procmask (for blocking) and sigactions
*
* Call this before a plugin
* @retval pc Plugin context structure, use free() to deallocate
* @retval NULL Error
* @see plugin_context_check
* */
static void *
plugin_context_get(void)
{
int i;
struct plugin_context *pc = NULL;
if ((pc = malloc(sizeof(*pc))) == NULL){
clixon_err(OE_UNIX, errno, "malloc");
goto done;
}
memset(pc, 0, sizeof(*pc));
if (sigprocmask(0, NULL, &pc->pc_sigset) < 0){
clixon_err(OE_UNIX, errno, "sigprocmask");
goto done;
}
for (i=1; i<32; i++){
if (sigaction(i, NULL, &pc->pc_sigaction_vec[i]) < 0){
clixon_err(OE_UNIX, errno, "sigaction");
goto done;
}
/* Mask SA_RESTORER: Not intended for application use.
* Note that it may not be included in user space so may be hardcoded below
*/
#ifdef SA_RESTORER
pc->pc_sigaction_vec[i].sa_flags &= ~SA_RESTORER;
#else
pc->pc_sigaction_vec[i].sa_flags &= ~0x04000000;
#endif
}
if (isatty(0) && tcgetattr(0, &pc->pc_termios) < 0){
clixon_err(OE_UNIX, errno, "tcgetattr %d", errno);
goto done;
}
return pc;
done:
if (pc)
free(pc);
return NULL;
}
/*! Given an existing, old plugin context, check if anything has changed
*
* Called twice:
* 1) Make a check of resources
* 2) Make a new check and compare with the old check, return 1 on success, 0 on fail
* Log if there is a difference at loglevel WARNING.
* Controlled by CLICON_PLUGIN_CALLBACK_CHECK:
* 0 : No checks
* 1 : warning logs on failure
* 2 : log and abort on failure
*
* @param[in] h Clixon handle
* @param[in,out] wh Either: NULL for init, will be assigned, OR previous handle (will be freed)
* @param[in] name Name of plugin for logging. Can be other name, context dependent
* @param[in] fn Typically name of callback, or caller function
* @retval 1 OK
* @retval 0 Fail, log on syslog using LOG_WARNING
* @retval -1 Error
* @note Only logs error, does not generate error
* @note name and fn are context dependent, since the env of callback calls are very different
* @see plugin_context_get
* @see CLICON_PLUGIN_CALLBACK_CHECK Enable to activate these checks
*/
int
plugin_context_check(clixon_handle h,
void **wh,
const char *name,
const char *fn)
{
int retval = -1;
int failed = 0;
int i;
struct plugin_context *oldpc;
struct plugin_context *newpc = NULL;
int option;
if (h == NULL){
errno = EINVAL;
return -1;
}
option = clicon_option_int(h, "CLICON_PLUGIN_CALLBACK_CHECK");
/* Check if plugion checks are enabled */
if (option == 0)
return 1;
if (wh == NULL){
errno = EINVAL;
return -1;
}
if (*wh == NULL){
*wh = plugin_context_get();
return 1;
}
oldpc = (struct plugin_context *)*wh;
if ((newpc = plugin_context_get()) == NULL)
goto done;
if (oldpc->pc_termios.c_iflag != newpc->pc_termios.c_iflag){
clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios input modes from 0x%x to 0x%x", __FUNCTION__,
name, fn,
oldpc->pc_termios.c_iflag,
newpc->pc_termios.c_iflag);
failed++;
}
if (oldpc->pc_termios.c_oflag != newpc->pc_termios.c_oflag){
clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios output modes from 0x%x to 0x%x", __FUNCTION__,
name, fn,
oldpc->pc_termios.c_oflag,
newpc->pc_termios.c_oflag);
failed++;
}
if (oldpc->pc_termios.c_cflag != newpc->pc_termios.c_cflag){
clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios control modes from 0x%x to 0x%x", __FUNCTION__,
name, fn,
oldpc->pc_termios.c_cflag,
newpc->pc_termios.c_cflag);
failed++;
}
if (oldpc->pc_termios.c_lflag != newpc->pc_termios.c_lflag){
clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios local modes from 0x%x to 0x%x", __FUNCTION__,
name, fn,
oldpc->pc_termios.c_lflag,
newpc->pc_termios.c_lflag);
failed++;
}
/* XXX pc_termios.cc_t c_cc[NCCS] not checked */
/* Abort if option is 2 or above on failure
*/
if (option > 1 && failed)
abort();
for (i=1; i<32; i++){
if (sigismember(&oldpc->pc_sigset, i) != sigismember(&newpc->pc_sigset, i)){
clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed blocking of signal %s(%d) from %d to %d", __FUNCTION__,
name, fn, strsignal(i), i,
sigismember(&oldpc->pc_sigset, i),
sigismember(&newpc->pc_sigset, i)
);
failed++;
}
if (oldpc->pc_sigaction_vec[i].sa_flags != newpc->pc_sigaction_vec[i].sa_flags){
clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed flags of signal %s(%d) from 0x%x to 0x%x", __FUNCTION__,
name, fn, strsignal(i), i,
oldpc->pc_sigaction_vec[i].sa_flags,
newpc->pc_sigaction_vec[i].sa_flags);;
failed++;
}
if (oldpc->pc_sigaction_vec[i].sa_sigaction != newpc->pc_sigaction_vec[i].sa_sigaction){
clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed action of signal %s(%d) from %p to %p", __FUNCTION__,
name, fn, strsignal(i), i,
oldpc->pc_sigaction_vec[i].sa_sigaction,
newpc->pc_sigaction_vec[i].sa_sigaction);
failed++;
}
/* Abort if option is 2 or above on failure
*/
if (option > 1 && failed)
abort();
}
if (failed)
goto fail;
retval = 1; /* OK */
done:
if (newpc)
free(newpc);
if (oldpc)
free(oldpc);
if (wh && *wh)
*wh = NULL;
return retval;
fail:
retval = 0;
goto done;
}
/*! Call single plugin start callback
*
@ -700,7 +512,7 @@ clixon_plugin_start_one(clixon_plugin_t *cp,
if ((fn = cp->cp_api.ca_start) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (fn(h) < 0) {
if (clixon_err_category() < 0)
@ -708,7 +520,7 @@ clixon_plugin_start_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
}
retval = 0;
@ -758,7 +570,7 @@ clixon_plugin_exit_one(clixon_plugin_t *cp,
if ((fn = cp->cp_api.ca_exit) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (fn(h) < 0) {
if (clixon_err_category() < 0)
@ -766,7 +578,7 @@ clixon_plugin_exit_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (dlclose(cp->cp_handle) != 0) {
error = (char*)dlerror();
@ -833,7 +645,7 @@ clixon_plugin_auth_one(clixon_plugin_t *cp,
clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((fn = cp->cp_api.ca_auth) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if ((retval = fn(h, req, auth_type, authp)) < 0) {
if (clixon_err_category() < 0)
@ -841,7 +653,7 @@ clixon_plugin_auth_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
}
else
@ -918,7 +730,7 @@ clixon_plugin_extension_one(clixon_plugin_t *cp,
if ((fn = cp->cp_api.ca_extension) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (fn(h, yext, ys) < 0) {
if (clixon_err_category() < 0)
@ -926,7 +738,7 @@ clixon_plugin_extension_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
}
retval = 0;
@ -989,7 +801,7 @@ clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp,
if ((fn = cp->cp_api.ca_datastore_upgrade) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (fn(h, db, xt, msd) < 0) {
if (clixon_err_category() < 0)
@ -997,7 +809,7 @@ clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
}
retval = 0;
@ -1060,7 +872,7 @@ clixon_plugin_yang_mount_one(clixon_plugin_t *cp,
if ((fn = cp->cp_api.ca_yang_mount) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (fn(h, xt, config, vl, yanglib) < 0) {
if (clixon_err_category() < 0)
@ -1068,7 +880,7 @@ clixon_plugin_yang_mount_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
}
retval = 0;
@ -1127,7 +939,7 @@ clixon_plugin_yang_patch_one(clixon_plugin_t *cp,
if ((fn = cp->cp_api.ca_yang_patch) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (fn(h, ymod) < 0) {
if (clixon_err_category() < 0)
@ -1135,7 +947,7 @@ clixon_plugin_yang_patch_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
}
retval = 0;
@ -1187,7 +999,7 @@ clixon_plugin_netconf_errmsg_one(clixon_plugin_t *cp,
if ((fn = cp->cp_api.ca_errmsg) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (fn(h, xerr, cberr) < 0) {
if (clixon_err_category() < 0)
@ -1195,7 +1007,7 @@ clixon_plugin_netconf_errmsg_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
}
retval = 0;
@ -1247,7 +1059,7 @@ clixon_plugin_version_one(clixon_plugin_t *cp,
if ((fn = cp->cp_api.ca_version) != NULL){
wh = NULL;
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
if (fn(h, f) < 0) {
if (clixon_err_category() < 0)
@ -1255,7 +1067,7 @@ clixon_plugin_version_one(clixon_plugin_t *cp,
__FUNCTION__, cp->cp_name);
goto done;
}
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
goto done;
}
retval = 0;
@ -1424,16 +1236,16 @@ rpc_callback_call(clixon_handle h,
ns && rc->rc_namespace &&
strcmp(rc->rc_namespace, ns) == 0){
wh = NULL;
if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
goto done;
if (rc->rc_callback(h, xe, cbret, arg, rc->rc_arg) < 0){
clixon_debug(CLIXON_DBG_DEFAULT, "%s Error in: %s", __FUNCTION__, rc->rc_name);
if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
goto done;
goto done;
}
nr++;
if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
goto done;
}
rc = NEXTQ(rpc_callback_t *, rc);
@ -1551,16 +1363,16 @@ action_callback_call(clixon_handle h,
if ((rc = (rpc_callback_t *)yang_action_cb_get(ya)) != NULL){
do {
if (strcmp(rc->rc_name, name) == 0){
if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
goto done;
if (rc->rc_callback(h, xa, cbret, arg, rc->rc_arg) < 0){
clixon_debug(CLIXON_DBG_DEFAULT, "%s Error in: %s", __FUNCTION__, rc->rc_name);
if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
goto done;
goto done;
}
nr++;
if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0)
goto done;
}
rc = NEXTQ(rpc_callback_t *, rc);