4343#define CTL_QUERY_NODE_SEPARATOR "."
4444#define CTL_VALUE_ARG_SEPARATOR ","
4545
46+ /* GLOBAL TREE */
4647static int ctl_global_first_free = 0 ;
4748static struct ctl_node CTL_NODE (global )[CTL_MAX_ENTRIES ];
4849
@@ -78,6 +79,11 @@ char *Strdup(const char *s) {
7879 return p ;
7980}
8081
82+ int umfCtlGet (const char * name , void * ctx , void * arg ) {
83+ return ctl_query (NULL , ctx , CTL_QUERY_PROGRAMMATIC , name , CTL_QUERY_READ ,
84+ arg );
85+ }
86+
8187/*
8288 * ctl_find_node -- (internal) searches for a matching entry point in the
8389 * provided nodes
@@ -102,6 +108,9 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
102108 * in the main ctl tree.
103109 */
104110 while (node_name != NULL ) {
111+ if (n != NULL && n -> type == CTL_NODE_SUBTREE ) {
112+ break ;
113+ }
105114 char * endptr ;
106115 /*
107116 * Ignore errno from strtol: FreeBSD returns EINVAL if no
@@ -128,6 +137,7 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
128137 break ;
129138 }
130139 }
140+
131141 if (n -> name == NULL ) {
132142 goto error ;
133143 }
@@ -244,21 +254,29 @@ static void ctl_query_cleanup_real_args(const struct ctl_node *n,
244254 */
245255static int ctl_exec_query_read (void * ctx , const struct ctl_node * n ,
246256 enum ctl_query_source source , void * arg ,
247- struct ctl_index_utlist * indexes ) {
257+ struct ctl_index_utlist * indexes ,
258+ char * extra_name ,
259+ umf_ctl_query_type query_type ) {
260+ (void )extra_name , (void )query_type ;
248261 if (arg == NULL ) {
249262 errno = EINVAL ;
250263 return -1 ;
251264 }
252265
253- return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes );
266+ assert (MAX_CTL_QUERY_TYPE != query_type );
267+ return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes , NULL ,
268+ MAX_CTL_QUERY_TYPE );
254269}
255270
256271/*
257272 * ctl_exec_query_write -- (internal) calls the write callback of a node
258273 */
259274static int ctl_exec_query_write (void * ctx , const struct ctl_node * n ,
260275 enum ctl_query_source source , void * arg ,
261- struct ctl_index_utlist * indexes ) {
276+ struct ctl_index_utlist * indexes ,
277+ char * extra_name ,
278+ umf_ctl_query_type query_type ) {
279+ (void )extra_name , (void )query_type ;
262280 if (arg == NULL ) {
263281 errno = EINVAL ;
264282 return -1 ;
@@ -269,7 +287,9 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
269287 return -1 ;
270288 }
271289
272- int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes );
290+ assert (MAX_CTL_QUERY_TYPE != query_type );
291+ int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes , NULL ,
292+ MAX_CTL_QUERY_TYPE );
273293 ctl_query_cleanup_real_args (n , real_arg , source );
274294
275295 return ret ;
@@ -280,24 +300,40 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
280300 */
281301static int ctl_exec_query_runnable (void * ctx , const struct ctl_node * n ,
282302 enum ctl_query_source source , void * arg ,
283- struct ctl_index_utlist * indexes ) {
284- return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes );
303+ struct ctl_index_utlist * indexes ,
304+ char * extra_name ,
305+ umf_ctl_query_type query_type ) {
306+ (void )extra_name , (void )query_type ;
307+ assert (MAX_CTL_QUERY_TYPE != query_type );
308+ return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes , NULL ,
309+ MAX_CTL_QUERY_TYPE );
310+ }
311+
312+ static int ctl_exec_query_subtree (void * ctx , const struct ctl_node * n ,
313+ enum ctl_query_source source , void * arg ,
314+ struct ctl_index_utlist * indexes ,
315+ char * extra_name ,
316+ umf_ctl_query_type query_type ) {
317+ return n -> cb [CTL_QUERY_SUBTREE ](ctx , source , arg , indexes , extra_name ,
318+ query_type );
285319}
286320
287321static int (* ctl_exec_query [MAX_CTL_QUERY_TYPE ])(
288322 void * ctx , const struct ctl_node * n , enum ctl_query_source source ,
289- void * arg , struct ctl_index_utlist * indexes ) = {
323+ void * arg , struct ctl_index_utlist * indexes , char * extra_name ,
324+ umf_ctl_query_type query_type ) = {
290325 ctl_exec_query_read ,
291326 ctl_exec_query_write ,
292327 ctl_exec_query_runnable ,
328+ ctl_exec_query_subtree ,
293329};
294330
295331/*
296332 * ctl_query -- (internal) parses the name and calls the appropriate methods
297333 * from the ctl tree
298334 */
299335int ctl_query (struct ctl * ctl , void * ctx , enum ctl_query_source source ,
300- const char * name , enum ctl_query_type type , void * arg ) {
336+ const char * name , umf_ctl_query_type type , void * arg ) {
301337 if (name == NULL ) {
302338 errno = EINVAL ;
303339 return -1 ;
@@ -324,13 +360,17 @@ int ctl_query(struct ctl *ctl, void *ctx, enum ctl_query_source source,
324360 n = ctl_find_node (ctl -> root , name , indexes );
325361 }
326362
327- if (n == NULL || n -> type != CTL_NODE_LEAF || n -> cb [type ] == NULL ) {
363+ if (n == NULL ||
364+ (n -> type != CTL_NODE_LEAF && n -> type != CTL_NODE_SUBTREE ) ||
365+ n -> cb [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ] == NULL ) {
328366 errno = EINVAL ;
329367 goto out ;
330368 }
331369
332- ret = ctl_exec_query [type ](ctx , n , source , arg , indexes );
333-
370+ char * extra_name = strstr (name , n -> name );
371+ ret =
372+ ctl_exec_query [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ](
373+ ctx , n , source , arg , indexes , extra_name , type );
334374out :
335375 ctl_delete_indexes (indexes );
336376
0 commit comments