Moved callbacks starting programs from libclixon_cli to example code
The functions are: `cli_start_shell` and `cli_start_program` If you need them, add them to your application plugin code instead
This commit is contained in:
parent
2790d243e1
commit
b1d969e42b
4 changed files with 86 additions and 225 deletions
|
|
@ -35,6 +35,9 @@ Expected: January 2025
|
||||||
|
|
||||||
Developers may need to change their code
|
Developers may need to change their code
|
||||||
|
|
||||||
|
* Moved callbacks starting programs from libclixon_cli to example code
|
||||||
|
* The functions are: `cli_start_shell` and `cli_start_program`
|
||||||
|
* If you need them, add them to your application plugin code instead
|
||||||
* Changed C-API: add `system-only` parameter with default value `0` last:
|
* Changed C-API: add `system-only` parameter with default value `0` last:
|
||||||
* `clixon_json2file()` -> `clixon_json2file(,0)`
|
* `clixon_json2file()` -> `clixon_json2file(,0)`
|
||||||
* `clixon_json2cbuf()` -> `clixon_json2cbuf(,0)`
|
* `clixon_json2cbuf()` -> `clixon_json2cbuf(,0)`
|
||||||
|
|
|
||||||
|
|
@ -774,229 +774,6 @@ cli_set_mode(clixon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* @brief Spawns a new process and runs the specified program within it
|
|
||||||
*
|
|
||||||
* The function creates a new child process and runs the specified program within it.
|
|
||||||
* Before launching the program in the child process, environment variables taken from cvv are set.
|
|
||||||
*
|
|
||||||
* The function checks the parameters passed to it. Situations where at least one function argument
|
|
||||||
* is missing, or when two arguments are present in both the function and the cvv vector are considered invalid.
|
|
||||||
*
|
|
||||||
* Example usage:
|
|
||||||
* @code
|
|
||||||
* python3_args("Run program"), cli_start_program("python3"); {
|
|
||||||
* <argument:string>("Single shell command"), cli_start_program("python3", "/tmp/test.py");
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* python3_single("Run program"), cli_start_program("python3"); {
|
|
||||||
* <source:rest>("Single shell command"), cli_start_program("python3");
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* python3_script("Run program") <source:rest>("Path program"), cli_start_program("python3");
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @warning Please note that the usage of this function consists of executing an arbitrary command given to
|
|
||||||
* the function as an argument. It may pose a serious security risk if the function is used improperly.
|
|
||||||
* Developers should take necessary precautions to ensure safety, such as using `chroot` to limit the
|
|
||||||
* space of accessible scripts for execution.
|
|
||||||
*
|
|
||||||
* @param[in] h Clixon handle
|
|
||||||
* @param[in] cvv Vector of command variables
|
|
||||||
* @param[in] argv Function arguments
|
|
||||||
* @retval 0 OK, returns the exit code of the program
|
|
||||||
* @retval -1 Error
|
|
||||||
* @note utility, should probably not be in lib
|
|
||||||
* @see cli_start_shell
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cli_start_program(clixon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
int pid = 0;
|
|
||||||
int retval = -1;
|
|
||||||
int s = 0;
|
|
||||||
int arg_count = 0;
|
|
||||||
int cvv_count = 0;
|
|
||||||
int i = 0;
|
|
||||||
int status = 0;
|
|
||||||
char *script_path = NULL;
|
|
||||||
char *runner = NULL;
|
|
||||||
char *buf = NULL;
|
|
||||||
char *work_dir = NULL;
|
|
||||||
char *reserve_path = NULL;
|
|
||||||
char **args = NULL;
|
|
||||||
size_t bufsize = 0;
|
|
||||||
struct passwd pw, *pwresult = NULL;
|
|
||||||
|
|
||||||
/* Check parameters */
|
|
||||||
if (cvec_len(argv) == 0){
|
|
||||||
clixon_err(OE_PLUGIN, EINVAL, "Can not find argument");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get data */
|
|
||||||
arg_count = cvec_len(argv);
|
|
||||||
cvv_count = cvec_len(cvv);
|
|
||||||
|
|
||||||
runner = cv_string_get(cvec_i(argv, 0));
|
|
||||||
|
|
||||||
if (arg_count > 1) {
|
|
||||||
script_path = cv_string_get(cvec_i(argv, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (script_path){
|
|
||||||
reserve_path = strdup(script_path);
|
|
||||||
work_dir = dirname(reserve_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
|
|
||||||
if (bufsize == -1){
|
|
||||||
bufsize = 16384;
|
|
||||||
}
|
|
||||||
buf = malloc(bufsize);
|
|
||||||
if (buf == NULL) {
|
|
||||||
perror("malloc");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
s = getpwuid_r(getuid(), &pw, buf, bufsize, &pwresult);
|
|
||||||
if (pwresult == NULL) {
|
|
||||||
if (s == 0)
|
|
||||||
clixon_err(OE_PLUGIN, errno, "getpwuid_r");
|
|
||||||
else
|
|
||||||
perror("getpwuid_r");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare arguments for execlp */
|
|
||||||
args = malloc((arg_count + cvv_count) * sizeof(char *));
|
|
||||||
if (args == NULL) {
|
|
||||||
perror("malloc");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < arg_count; i++) {
|
|
||||||
args[i] = cv_string_get(cvec_i(argv, i));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < cvv_count; i++) {
|
|
||||||
args[arg_count + i] = cv_string_get(cvec_i(cvv, i + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* main run */
|
|
||||||
if ((pid = fork()) == 0) {
|
|
||||||
/* child process */
|
|
||||||
if ((work_dir ? chdir(work_dir) : chdir(pw.pw_dir)) < 0) {
|
|
||||||
clixon_err(OE_PLUGIN, errno, "chdir");
|
|
||||||
}
|
|
||||||
execvp(runner, args);
|
|
||||||
clixon_err(OE_PLUGIN, errno, "Error running script");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else if(pid == -1){
|
|
||||||
clixon_err(OE_PLUGIN, errno, "fork");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
/* parent process */
|
|
||||||
if (waitpid(pid, &status, 0) != pid ){
|
|
||||||
clixon_err(OE_PLUGIN, errno, "waitpid error");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
retval = WEXITSTATUS(status);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
if(buf)
|
|
||||||
free(buf);
|
|
||||||
if(reserve_path)
|
|
||||||
free(reserve_path);
|
|
||||||
if(args)
|
|
||||||
free(args);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Start bash from cli callback
|
|
||||||
*
|
|
||||||
* Typical usage: shell("System Bash") <source:rest>, cli_start_shell();
|
|
||||||
* @param[in] h Clixon handle
|
|
||||||
* @param[in] cvv Vector of command variables
|
|
||||||
* @param[in] argv [<shell>], defaults to "sh"
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
* @note utility, should probably not be in lib
|
|
||||||
* @see cli_start_program
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cli_start_shell(clixon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
char *cmd;
|
|
||||||
char *shcmd = "sh";
|
|
||||||
struct passwd *pw;
|
|
||||||
char bcmd[128];
|
|
||||||
cg_var *cv1 = cvec_i(cvv, 1);
|
|
||||||
sigset_t oldsigset;
|
|
||||||
struct sigaction oldsigaction[32] = {{{0,},},};
|
|
||||||
|
|
||||||
if (cvec_len(argv) > 1){
|
|
||||||
clixon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: [<shell>]",
|
|
||||||
cvec_len(argv));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (cvec_len(argv) == 1){
|
|
||||||
shcmd = cv_string_get(cvec_i(argv, 0));
|
|
||||||
}
|
|
||||||
cmd = (cvec_len(cvv)>1 ? cv_string_get(cv1) : NULL);
|
|
||||||
if ((pw = getpwuid(getuid())) == NULL){
|
|
||||||
clixon_err(OE_UNIX, errno, "getpwuid");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (chdir(pw->pw_dir) < 0){
|
|
||||||
clixon_err(OE_UNIX, errno, "chdir");
|
|
||||||
endpwent();
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
endpwent();
|
|
||||||
|
|
||||||
if (clixon_signal_save(&oldsigset, oldsigaction) < 0)
|
|
||||||
goto done;
|
|
||||||
cli_signal_flush(h);
|
|
||||||
cli_signal_unblock(h);
|
|
||||||
if (cmd){
|
|
||||||
snprintf(bcmd, 128, "%s -c \"%s\"", shcmd, cmd);
|
|
||||||
if (system(bcmd) < 0){
|
|
||||||
cli_signal_block(h);
|
|
||||||
clixon_err(OE_UNIX, errno, "system(bash -c)");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
snprintf(bcmd, 128, "%s ", shcmd); /* -l (login shell) but is applicable to bash only */
|
|
||||||
if (system(bcmd) < 0){
|
|
||||||
cli_signal_block(h);
|
|
||||||
clixon_err(OE_UNIX, errno, "system(bash)");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cli_signal_block(h);
|
|
||||||
#if 0 /* Allow errcodes from bash */
|
|
||||||
if (retval != 0){
|
|
||||||
clixon_err(OE_UNIX, errno, "system(%s) %d", cmd, retval);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (clixon_signal_restore(&oldsigset, oldsigaction) < 0)
|
|
||||||
goto done;
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Generic quit callback
|
/*! Generic quit callback
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
|
|
|
||||||
|
|
@ -80,11 +80,12 @@ cligen_handle cli_cligen(clixon_handle h);
|
||||||
int cli_notification_register(clixon_handle h, char *stream, enum format_enum format,
|
int cli_notification_register(clixon_handle h, char *stream, enum format_enum format,
|
||||||
char *filter, int status,
|
char *filter, int status,
|
||||||
int (*fn)(int, void*), void *arg);
|
int (*fn)(int, void*), void *arg);
|
||||||
|
void cli_signal_block(clixon_handle h);
|
||||||
|
void cli_signal_unblock(clixon_handle h);
|
||||||
|
void cli_signal_flush(clixon_handle h);
|
||||||
int mtpoint_paths(yang_stmt *yspec0, char *mtpoint, char *api_path_fmt1, char **api_path_fmt01);
|
int mtpoint_paths(yang_stmt *yspec0, char *mtpoint, char *api_path_fmt1, char **api_path_fmt01);
|
||||||
int dbxml_body(cxobj *xbot, cvec *cvv);
|
int dbxml_body(cxobj *xbot, cvec *cvv);
|
||||||
int identityref_add_ns(cxobj *x, void *arg);
|
int identityref_add_ns(cxobj *x, void *arg);
|
||||||
|
|
||||||
int cli_dbxml(clixon_handle h, cvec *vars, cvec *argv, enum operation_type op, cvec *nsctx);
|
int cli_dbxml(clixon_handle h, cvec *vars, cvec *argv, enum operation_type op, cvec *nsctx);
|
||||||
int cli_set(clixon_handle h, cvec *vars, cvec *argv);
|
int cli_set(clixon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_merge(clixon_handle h, cvec *vars, cvec *argv);
|
int cli_merge(clixon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
@ -110,6 +112,84 @@ mycallback(clixon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Start bash from cli callback
|
||||||
|
*
|
||||||
|
* Typical usage: shell("System Bash") <source:rest>, cli_start_shell();
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] cvv Vector of command variables
|
||||||
|
* @param[in] argv [<shell>], defaults to "sh"
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
* @note Code potentially unsafe
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cli_start_shell(clixon_handle h,
|
||||||
|
cvec *cvv,
|
||||||
|
cvec *argv)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *cmd;
|
||||||
|
char *shcmd = "sh";
|
||||||
|
struct passwd *pw;
|
||||||
|
char bcmd[128];
|
||||||
|
cg_var *cv1 = cvec_i(cvv, 1);
|
||||||
|
sigset_t oldsigset;
|
||||||
|
struct sigaction oldsigaction[32] = {{{0,},},};
|
||||||
|
|
||||||
|
if (cvec_len(argv) > 1){
|
||||||
|
clixon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: [<shell>]",
|
||||||
|
cvec_len(argv));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (cvec_len(argv) == 1){
|
||||||
|
shcmd = cv_string_get(cvec_i(argv, 0));
|
||||||
|
}
|
||||||
|
cmd = (cvec_len(cvv)>1 ? cv_string_get(cv1) : NULL);
|
||||||
|
if ((pw = getpwuid(getuid())) == NULL){
|
||||||
|
clixon_err(OE_UNIX, errno, "getpwuid");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (chdir(pw->pw_dir) < 0){
|
||||||
|
clixon_err(OE_UNIX, errno, "chdir");
|
||||||
|
endpwent();
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
endpwent();
|
||||||
|
|
||||||
|
if (clixon_signal_save(&oldsigset, oldsigaction) < 0)
|
||||||
|
goto done;
|
||||||
|
cli_signal_flush(h);
|
||||||
|
cli_signal_unblock(h);
|
||||||
|
if (cmd){
|
||||||
|
snprintf(bcmd, 128, "%s -c \"%s\"", shcmd, cmd);
|
||||||
|
if (system(bcmd) < 0){
|
||||||
|
cli_signal_block(h);
|
||||||
|
clixon_err(OE_UNIX, errno, "system(bash -c)");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
snprintf(bcmd, 128, "%s ", shcmd); /* -l (login shell) but is applicable to bash only */
|
||||||
|
if (system(bcmd) < 0){
|
||||||
|
cli_signal_block(h);
|
||||||
|
clixon_err(OE_UNIX, errno, "system(bash)");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cli_signal_block(h);
|
||||||
|
#if 0 /* Allow errcodes from bash */
|
||||||
|
if (retval != 0){
|
||||||
|
clixon_err(OE_UNIX, errno, "system(%s) %d", cmd, retval);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (clixon_signal_restore(&oldsigset, oldsigaction) < 0)
|
||||||
|
goto done;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Example "downcall", ie initiate an RPC to the backend
|
/*! Example "downcall", ie initiate an RPC to the backend
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue