Changed hash API for better error handling
This commit is contained in:
parent
0f359676b1
commit
cdbce7645e
10 changed files with 125 additions and 73 deletions
|
|
@ -33,7 +33,10 @@
|
||||||
* CLICON_XML_CHANGELOG enables the yang changelog feature
|
* CLICON_XML_CHANGELOG enables the yang changelog feature
|
||||||
* CLICON_XML_CHANGELOG_FILE where the changelog resides
|
* CLICON_XML_CHANGELOG_FILE where the changelog resides
|
||||||
|
|
||||||
|
|
||||||
### API changes on existing features (you may need to change your code)
|
### API changes on existing features (you may need to change your code)
|
||||||
|
* Changed hash API for better error handling
|
||||||
|
* hash_dump, hash_keys, clicon_option_dump have new signatures
|
||||||
* Renamed `xml_insert` to `xml_wrap_all`.
|
* Renamed `xml_insert` to `xml_wrap_all`.
|
||||||
* Added modules-state diff parameter to xmldb_get datastore function for startup scenarios. Set this to NULL in normal cases.
|
* Added modules-state diff parameter to xmldb_get datastore function for startup scenarios. Set this to NULL in normal cases.
|
||||||
* `rpc_callback_register` added a namespace parameter. Example:
|
* `rpc_callback_register` added a namespace parameter. Example:
|
||||||
|
|
|
||||||
|
|
@ -509,7 +509,9 @@ main(int argc,
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||||
clicon_argv_set(h, argv0, argc, argv);
|
clicon_argv_set(h, argv0, argc, argv);
|
||||||
|
|
||||||
clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, logdst);
|
clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, logdst);
|
||||||
|
|
||||||
/* Defer: Wait to the last minute to print help message */
|
/* Defer: Wait to the last minute to print help message */
|
||||||
|
|
|
||||||
|
|
@ -439,6 +439,9 @@ main(int argc, char **argv)
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||||
|
clicon_argv_set(h, argv0, argc, argv);
|
||||||
|
|
||||||
/* Defer: Wait to the last minute to print help message */
|
/* Defer: Wait to the last minute to print help message */
|
||||||
if (help)
|
if (help)
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
|
|
|
||||||
|
|
@ -472,6 +472,9 @@ main(int argc,
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||||
|
clicon_argv_set(h, argv0, argc, argv);
|
||||||
|
|
||||||
/* Create top-level yang spec and store as option */
|
/* Create top-level yang spec and store as option */
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -633,6 +633,9 @@ main(int argc,
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||||
|
clicon_argv_set(h, argv0, argc, argv);
|
||||||
|
|
||||||
/* Initialize plugins group */
|
/* Initialize plugins group */
|
||||||
if ((dir = clicon_restconf_dir(h)) != NULL)
|
if ((dir = clicon_restconf_dir(h)) != NULL)
|
||||||
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,8 @@ text_disconnect(xmldb_handle xh)
|
||||||
free(th->th_dbdir);
|
free(th->th_dbdir);
|
||||||
if (th->th_dbs){
|
if (th->th_dbs){
|
||||||
if (th->th_cache){
|
if (th->th_cache){
|
||||||
keys = hash_keys(th->th_dbs, &klen);
|
if (hash_keys(th->th_dbs, &keys, &klen) < 0)
|
||||||
|
goto done;
|
||||||
for(i = 0; i < klen; i++)
|
for(i = 0; i < klen; i++)
|
||||||
if ((de = hash_value(th->th_dbs, keys[i], NULL)) != NULL){
|
if ((de = hash_value(th->th_dbs, keys[i], NULL)) != NULL){
|
||||||
if (de->de_xml)
|
if (de->de_xml)
|
||||||
|
|
@ -219,7 +220,7 @@ text_disconnect(xmldb_handle xh)
|
||||||
free(th);
|
free(th);
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
// done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1605,23 +1606,26 @@ int
|
||||||
text_unlock_all(xmldb_handle xh,
|
text_unlock_all(xmldb_handle xh,
|
||||||
int pid)
|
int pid)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
struct text_handle *th = handle(xh);
|
struct text_handle *th = handle(xh);
|
||||||
char **keys = NULL;
|
char **keys = NULL;
|
||||||
size_t klen;
|
size_t klen;
|
||||||
int i;
|
int i;
|
||||||
struct db_element *de;
|
struct db_element *de;
|
||||||
|
|
||||||
if ((keys = hash_keys(th->th_dbs, &klen)) == NULL)
|
if (hash_keys(th->th_dbs, &keys, &klen) < 0)
|
||||||
return 0;
|
goto done;
|
||||||
for(i = 0; i < klen; i++)
|
for(i = 0; i < klen; i++)
|
||||||
if ((de = hash_value(th->th_dbs, keys[i], NULL)) != NULL &&
|
if ((de = hash_value(th->th_dbs, keys[i], NULL)) != NULL &&
|
||||||
de->de_pid == pid){
|
de->de_pid == pid){
|
||||||
de->de_pid = 0;
|
de->de_pid = 0;
|
||||||
hash_add(th->th_dbs, keys[i], de, sizeof(*de));
|
hash_add(th->th_dbs, keys[i], de, sizeof(*de));
|
||||||
}
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
if (keys)
|
if (keys)
|
||||||
free(keys);
|
free(keys);
|
||||||
return 0;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Check if database is locked
|
/*! Check if database is locked
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,8 @@ clicon_hash_t hash_lookup (clicon_hash_t *head, const char *key);
|
||||||
void *hash_value (clicon_hash_t *head, const char *key, size_t *vlen);
|
void *hash_value (clicon_hash_t *head, const char *key, size_t *vlen);
|
||||||
clicon_hash_t hash_add (clicon_hash_t *head, const char *key, void *val, size_t vlen);
|
clicon_hash_t hash_add (clicon_hash_t *head, const char *key, void *val, size_t vlen);
|
||||||
int hash_del (clicon_hash_t *head, const char *key);
|
int hash_del (clicon_hash_t *head, const char *key);
|
||||||
void hash_dump(clicon_hash_t *head, FILE *f);
|
int hash_dump(clicon_hash_t *head, FILE *f);
|
||||||
char **hash_keys(clicon_hash_t *hash, size_t *nkeys);
|
int hash_keys(clicon_hash_t *hash, char ***vector, size_t *nkeys);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros to iterate over hash contents.
|
* Macros to iterate over hash contents.
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ enum startup_mode_t{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Print registry on file. For debugging. */
|
/* Print registry on file. For debugging. */
|
||||||
void clicon_option_dump(clicon_handle h, int dblevel);
|
int clicon_option_dump(clicon_handle h, int dblevel);
|
||||||
|
|
||||||
/* Add a clicon options overriding file setting */
|
/* Add a clicon options overriding file setting */
|
||||||
int clicon_option_add(clicon_handle h, char *name, char *value);
|
int clicon_option_add(clicon_handle h, char *name, char *value);
|
||||||
|
|
|
||||||
|
|
@ -105,16 +105,16 @@ hash_bucket(const char *str)
|
||||||
|
|
||||||
while(*str)
|
while(*str)
|
||||||
n += (uint32_t)*str++;
|
n += (uint32_t)*str++;
|
||||||
|
|
||||||
return n % HASH_SIZE;
|
return n % HASH_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Initialize hash table.
|
/*! Initialize hash table.
|
||||||
*
|
*
|
||||||
* @retval Pointer to new hash table.
|
* @retval hash Pointer to new hash table.
|
||||||
|
* @retval NULL Error
|
||||||
*/
|
*/
|
||||||
clicon_hash_t *
|
clicon_hash_t *
|
||||||
hash_init (void)
|
hash_init(void)
|
||||||
{
|
{
|
||||||
clicon_hash_t *hash;
|
clicon_hash_t *hash;
|
||||||
|
|
||||||
|
|
@ -148,13 +148,12 @@ hash_free(clicon_hash_t *hash)
|
||||||
free(hash);
|
free(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Find hash key.
|
/*! Find hash key.
|
||||||
*
|
*
|
||||||
* @param[in] hash Hash table
|
* @param[in] hash Hash table
|
||||||
* @param[in] key Variable name
|
* @param[in] key Variable name
|
||||||
* @retval variable Hash variable structure on success
|
* @retval variable Hash variable structure on success
|
||||||
* @retval NULL Error
|
* @retval NULL Not found
|
||||||
*/
|
*/
|
||||||
clicon_hash_t
|
clicon_hash_t
|
||||||
hash_lookup(clicon_hash_t *hash,
|
hash_lookup(clicon_hash_t *hash,
|
||||||
|
|
@ -178,9 +177,9 @@ hash_lookup(clicon_hash_t *hash,
|
||||||
/*! Get value of hash
|
/*! Get value of hash
|
||||||
* @param[in] hash Hash table
|
* @param[in] hash Hash table
|
||||||
* @param[in] key Variable name
|
* @param[in] key Variable name
|
||||||
* @param[out] vlen Length of value (as returned by function)
|
* @param[out] vlen Length of value (as returned by function if != NULL)
|
||||||
* @retval value Hash value, length given in vlen
|
* @retval value Hash value, length given in vlen
|
||||||
* @retval NULL Error
|
* @retval NULL Key not found or value NULL
|
||||||
*/
|
*/
|
||||||
void *
|
void *
|
||||||
hash_value(clicon_hash_t *hash,
|
hash_value(clicon_hash_t *hash,
|
||||||
|
|
@ -191,7 +190,7 @@ hash_value(clicon_hash_t *hash,
|
||||||
|
|
||||||
h = hash_lookup(hash, key);
|
h = hash_lookup(hash, key);
|
||||||
if (h == NULL)
|
if (h == NULL)
|
||||||
return NULL;
|
return NULL; /* OK, key not found */
|
||||||
|
|
||||||
if (vlen)
|
if (vlen)
|
||||||
*vlen = h->h_vlen;
|
*vlen = h->h_vlen;
|
||||||
|
|
@ -204,8 +203,9 @@ hash_value(clicon_hash_t *hash,
|
||||||
* @param[in] key Variable name
|
* @param[in] key Variable name
|
||||||
* @param[in] val Variable value (pointer to)
|
* @param[in] val Variable value (pointer to)
|
||||||
* @param[in] vlen Length of variable value
|
* @param[in] vlen Length of variable value
|
||||||
* @retval variable New hash structure on success
|
* @retval hash New hash structure on success
|
||||||
* @retval NULL Failure
|
* @retval NULL Error
|
||||||
|
* @note special case val is NULL and vlen==0
|
||||||
*/
|
*/
|
||||||
clicon_hash_t
|
clicon_hash_t
|
||||||
hash_add(clicon_hash_t *hash,
|
hash_add(clicon_hash_t *hash,
|
||||||
|
|
@ -213,10 +213,16 @@ hash_add(clicon_hash_t *hash,
|
||||||
void *val,
|
void *val,
|
||||||
size_t vlen)
|
size_t vlen)
|
||||||
{
|
{
|
||||||
void *newval;
|
void *newval = NULL;
|
||||||
clicon_hash_t h;
|
clicon_hash_t h;
|
||||||
clicon_hash_t new = NULL;
|
clicon_hash_t new = NULL;
|
||||||
|
|
||||||
|
/* Check NULL case */
|
||||||
|
if ((val == NULL && vlen != 0) ||
|
||||||
|
(val != NULL && vlen == 0)){
|
||||||
|
clicon_err(OE_UNIX, EINVAL, "Mismatch in value and length, only one is zero");
|
||||||
|
goto catch;
|
||||||
|
}
|
||||||
/* If variable exist, don't allocate a new. just replace value */
|
/* If variable exist, don't allocate a new. just replace value */
|
||||||
h = hash_lookup(hash, key);
|
h = hash_lookup(hash, key);
|
||||||
if (h == NULL) {
|
if (h == NULL) {
|
||||||
|
|
@ -235,6 +241,7 @@ hash_add(clicon_hash_t *hash,
|
||||||
h = new;
|
h = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vlen){
|
||||||
/* Make copy of value. aligned */
|
/* Make copy of value. aligned */
|
||||||
newval = malloc(align4(vlen+3));
|
newval = malloc(align4(vlen+3));
|
||||||
if (newval == NULL){
|
if (newval == NULL){
|
||||||
|
|
@ -242,6 +249,7 @@ hash_add(clicon_hash_t *hash,
|
||||||
goto catch;
|
goto catch;
|
||||||
}
|
}
|
||||||
memcpy(newval, val, vlen);
|
memcpy(newval, val, vlen);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free old value if existing variable */
|
/* Free old value if existing variable */
|
||||||
if (h->h_val)
|
if (h->h_val)
|
||||||
|
|
@ -270,8 +278,8 @@ catch:
|
||||||
* @param[in] hash Hash table
|
* @param[in] hash Hash table
|
||||||
* @param[in] key Variable name
|
* @param[in] key Variable name
|
||||||
*
|
*
|
||||||
* @retval 0 success
|
* @retval 0 OK
|
||||||
* @retval -1 failure
|
* @retval -1 Key not found
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
hash_del(clicon_hash_t *hash,
|
hash_del(clicon_hash_t *hash,
|
||||||
|
|
@ -295,14 +303,18 @@ hash_del(clicon_hash_t *hash,
|
||||||
/*! Return vector of keys in hash table
|
/*! Return vector of keys in hash table
|
||||||
*
|
*
|
||||||
* @param[in] hash Hash table
|
* @param[in] hash Hash table
|
||||||
|
* @param[out] vector Vector of keys, NULL if not found
|
||||||
* @param[out] nkeys Size of key vector
|
* @param[out] nkeys Size of key vector
|
||||||
* @retval vector Vector of keys
|
* @retval 0 OK
|
||||||
* @retval NULL Error
|
* @retval -1 Error
|
||||||
|
* @note: vector needs to be deallocated with free
|
||||||
*/
|
*/
|
||||||
char **
|
int
|
||||||
hash_keys(clicon_hash_t *hash,
|
hash_keys(clicon_hash_t *hash,
|
||||||
|
char ***vector,
|
||||||
size_t *nkeys)
|
size_t *nkeys)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
int bkt;
|
int bkt;
|
||||||
clicon_hash_t h;
|
clicon_hash_t h;
|
||||||
char **tmp;
|
char **tmp;
|
||||||
|
|
@ -325,40 +337,48 @@ hash_keys(clicon_hash_t *hash,
|
||||||
h = NEXTQ(clicon_hash_t, h);
|
h = NEXTQ(clicon_hash_t, h);
|
||||||
} while (h != hash[bkt]);
|
} while (h != hash[bkt]);
|
||||||
}
|
}
|
||||||
|
if (vector){
|
||||||
return keys;
|
*vector = keys;
|
||||||
|
keys = NULL;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
catch:
|
catch:
|
||||||
if (keys)
|
if (keys)
|
||||||
free(keys);
|
free(keys);
|
||||||
return NULL;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Dump contents of hash to FILE pointer.
|
/*! Dump contents of hash to FILE pointer.
|
||||||
*
|
*
|
||||||
* @param[in] hash Hash structure
|
* @param[in] hash Hash structure
|
||||||
* @param[in] f FILE pointer for print output
|
* @param[in] f FILE pointer for print output
|
||||||
* @retval void
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
hash_dump(clicon_hash_t *hash,
|
hash_dump(clicon_hash_t *hash,
|
||||||
FILE *f)
|
FILE *f)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
int i;
|
int i;
|
||||||
char **keys;
|
char **keys = NULL;
|
||||||
void *val;
|
void *val;
|
||||||
size_t klen;
|
size_t klen;
|
||||||
size_t vlen;
|
size_t vlen;
|
||||||
|
|
||||||
if (hash == NULL)
|
if (hash == NULL)
|
||||||
return;
|
goto ok;
|
||||||
keys = hash_keys(hash, &klen);
|
if (hash_keys(hash, &keys, &klen) < 0)
|
||||||
if (keys == NULL)
|
goto done;
|
||||||
return;
|
|
||||||
|
|
||||||
for(i = 0; i < klen; i++) {
|
for(i = 0; i < klen; i++) {
|
||||||
val = hash_value(hash, keys[i], &vlen);
|
val = hash_value(hash, keys[i], &vlen);
|
||||||
printf("%s =\t 0x%p , length %zu\n", keys[i], val, vlen);
|
printf("%s =\t 0x%p , length %zu\n", keys[i], val, vlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ok:
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (keys)
|
||||||
free(keys);
|
free(keys);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,24 +86,25 @@ static const map_str2int startup_mode_map[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Print registry on file. For debugging.
|
/*! Print registry on file. For debugging.
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] dbglevel Debug level
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
clicon_option_dump(clicon_handle h,
|
clicon_option_dump(clicon_handle h,
|
||||||
int dbglevel)
|
int dbglevel)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
clicon_hash_t *hash = clicon_options(h);
|
clicon_hash_t *hash = clicon_options(h);
|
||||||
int i;
|
int i;
|
||||||
char **keys;
|
char **keys = NULL;
|
||||||
void *val;
|
void *val;
|
||||||
size_t klen;
|
size_t klen;
|
||||||
size_t vlen;
|
size_t vlen;
|
||||||
|
|
||||||
if (hash == NULL)
|
if (hash_keys(hash, &keys, &klen) < 0)
|
||||||
return;
|
goto done;
|
||||||
keys = hash_keys(hash, &klen);
|
|
||||||
if (keys == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(i = 0; i < klen; i++) {
|
for(i = 0; i < klen; i++) {
|
||||||
val = hash_value(hash, keys[i], &vlen);
|
val = hash_value(hash, keys[i], &vlen);
|
||||||
if (vlen){
|
if (vlen){
|
||||||
|
|
@ -115,7 +116,11 @@ clicon_option_dump(clicon_handle h,
|
||||||
else
|
else
|
||||||
clicon_debug(dbglevel, "%s = NULL", keys[i]);
|
clicon_debug(dbglevel, "%s = NULL", keys[i]);
|
||||||
}
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (keys)
|
||||||
free(keys);
|
free(keys);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Read filename and set values to global options registry. XML variant.
|
/*! Read filename and set values to global options registry. XML variant.
|
||||||
|
|
@ -1063,12 +1068,16 @@ clicon_argv_get(clicon_handle h,
|
||||||
clicon_hash_t *cdat = clicon_data(h);
|
clicon_hash_t *cdat = clicon_data(h);
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
|
if (argc){
|
||||||
if ((p = hash_value(cdat, "argc", NULL)) == NULL)
|
if ((p = hash_value(cdat, "argc", NULL)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
*argc = *(int*)p;
|
*argc = *(int*)p;
|
||||||
|
}
|
||||||
|
if (argv){
|
||||||
if ((p = hash_value(cdat, "argv", NULL)) == NULL)
|
if ((p = hash_value(cdat, "argv", NULL)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
*argv = *(char***)p;
|
*argv = *(char***)p;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1076,9 +1085,10 @@ clicon_argv_get(clicon_handle h,
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] prog argv[0] - the program name
|
* @param[in] prog argv[0] - the program name
|
||||||
* @param[in] argc Length of argv
|
* @param[in] argc Length of argv
|
||||||
* @param[in] argv Array of command-line options
|
* @param[in] argv Array of command-line options or NULL
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
* @note If argv=NULL deallocate allocated argv vector if exists.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_argv_set(clicon_handle h,
|
clicon_argv_set(clicon_handle h,
|
||||||
|
|
@ -1086,20 +1096,25 @@ clicon_argv_set(clicon_handle h,
|
||||||
int argc,
|
int argc,
|
||||||
char **argv)
|
char **argv)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
clicon_hash_t *cdat = clicon_data(h);
|
clicon_hash_t *cdat = clicon_data(h);
|
||||||
char **argvv = NULL;
|
char **argvv = NULL;
|
||||||
|
|
||||||
/* add space for null-termination and argv[0] program name */
|
/* add space for null-termination and argv[0] program name */
|
||||||
if ((argvv = calloc(argc+2, sizeof(char*))) == NULL){
|
if ((argvv = calloc(argc+2, sizeof(char*))) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "calloc");
|
clicon_err(OE_UNIX, errno, "calloc");
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
memcpy(argvv+1, argv, argc*sizeof(char*));
|
memcpy(argvv+1, argv, argc*sizeof(char*));
|
||||||
argvv[0] = prgm;
|
argvv[0] = prgm;
|
||||||
if (hash_add(cdat, "argv", &argvv, sizeof(argvv))==NULL)
|
if (hash_add(cdat, "argv", &argvv, sizeof(argvv))==NULL)
|
||||||
return -1;
|
goto done;
|
||||||
argc += 1;
|
argc += 1;
|
||||||
if (hash_add(cdat, "argc", &argc, sizeof(argc))==NULL)
|
if (hash_add(cdat, "argc", &argc, sizeof(argc))==NULL)
|
||||||
return -1;
|
goto done;
|
||||||
return 0;
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (argvv)
|
||||||
|
free(argvv);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue