From 85af4342dcd3cdc45f382d21f5b6adf0e8ab7c87 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Wed, 12 Apr 2017 22:39:01 +0200 Subject: [PATCH] common plugin code, removed clixon_proc.c --- apps/backend/backend_plugin.c | 54 ++----- apps/cli/cli_plugin.c | 48 +----- apps/netconf/netconf_plugin.c | 54 ------- apps/restconf/restconf_lib.c | 61 +------ lib/clixon/clixon.h.in | 1 - lib/clixon/clixon_file.h | 2 + lib/clixon/clixon_plugin.h | 6 +- lib/clixon/clixon_proc.h | 46 ------ lib/src/Makefile.in | 2 +- lib/src/clixon_file.c | 32 ++++ lib/src/clixon_plugin.c | 74 +++++++++ lib/src/clixon_proc.c | 293 ---------------------------------- lib/src/clixon_string.c | 11 +- 13 files changed, 142 insertions(+), 542 deletions(-) delete mode 100644 lib/clixon/clixon_proc.h delete mode 100644 lib/src/clixon_proc.c diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c index 4889e6b5..7f0551b6 100644 --- a/apps/backend/backend_plugin.c +++ b/apps/backend/backend_plugin.c @@ -152,8 +152,8 @@ config_plugin_init(clicon_handle h) * @retval -1 Error */ static int -plugin_unload(clicon_handle h, - struct plugin *plg) +backend_plugin_unload(clicon_handle h, + struct plugin *plg) { char *error; @@ -182,37 +182,16 @@ plugin_unload(clicon_handle h, * @retval NULL Error */ static struct plugin * -plugin_load (clicon_handle h, - char *file, - int dlflags) +backend_plugin_load (clicon_handle h, + char *file, + int dlflags) { - char *error; void *handle; char *name; - struct plugin *new; - plginit_t *initfun; - - dlerror(); /* Clear any existing error */ - if ((handle = dlopen (file, dlflags)) == NULL) { - error = (char*)dlerror(); - clicon_err(OE_UNIX, 0, "dlopen: %s", error?error:"Unknown error"); - return NULL; - } - - initfun = dlsym(handle, PLUGIN_INIT); - if ((error = (char*)dlerror()) != NULL) { - clicon_err(OE_UNIX, 0, "dlsym: %s: %s", file, error); - return NULL; - } - - if (initfun(h) != 0) { - dlclose(handle); - if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ - clicon_err(OE_DB, 0, "Unknown error: %s: plugin_init does not make clicon_err call on error", - file); - return NULL; - } + struct plugin *new = NULL; + if ((handle = plugin_load(h, file, dlflags)) == NULL) + goto done; if ((new = malloc(sizeof(*new))) == NULL) { clicon_err(OE_UNIX, errno, "dhunk: %s", strerror(errno)); dlclose(handle); @@ -224,7 +203,6 @@ plugin_load (clicon_handle h, snprintf(new->p_name, sizeof(new->p_name), "%*s", (int)strlen(name)-2, name); new->p_handle = handle; - new->p_init = initfun; if ((new->p_start = dlsym(handle, PLUGIN_START)) != NULL) clicon_debug(2, "%s callback registered.", PLUGIN_START); if ((new->p_exit = dlsym(handle, PLUGIN_EXIT)) != NULL) @@ -244,7 +222,7 @@ plugin_load (clicon_handle h, if ((new->p_trans_abort = dlsym(handle, PLUGIN_TRANS_ABORT)) != NULL) clicon_debug(2, "%s callback registered.", PLUGIN_TRANS_ABORT); clicon_debug(2, "Plugin '%s' loaded.\n", name); - + done: return new; } @@ -338,7 +316,7 @@ plugin_append(struct plugin *p) * @retval -1 Error */ static int -config_plugin_load_dir(clicon_handle h, +backend_plugin_load_dir(clicon_handle h, const char *dir) { int retval = -1; @@ -374,7 +352,7 @@ config_plugin_load_dir(clicon_handle h, clicon_debug(1, "Loading master plugin '%.*s' ...", (int)strlen(filename), filename); - new = plugin_load(h, filename, RTLD_NOW|RTLD_GLOBAL); + new = backend_plugin_load(h, filename, RTLD_NOW|RTLD_GLOBAL); if (new == NULL) goto quit; if (plugin_append(new) < 0) @@ -387,7 +365,7 @@ config_plugin_load_dir(clicon_handle h, continue; /* Skip master now */ snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name); clicon_debug(1, "Loading plugin '%.*s' ...", (int)strlen(filename), filename); - new = plugin_load(h, filename, RTLD_NOW); + new = backend_plugin_load(h, filename, RTLD_NOW); if (new == NULL) goto quit; /* Append to 'plugins' */ @@ -405,7 +383,7 @@ quit: while (--np >= 0){ if ((p = &plugins[np]) == NULL) continue; - plugin_unload(h, p); + backend_plugin_unload(h, p); free(p); } free(plugins); @@ -428,7 +406,7 @@ plugin_initiate(clicon_handle h) char *dir; /* First load CLICON system plugins */ - if (config_plugin_load_dir(h, CLIXON_BACKEND_SYSDIR) < 0) + if (backend_plugin_load_dir(h, CLIXON_BACKEND_SYSDIR) < 0) return -1; /* Then load application plugins */ @@ -436,7 +414,7 @@ plugin_initiate(clicon_handle h) clicon_err(OE_PLUGIN, 0, "backend_dir not defined"); return -1; } - if (config_plugin_load_dir(h, dir) < 0) + if (backend_plugin_load_dir(h, dir) < 0) return -1; return 0; @@ -455,7 +433,7 @@ plugin_finish(clicon_handle h) for (i = 0; i < nplugins; i++) { p = &plugins[i]; - plugin_unload(h, p); + backend_plugin_unload(h, p); } if (plugins){ free(plugins); diff --git a/apps/cli/cli_plugin.c b/apps/cli/cli_plugin.c index fdbe8408..77252d83 100644 --- a/apps/cli/cli_plugin.c +++ b/apps/cli/cli_plugin.c @@ -162,31 +162,6 @@ syntax_append(clicon_handle h, return 0; } -/* - * Unload a plugin - */ -static int -plugin_unload(clicon_handle h, void *handle) -{ - int retval = 0; - char *error; - plgexit_t *exitfun; - - /* Call exit function is it exists */ - exitfun = dlsym(handle, PLUGIN_EXIT); - if (dlerror() == NULL) - exitfun(h); - - dlerror(); /* Clear any existing error */ - if (dlclose(handle) != 0) { - error = (char*)dlerror(); - cli_output (stderr, "dlclose: %s\n", error ? error : "Unknown error"); - /* Just report */ - } - - return retval; -} - /* * Unload all plugins in a group */ @@ -275,41 +250,22 @@ cli_plugin_load(clicon_handle h, char *file, int dlflags) { - char *error; char *name; - void *handle = NULL; - plginit_t *initfun; + plghndl_t handle = NULL; struct cli_plugin *cp = NULL; - dlerror(); /* Clear any existing error */ - if ((handle = dlopen (file, dlflags)) == NULL) { - error = (char*)dlerror(); - cli_output (stderr, "dlopen: %s\n", error ? error : "Unknown error"); + if ((handle = plugin_load(h, file, dlflags)) == NULL) goto quit; - } - /* call plugin_init() if defined */ - if ((initfun = dlsym(handle, PLUGIN_INIT)) != NULL) { - if (initfun(h) != 0) { - cli_output (stderr, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file); - goto quit; - } - } - if ((cp = malloc(sizeof (struct cli_plugin))) == NULL) { perror("malloc"); goto quit; } memset (cp, 0, sizeof(*cp)); - name = basename(file); snprintf(cp->cp_name, sizeof(cp->cp_name), "%.*s", (int)strlen(name)-3, name); cp->cp_handle = handle; quit: - if (cp == NULL) { - if (handle) - dlclose(handle); - } return cp; } diff --git a/apps/netconf/netconf_plugin.c b/apps/netconf/netconf_plugin.c index 9dc5d434..9a2e611f 100644 --- a/apps/netconf/netconf_plugin.c +++ b/apps/netconf/netconf_plugin.c @@ -75,60 +75,6 @@ struct netconf_reg { }; typedef struct netconf_reg netconf_reg_t; -/*! Unload a plugin - */ -static int -plugin_unload(clicon_handle h, void *handle) -{ - int retval = 0; - char *error; - plgexit_t *exitfn; - - /* Call exit function is it exists */ - exitfn = dlsym(handle, PLUGIN_EXIT); - if (dlerror() == NULL) - exitfn(h); - - dlerror(); /* Clear any existing error */ - if (dlclose(handle) != 0) { - error = (char*)dlerror(); - clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error"); - /* Just report */ - } - return retval; -} - - - -/* - * Load a dynamic plugin object and call it's init-function - * Note 'file' may be destructively modified - */ -static plghndl_t -plugin_load (clicon_handle h, char *file, int dlflags) -{ - char *error; - void *handle = NULL; - plginit_t *initfn; - - dlerror(); /* Clear any existing error */ - if ((handle = dlopen (file, dlflags)) == NULL) { - error = (char*)dlerror(); - clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error"); - goto quit; - } - /* call plugin_init() if defined */ - if ((initfn = dlsym(handle, PLUGIN_INIT)) != NULL) { - if (initfn(h) != 0) { - clicon_err(OE_PLUGIN, errno, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file); - goto quit; - } - } -quit: - - return handle; -} - static int nplugins = 0; static plghndl_t *plugins = NULL; static netconf_reg_t *deps = NULL; diff --git a/apps/restconf/restconf_lib.c b/apps/restconf/restconf_lib.c index cd933a36..7f5f6e4d 100644 --- a/apps/restconf/restconf_lib.c +++ b/apps/restconf/restconf_lib.c @@ -269,44 +269,6 @@ static int nplugins = 0; static plghndl_t *plugins = NULL; static credentials_t *p_credentials = NULL; /* Credentials callback */ -/*! Load a dynamic plugin object and call it's init-function - * Note 'file' may be destructively modified - */ -static plghndl_t -plugin_load (clicon_handle h, - char *file, - int dlflags) -{ - char *error; - void *handle = NULL; - plginit_t *initfn; - - clicon_debug(1, "%s", __FUNCTION__); - dlerror(); /* Clear any existing error */ - if ((handle = dlopen (file, dlflags)) == NULL) { - error = (char*)dlerror(); - clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error"); - goto done; - } - /* call plugin_init() if defined */ - if ((initfn = dlsym(handle, PLUGIN_INIT)) == NULL){ - clicon_err(OE_PLUGIN, errno, "Failed to find plugin_init when loading restconf plugin %s", file); - goto err; - } - if (initfn(h) != 0) { - clicon_err(OE_PLUGIN, errno, "Failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file); - goto err; - } - p_credentials = dlsym(handle, "restconf_credentials"); - done: - return handle; - err: - if (handle) - dlclose(handle); - return NULL; -} - - /*! Load all plugins you can find in CLICON_RESTCONF_DIR */ int @@ -335,6 +297,7 @@ restconf_plugin_load(clicon_handle h) (int)strlen(filename), filename); if ((handle = plugin_load(h, filename, RTLD_NOW)) == NULL) goto quit; + p_credentials = dlsym(handle, "restconf_credentials"); if ((plugins = realloc(plugins, (nplugins+1) * sizeof (*plugins))) == NULL) { clicon_err(OE_UNIX, errno, "realloc"); goto quit; @@ -348,28 +311,6 @@ quit: return retval; } -/*! Unload a plugin - */ -static int -plugin_unload(clicon_handle h, void *handle) -{ - int retval = 0; - char *error; - plgexit_t *exitfn; - - /* Call exit function is it exists */ - exitfn = dlsym(handle, PLUGIN_EXIT); - if (dlerror() == NULL) - exitfn(h); - - dlerror(); /* Clear any existing error */ - if (dlclose(handle) != 0) { - error = (char*)dlerror(); - clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error"); - /* Just report */ - } - return retval; -} /*! Unload all restconf plugins */ int diff --git a/lib/clixon/clixon.h.in b/lib/clixon/clixon.h.in index 907aba4f..d9f00a80 100644 --- a/lib/clixon/clixon.h.in +++ b/lib/clixon/clixon.h.in @@ -76,7 +76,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/clixon/clixon_file.h b/lib/clixon/clixon_file.h index 5965f62b..08cc1f57 100644 --- a/lib/clixon/clixon_file.h +++ b/lib/clixon/clixon_file.h @@ -42,4 +42,6 @@ int clicon_file_dirent(const char *dir, struct dirent **ent, int clicon_file_copy(char *src, char *target); +int group_name2gid(char *name, gid_t *gid); + #endif /* _CLIXON_FILE_H_ */ diff --git a/lib/clixon/clixon_plugin.h b/lib/clixon/clixon_plugin.h index 7dc50ddf..10d3d082 100644 --- a/lib/clixon/clixon_plugin.h +++ b/lib/clixon/clixon_plugin.h @@ -51,7 +51,7 @@ typedef void *(find_plugin_t)(clicon_handle, char *); * Prototypes */ /* Common plugin function names, function types and signatures. - * This set of plugins is extended in + * This plugin code is exytended by backend, cli, netconf, restconf plugins * Cli see cli_plugin.c * Backend see config_plugin.c */ @@ -77,4 +77,8 @@ typedef int (plgexit_t)(clicon_handle); /* Plugin exit */ /* Find a function in global namespace or a plugin. XXX clicon internal */ void *clicon_find_func(clicon_handle h, char *plugin, char *func); +plghndl_t plugin_load (clicon_handle h, char *file, int dlflags); + +int plugin_unload(clicon_handle h, plghndl_t *handle); + #endif /* _CLIXON_PLUGIN_H_ */ diff --git a/lib/clixon/clixon_proc.h b/lib/clixon/clixon_proc.h deleted file mode 100644 index 2a85d9b0..00000000 --- a/lib/clixon/clixon_proc.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - ***** BEGIN LICENSE BLOCK ***** - - Copyright (C) 2009-2017 Olof Hagsand and Benny Holmgren - - This file is part of CLIXON. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - Alternatively, the contents of this file may be used under the terms of - the GNU General Public License Version 3 or later (the "GPL"), - in which case the provisions of the GPL are applicable instead - of those above. If you wish to allow use of your version of this file only - under the terms of the GPL, and not to allow others to - use your version of this file under the terms of Apache License version 2, - indicate your decision by deleting the provisions above and replace them with - the notice and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this file under - the terms of any one of the Apache License version 2 or the GPL. - - ***** END LICENSE BLOCK ***** - - */ - -#ifndef _CLIXON_PROC_H_ -#define _CLIXON_PROC_H_ - -/* - * Prototypes - */ -int clicon_proc_run (char *, void (outcb)(char *), int doerr); -int clicon_proc_daemon (char *); -int group_name2gid(char *name, gid_t *gid); - -#endif /* _CLIXON_PROC_H_ */ diff --git a/lib/src/Makefile.in b/lib/src/Makefile.in index 0135d78e..8c390233 100644 --- a/lib/src/Makefile.in +++ b/lib/src/Makefile.in @@ -61,7 +61,7 @@ CPPFLAGS = @CPPFLAGS@ INCLUDES = -I. @INCLUDES@ -I$(top_srcdir)/lib/clixon -I$(top_srcdir)/include -I$(top_srcdir) -SRC = clixon_sig.c clixon_log.c clixon_err.c clixon_event.c clixon_proc.c \ +SRC = clixon_sig.c clixon_log.c clixon_err.c clixon_event.c \ clixon_string.c clixon_handle.c \ clixon_xml.c clixon_xml_map.c clixon_file.c \ clixon_json.c clixon_yang.c clixon_yang_type.c \ diff --git a/lib/src/clixon_file.c b/lib/src/clixon_file.c index 082ee6ae..bb1868dd 100644 --- a/lib/src/clixon_file.c +++ b/lib/src/clixon_file.c @@ -51,6 +51,7 @@ #include #include #include +#include /* cligen */ #include @@ -229,3 +230,34 @@ clicon_file_copy(char *src, } +/*! Translate group name to gid. Return -1 if error or not found. + * @param[in] name Name of group + * @param[out] gid Group id + * @retval 0 OK + * @retval -1 Error. or not found + */ +int +group_name2gid(char *name, + gid_t *gid) +{ + char buf[1024]; + struct group g0; + struct group *gr = &g0; + struct group *gtmp; + + gr = &g0; + /* This leaks memory in ubuntu */ + if (getgrnam_r(name, gr, buf, sizeof(buf), >mp) < 0){ + clicon_err(OE_UNIX, errno, "%s: getgrnam_r(%s): %s", + __FUNCTION__, name, strerror(errno)); + return -1; + } + if (gtmp == NULL){ + clicon_err(OE_UNIX, 0, "%s: No such group: %s", __FUNCTION__, name); + fprintf(stderr, "No such group %s\n", name); + return -1; + } + if (gid) + *gid = gr->gr_gid; + return 0; +} diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c index 24a5319b..c127a948 100644 --- a/lib/src/clixon_plugin.c +++ b/lib/src/clixon_plugin.c @@ -45,6 +45,7 @@ #include "clixon_err.h" #include "clixon_queue.h" #include "clixon_hash.h" +#include "clixon_log.h" #include "clixon_handle.h" #include "clixon_plugin.h" @@ -84,3 +85,76 @@ clicon_find_func(clicon_handle h, char *plugin, char *func) return dlsym(dlhandle, func); } + +/*! Load a dynamic plugin object and call its init-function + * Note 'file' may be destructively modified + * @param[in] h Clicon handle + * @param[in] file Which plugin to load + * @param[in] dlflags See man(3) dlopen + */ +plghndl_t +plugin_load (clicon_handle h, + char *file, + int dlflags) +{ + char *error; + void *handle = NULL; + plginit_t *initfn; + + clicon_debug(1, "%s", __FUNCTION__); + dlerror(); /* Clear any existing error */ + if ((handle = dlopen (file, dlflags)) == NULL) { + error = (char*)dlerror(); + clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error"); + goto done; + } + /* call plugin_init() if defined */ + if ((initfn = dlsym(handle, PLUGIN_INIT)) == NULL){ + clicon_err(OE_PLUGIN, errno, "Failed to find plugin_init when loading restconf plugin %s", file); + goto err; + } + if ((error = (char*)dlerror()) != NULL) { + clicon_err(OE_UNIX, 0, "dlsym: %s: %s", file, error); + goto done; + } + if (initfn(h) != 0) { + clicon_err(OE_PLUGIN, errno, "Failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file); + if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ + clicon_err(OE_DB, 0, "Unknown error: %s: plugin_init does not make clicon_err call on error", + file); + goto err; + } + done: + return handle; + err: + if (handle) + dlclose(handle); + return NULL; +} + + +/*! Unload a plugin + * @param[in] h Clicon handle + * @param[in] handle Clicon handle + */ +int +plugin_unload(clicon_handle h, + plghndl_t *handle) +{ + int retval = 0; + char *error; + plgexit_t *exitfn; + + /* Call exit function is it exists */ + exitfn = dlsym(handle, PLUGIN_EXIT); + if (dlerror() == NULL) + exitfn(h); + + dlerror(); /* Clear any existing error */ + if (dlclose(handle) != 0) { + error = (char*)dlerror(); + clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error"); + /* Just report */ + } + return retval; +} diff --git a/lib/src/clixon_proc.c b/lib/src/clixon_proc.c deleted file mode 100644 index cd1e363b..00000000 --- a/lib/src/clixon_proc.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * - ***** BEGIN LICENSE BLOCK ***** - - Copyright (C) 2009-2017 Olof Hagsand and Benny Holmgren - - This file is part of CLIXON. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - Alternatively, the contents of this file may be used under the terms of - the GNU General Public License Version 3 or later (the "GPL"), - in which case the provisions of the GPL are applicable instead - of those above. If you wish to allow use of your version of this file only - under the terms of the GPL, and not to allow others to - use your version of this file under the terms of Apache License version 2, - indicate your decision by deleting the provisions above and replace them with - the notice and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this file under - the terms of any one of the Apache License version 2 or the GPL. - - ***** END LICENSE BLOCK ***** - - */ - -#ifdef HAVE_CONFIG_H -#include "clixon_config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* clicon */ -#include "clixon_err.h" -#include "clixon_log.h" -#include "clixon_sig.h" -#include "clixon_string.h" -#include "clixon_queue.h" -#include "clixon_proc.h" - -/* - * Macros - */ -#define signal_set_mask(set) sigprocmask(SIG_SETMASK, (set), NULL) -#define signal_get_mask(set) sigprocmask (0, NULL, (set)) - -/* - * Child process ID - * XXX Really shouldn't be a global variable - */ -static int _clicon_proc_child = 0; - -/* - * Make sure child is killed by ctrl-C - */ -static void -clicon_proc_sigint(int sig) -{ - if (_clicon_proc_child > 0) - kill (_clicon_proc_child, SIGINT); -} - -/*! Fork a child process, setup a pipe between parent and child. - * Allowing parent to read the output of the child. - * @param[in] doerr If non-zero, stderr will be directed to the pipe as well. - * The pipe for the parent to write - * to the child is closed and cannot be used. - * - * When child process is done with the pipe setup, execute the specified - * command, execv(argv[0], argv). - * - * When parent is done with the pipe setup it will read output from the child - * until eof. The read output will be sent to the specified output callback, - * 'outcb' function. - * - * @retval number Matches (processes affected). - * @retval -1 Error. - */ -int -clicon_proc_run (char *cmd, - void (outcb)(char *), - int doerr) -{ - char - **argv, - buf[512]; - int - outfd[2] = { -1, -1 }; - int - n, - argc, - status, - retval = -1; - pid_t - child; - sigfn_t oldhandler = NULL; - sigset_t oset; - - argv = clicon_strsep(cmd, " \t", &argc); - if (!argv) - return -1; - - if (pipe (outfd) == -1) - goto done; - - signal_get_mask(&oset); - set_signal(SIGINT, clicon_proc_sigint, &oldhandler); - - - if ((child = fork ()) < 0) { - retval = -1; - goto done; - } - - if (child == 0) { /* Child */ - - /* Unblock all signals except TSTP */ - clicon_signal_unblock (0); - signal (SIGTSTP, SIG_IGN); - - close (outfd[0]); /* Close unused read ends */ - outfd[0] = -1; - - /* Divert stdout and stderr to pipes */ - dup2 (outfd[1], STDOUT_FILENO); - if (doerr) - dup2 (outfd[1], STDERR_FILENO); - - execvp (argv[0], argv); - perror("execvp"); - _exit(-1); - } - - /* Parent */ - - /* Close unused write ends */ - close (outfd[1]); - outfd[1] = -1; - - /* Read from pipe */ - while ((n = read (outfd[0], buf, sizeof (buf)-1)) != 0) { - if (n < 0) { - if (errno == EINTR) - continue; - break; - } - buf[n] = '\0'; - /* Pass read data to callback function is defined */ - if (outcb) - outcb (buf); - } - - /* Wait for child to finish */ - if(waitpid (child, &status, 0) == child) - retval = WEXITSTATUS(status); - else - retval = -1; - - done: - - /* Clean up all pipes */ - if (outfd[0] != -1) - close (outfd[0]); - if (outfd[1] != -1) - close (outfd[1]); - - /* Restore sigmask and fn */ - signal_set_mask (&oset); - set_signal(SIGINT, oldhandler, NULL); - - if(argv) - free(argv); - return retval; -} - -/*! Spawn command and report exit status - */ -int -clicon_proc_daemon (char *cmd) -{ - char - **argv; - int - i, - argc, - retval = -1, - status, status2; - pid_t - child, - pid; - struct rlimit - rlim; - - argv = clicon_strsep(cmd, " \t", &argc); - if (!argv) - return -1; - - if ((child = fork ()) < 0) { - clicon_err(OE_UNIX, errno, "fork"); - goto done; - } - - if (child == 0) { /* Child */ - - clicon_signal_unblock (0); - if ((pid = fork ()) < 0) { - clicon_err(OE_UNIX, errno, "fork"); - return -1; - _exit(1); - } - if (pid == 0) { /* Grandchild, create new session */ - setsid(); - if (chdir("/") < 0){ - clicon_err(OE_UNIX, errno, "chdirq"); - _exit(1); - } - /* Close open descriptors */ - if ( ! getrlimit (RLIMIT_NOFILE, &rlim)) - for (i = 0; i < rlim.rlim_cur; i++) - close(i); - - if (execv (argv[0], argv) < 0) { - clicon_err(OE_UNIX, errno, "execv"); - _exit(1); - } - /* Not reached */ - } - - waitpid (pid, &status2, 0); - _exit(status2); - - } - - if (waitpid (child, &status, 0) > 0) - retval = 0; - - done: - if (argv) - free(argv); - return (retval); -} - - -/*! Translate group name to gid. Return -1 if error or not found. - */ -int -group_name2gid(char *name, gid_t *gid) -{ - char buf[1024]; - struct group g0; - struct group *gr = &g0; - struct group *gtmp; - - gr = &g0; - /* This leaks memory in ubuntu */ - if (getgrnam_r(name, gr, buf, sizeof(buf), >mp) < 0){ - clicon_err(OE_UNIX, errno, "%s: getgrnam_r(%s): %s", - __FUNCTION__, name, strerror(errno)); - return -1; - } - if (gtmp == NULL){ - clicon_err(OE_UNIX, 0, "%s: No such group: %s", __FUNCTION__, name); - fprintf(stderr, "No such group %s\n", name); - return -1; - } - if (gid) - *gid = gr->gr_gid; - return 0; -} diff --git a/lib/src/clixon_string.c b/lib/src/clixon_string.c index aecb7977..98de980f 100644 --- a/lib/src/clixon_string.c +++ b/lib/src/clixon_string.c @@ -170,13 +170,16 @@ percent_encode(char *str, { int retval = -1; char *esc = NULL; + int len; int i, j; /* This is max */ - if ((esc = malloc(strlen(str)*3+1)) == NULL){ + len = strlen(str)*3+1; + if ((esc = malloc(len)) == NULL){ clicon_err(OE_UNIX, errno, "malloc"); goto done; } + memset(esc, 0, len); j = 0; for (i=0; i 2 && @@ -226,6 +232,7 @@ percent_decode(char *esc, str[j] = esc[i]; j++; } + str[j++] = '\0'; *strp = str; retval = 0; done: