C-API: Added cli_process_control(), added uid to cli_process_control()

This commit is contained in:
Olof hagsand 2023-06-01 17:44:49 +02:00
parent bd6a67f1d9
commit 080eef0278
12 changed files with 103 additions and 20 deletions

View file

@ -54,6 +54,7 @@ Expected: July 2023
### C/CLI-API changes on existing features
Developers may need to change their code
* Added `uid` parameter to `clixon_process_register()`
* Added output function to JSON output:
* `xml2json_vec(...,skiptop)` --> `xml2json_vec(..., cligen_output, skiptop)`
* `yang2cli_yspec` removed last argument `printgen`.

View file

@ -436,7 +436,7 @@ filter_xpath_again(clicon_handle h,
return retval;
}
/*! Help function for NACM access and returnmessage
/*! Help function for NACM access and return message
*
* @param[in] h Clicon handle
* @param[in] xret Result XML tree

View file

@ -314,13 +314,14 @@ restconf_pseudo_process_control(clicon_handle h)
if (clixon_process_register(h, RESTCONF_PROCESS,
"Clixon RESTCONF process",
NULL /* XXX network namespace */,
-1,
restconf_rpc_wrapper,
argv, nr) < 0)
goto done;
if (argv != NULL)
free(argv);
retval = 0;
done:
if (argv != NULL)
free(argv);
if (cb)
cbuf_free(cb);
return retval;

View file

@ -1626,3 +1626,64 @@ cvec_append(cvec *cvv0,
}
return cvv2;
}
/*! Process control as defined by clixon-lib API
*
* @param[in] h Clicon handle
* @param[in] cvv Not used
* @param[in] arg Two strings: <process name> <process operation>
* @code
* actions-daemon("Actions daemon operations") start,
* cli_process_control("Action process", "start");
* @endcode
*/
int
cli_process_control(clicon_handle h,
cvec *cvv,
cvec *argv)
{
int retval = -1;
char *name;
char *opstr;
cbuf *cb = NULL;
cxobj *xret = NULL;
cxobj *xerr;
if (cvec_len(argv) != 2){
clicon_err(OE_PLUGIN, EINVAL, "Requires two element: process name and operation");
goto done;
}
name = cv_string_get(cvec_i(argv, 0));
opstr = cv_string_get(cvec_i(argv, 1));
if (clixon_process_op_str2int(opstr) == -1){
clicon_err(OE_UNIX, 0, "No such process op: %s", opstr);
goto done;
}
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR);
cprintf(cb, ">");
cprintf(cb, "<process-control xmlns=\"%s\">", CLIXON_LIB_NS);
cprintf(cb, "<name>%s</name>", name);
cprintf(cb, "<operation>%s</operation>", opstr);
cprintf(cb, "</process-control>");
cprintf(cb, "</rpc>");
if (clicon_rpc_netconf(h, cbuf_get(cb), &xret, NULL) < 0)
goto done;
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
clixon_netconf_error(xerr, "Get configuration", NULL);
goto done;
}
if (clixon_xml2file(stdout, xml_child_i(xret, 0), 0, 1, NULL, cligen_output, 0, 1) < 0)
goto done;
retval = 0;
done:
if (xret)
xml_free(xret);
if (cb)
cbuf_free(cb);
return retval;
}

View file

@ -1515,7 +1515,6 @@ cli_show_statistics(clicon_handle h,
if (clixon_xml2file(stdout, xml_child_i(xret, 0), 0, 1, NULL, cligen_output, 0, 1) < 0)
goto done;
fprintf(stdout, "CLI:\n");
retval = 0;
done:
if (xret)

View file

@ -80,8 +80,6 @@ int cli_notification_register(clicon_handle h, char *stream, enum format_enum fo
char *filter, int status,
int (*fn)(int, void*), void *arg);
/* cli_common.c: CLIgen new vector callbacks */
int mtpoint_paths(yang_stmt *yspec0, char *mtpoint, char *api_path_fmt1, char **api_path_fmt01);
int dbxml_body(cxobj *xbot, cvec *cvv);
int identityref_add_ns(cxobj *x, void *arg);
@ -113,6 +111,7 @@ int cli_unlock(clicon_handle h, cvec *cvv, cvec *argv);
int cli_copy_config(clicon_handle h, cvec *cvv, cvec *argv);
int cli_help(clicon_handle h, cvec *vars, cvec *argv);
cvec *cvec_append(cvec *cvv0, cvec *cvv1);
int cli_process_control(clicon_handle h, cvec *vars, cvec *argv);
/* In cli_show.c */
int expand_dbvar(void *h, char *name, cvec *cvv, cvec *argv,

View file

@ -52,19 +52,25 @@ typedef enum proc_operation {
PROC_OP_STATUS
} proc_operation;
/* Process RPC callback function */
typedef int (proc_cb_t)(clicon_handle h, process_entry_t *pe, proc_operation *operation);
/*! Process RPC callback function
*
* @param[in] h Clixon handle
* @param[in] pe Process entry
* @param[in,out] op Process operation
*/
typedef int (proc_cb_t)(clicon_handle h,
process_entry_t *pe,
proc_operation *operation);
/*
* Prototypes
*/
int clixon_proc_socket(char **argv, int sock_flags, pid_t *pid, int *sock);
int clixon_proc_socket_close(pid_t pid, int sock);
int clixon_proc_background(char **argv, const char *netns, pid_t *pid);
int clixon_process_pid(clicon_handle h, const char *name, pid_t *pid);
proc_operation clixon_process_op_str2int(char *opstr);
int clixon_process_argv_get(clicon_handle h, const char *name, char ***argv, int *argc);
int clixon_process_register(clicon_handle h, const char *name, const char *descr, const char *netns, proc_cb_t *callback, char **argv, int argc);
int clixon_process_register(clicon_handle h, const char *name, const char *descr, const char *netns, uid_t uid, proc_cb_t *callback, char **argv, int argc);
int clixon_process_delete_all(clicon_handle h);
int clixon_process_operation(clicon_handle h, const char *name, proc_operation op, const int wrapit);
int clixon_process_status(clicon_handle h, const char *name, cbuf *cbret);

View file

@ -243,7 +243,7 @@ clicon_log_str(int level,
char *msg)
{
if (_logflags & CLICON_LOG_SYSLOG)
syslog(LOG_MAKEPRI(LOG_USER, level), "%s", msg);
syslog(LOG_MAKEPRI(LOG_USER, level), "%s", msg); // XXX this may block
/* syslog makes own filtering, we do it here:
* if normal (not debug) then filter loglevels >= debug
*/

View file

@ -81,7 +81,7 @@
* @param[in] buf Packet buffer
* @param[in] buflen Length of packet buffer
* @param[out] eof Socket closed / eof?
* @retval 0 OK
* @retval n length
* @retval -1 Error
*/
ssize_t

View file

@ -1688,6 +1688,7 @@ netconf_db_find(cxobj *xn,
* cbuf_free(cb);
* @endcode
* @see clixon_netconf_error_fn
* XXX does not support prefixes properly
*/
int
netconf_err2cb(cxobj *xerr,

View file

@ -50,7 +50,8 @@
description, namespace, start arguments, etc. Starts in STOPPED state:
--> STOPPED
On operation "start" or "restart" it gets a pid and goes into RUNNING state:
On operation using clixon_process_operation():
"start" or "restart" it gets a pid and goes into RUNNING state:
STOPPED -- (re)start --> RUNNING(pid)
When running, several things may happen:
@ -116,6 +117,7 @@
#include "clixon_hash.h"
#include "clixon_handle.h"
#include "clixon_options.h"
#include "clixon_uid.h"
#include "clixon_event.h"
#include "clixon_sig.h"
#include "clixon_string.h"
@ -143,6 +145,7 @@ struct process_entry_t {
char *pe_name; /* Name of process used for internal use. Unique with exiting=0 */
char *pe_description; /* Description of service */
char *pe_netns; /* Network namespace */
uid_t pe_uid; /* UID of process or -1 to keep same as backend */
char **pe_argv; /* argv with command as element 0 and NULL-terminated */
int pe_argc; /* Length of argc */
pid_t pe_pid; /* Running process id (state) or 0 if dead (pid is set if exiting=1) */
@ -150,7 +153,7 @@ struct process_entry_t {
proc_state_t pe_state; /* stopped, running, exiting */
pid_t pe_exit_status;/* Status on exit as defined in waitpid */
struct timeval pe_starttime; /* Start time */
proc_cb_t *pe_callback; /* Wrapper function, may be called from process_operation */
proc_cb_t *pe_callback; /* Wrapper function, may be called from process_operation */
};
/* Forward declaration */
@ -261,13 +264,15 @@ clixon_proc_socket_close(pid_t pid,
*
* @param[in] argv NULL-terminated Argument vector
* @param[in] netns Network namespace (or NULL)
* @param[in] uid User-id or -1 to keep existing
* @param[out] pid Process id
* @retval 0 OK
* @retval -1 Error.
*/
int
static int
clixon_proc_background(char **argv,
const char *netns,
uid_t uid,
pid_t *pid0)
{
int retval = -1;
@ -308,10 +313,14 @@ clixon_proc_background(char **argv,
char nsfile[PATH_MAX];
int nsfd;
#endif
if (uid != -1){
if (drop_priv_perm(uid) < 0)
goto done;
}
clicon_debug(1, "%s child", __FUNCTION__);
clicon_signal_unblock(0);
signal(SIGTSTP, SIG_IGN);
if (chdir("/") < 0){
clicon_err(OE_UNIX, errno, "chdirq");
exit(1);
@ -425,6 +434,7 @@ clixon_process_argv_get(clicon_handle h,
* @param[in] name Process name
* @param[in] description Description of process
* @param[in] netns Namespace netspace (or NULL)
* @param[in] uid UID of process (or -1 to keep same)
* @param[in] callback Wrapper function
* @param[in] argv NULL-terminated vector of vectors
* @param[in] argc Length of argv
@ -437,6 +447,7 @@ clixon_process_register(clicon_handle h,
const char *name,
const char *description,
const char *netns,
const uid_t uid,
proc_cb_t *callback,
char **argv,
int argc)
@ -470,6 +481,7 @@ clixon_process_register(clicon_handle h,
clicon_err(OE_DB, errno, "strdup netns");
goto done;
}
pe->pe_uid = uid;
pe->pe_argc = argc;
if ((pe->pe_argv = calloc(argc, sizeof(char *))) == NULL){
clicon_err(OE_UNIX, errno, "calloc");
@ -839,7 +851,8 @@ clixon_process_sched(int fd,
if (proc_op_run(pe->pe_pid, &isrunning) < 0)
goto done;
if (!isrunning)
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
if (clixon_proc_background(pe->pe_argv, pe->pe_netns,
pe->pe_uid, &pe->pe_pid) < 0)
goto done;
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
pe->pe_name, pe->pe_pid,
@ -864,7 +877,8 @@ clixon_process_sched(int fd,
case PROC_OP_START:
if (isrunning) /* Already runs */
break;
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
if (clixon_proc_background(pe->pe_argv, pe->pe_netns,
pe->pe_uid, &pe->pe_pid) < 0)
goto done;
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
pe->pe_name, pe->pe_pid,
@ -967,7 +981,8 @@ clixon_process_waitpid(clicon_handle h)
case PROC_OP_RESTART:
/* This is the case where there is an existing process running.
* it was killed above but still runs and needs to be reaped */
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
if (clixon_proc_background(pe->pe_argv, pe->pe_netns,
pe->pe_uid, &pe->pe_pid) < 0)
goto done;
gettimeofday(&pe->pe_starttime, NULL);
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,

View file

@ -489,7 +489,7 @@ clicon_rpc_netconf_xml(clicon_handle h,
* @param[in] db Name of database
* @param[in] xpath XPath (or "")
* @param[in] nsc Namespace context for filter
* @param[in] defaults Value of the with-defaults mode, rfc6243, or NULL
* @param[in] defaults Value of the with-defaults mode, rfc6243, or NULL
* @param[out] xt XML tree. Free with xml_free.
* Either <config> or <rpc-error>.
* @retval 0 OK