static pr_ctrls_t *ctrls_prepare(ctrls_action_t *act) { pr_ctrls_t *ctrl = NULL; /* Sanity check */ if (!act) return NULL; pr_block_ctrls(); /* Get a blank ctrl object */ ctrl = ctrls_new(); /* Fill in the fields from the action object. */ ctrl->ctrls_id = act->id; ctrl->ctrls_module = act->module; ctrl->ctrls_action = act->action; ctrl->ctrls_desc = act->desc; ctrl->ctrls_cb = act->action_cb; ctrl->ctrls_flags = act->flags; /* Add this to the "in use" list */ ctrl->ctrls_next = ctrls_active_list; ctrls_active_list = ctrl; pr_unblock_ctrls(); return ctrl; }
int pr_ctrls_register(const module *mod, const char *action, const char *desc, int (*cb)(pr_ctrls_t *, int, char **)) { ctrls_action_t *act = NULL, *acti = NULL; int act_id = -1; /* sanity checks */ if (!action || !desc || !cb) { errno = EINVAL; return -1; } pr_trace_msg("ctrls", 3, "module '%s' registering handler for ctrl action '%s' (at %p)", mod ? mod->name : "(none)", action, cb); /* Block ctrls while we're doing this */ pr_block_ctrls(); /* Get a ctrl action object */ act = ctrls_action_new(); /* Randomly generate a unique random ID for this object */ while (TRUE) { unsigned char have_id = FALSE; act_id = rand(); /* Check the list for this ID */ for (acti = ctrls_action_list; acti; acti = acti->next) { if (acti->id == act_id) { have_id = TRUE; break; } } if (!have_id) break; } act->next = NULL; act->id = act_id; act->action = pstrdup(ctrls_pool, action); act->desc = desc; act->module = mod; act->action_cb = cb; /* Add this to the list of "registered" actions */ if (ctrls_action_list) { act->next = ctrls_action_list; ctrls_action_list->prev = act; } ctrls_action_list = act; pr_unblock_ctrls(); return act_id; }
int pr_ctrls_unregister(module *mod, const char *action) { ctrls_action_t *act = NULL; unsigned char have_action = FALSE; /* sanity checks */ if (!action) { errno = EINVAL; return -1; } /* Make sure that ctrls are blocked while we're doing this */ pr_block_ctrls(); for (act = ctrls_action_list; act; act = act->next) { if (strcmp(act->action, action) == 0 && (act->module == mod || mod == ANY_MODULE || mod == NULL)) { have_action = TRUE; /* Remove this object from the list of registered actions */ if (act->prev) act->prev->next = act->next; else ctrls_action_list = act->next; if (act->next) act->next->prev = act->prev; /* Destroy this action. */ destroy_pool(act->pool); } } pr_unblock_ctrls(); if (!have_action) { errno = ENOENT; return -1; } return 0; }
int pr_ctrls_unregister(module *mod, const char *action) { ctrls_action_t *act = NULL; unsigned char have_action = FALSE; /* Make sure that ctrls are blocked while we're doing this */ pr_block_ctrls(); for (act = ctrls_action_list; act; act = act->next) { if ((action == NULL || strcmp(act->action, action) == 0) && (act->module == mod || mod == ANY_MODULE || mod == NULL)) { have_action = TRUE; /* Remove this object from the list of registered actions */ if (act->prev) { act->prev->next = act->next; } else { ctrls_action_list = act->next; } if (act->next) { act->next->prev = act->prev; } pr_trace_msg("ctrls", 3, "module '%s' unregistering handler for ctrl action '%s'", mod ? mod->name : "(none)", act->action); /* Destroy this action. */ destroy_pool(act->pool); } } pr_unblock_ctrls(); if (!have_action) { errno = ENOENT; return -1; } return 0; }
static void ctrls_free(pr_ctrls_t *ctrl) { /* Make sure that ctrls are blocked while we're doing this */ pr_block_ctrls(); /* Remove this object from the active list */ if (ctrl->ctrls_prev) ctrl->ctrls_prev->ctrls_next = ctrl->ctrls_next; else ctrls_active_list = ctrl->ctrls_next; if (ctrl->ctrls_next) ctrl->ctrls_next->ctrls_prev = ctrl->ctrls_prev; /* Clear its fields, and add it to the free list */ ctrl->ctrls_next = NULL; ctrl->ctrls_prev = NULL; ctrl->ctrls_id = 0; ctrl->ctrls_module = NULL; ctrl->ctrls_action = NULL; ctrl->ctrls_cb = NULL; ctrl->ctrls_cb_retval = 1; ctrl->ctrls_flags = 0; if (ctrl->ctrls_tmp_pool) { destroy_pool(ctrl->ctrls_tmp_pool); ctrl->ctrls_tmp_pool = NULL; } ctrl->ctrls_cb_args = NULL; ctrl->ctrls_cb_resps = NULL; ctrl->ctrls_data = NULL; ctrl->ctrls_next = ctrls_free_list; ctrls_free_list = ctrl; pr_unblock_ctrls(); return; }
int pr_run_ctrls(module *mod, const char *action) { pr_ctrls_t *ctrl = NULL; /* Are ctrls blocked? */ if (ctrls_blocked) { errno = EPERM; return -1; } for (ctrl = ctrls_active_list; ctrl; ctrl = ctrl->ctrls_next) { /* Be watchful of the various client-side flags. Note: if * ctrl->ctrls_cl is ever NULL, it means there's a bug in the code. */ if (ctrl->ctrls_cl->cl_flags != PR_CTRLS_CL_HAVEREQ) continue; /* Has this control been disabled? */ if (ctrl->ctrls_flags & PR_CTRLS_ACT_DISABLED) continue; /* Is it time to trigger this ctrl? */ if (!(ctrl->ctrls_flags & PR_CTRLS_REQUESTED)) continue; if (ctrl->ctrls_when > time(NULL)) { ctrl->ctrls_flags |= PR_CTRLS_PENDING; pr_ctrls_add_response(ctrl, "request pending"); continue; } if (action && strcmp(ctrl->ctrls_action, action) == 0) { pr_log_debug(DEBUG7, "calling '%s' control handler", ctrl->ctrls_action); /* Invoke the callback, if the ctrl's action matches. Unblock * ctrls before invoking the callback, then re-block them after the * callback returns. This will allow the action handlers to use some * of the Controls API functions correctly. */ pr_unblock_ctrls(); ctrl->ctrls_cb_retval = ctrl->ctrls_cb(ctrl, (ctrl->ctrls_cb_args ? ctrl->ctrls_cb_args->nelts : 0), (ctrl->ctrls_cb_args ? (char **) ctrl->ctrls_cb_args->elts : NULL)); pr_block_ctrls(); if (ctrl->ctrls_cb_retval < 1) { ctrl->ctrls_flags &= ~PR_CTRLS_REQUESTED; ctrl->ctrls_flags &= ~PR_CTRLS_PENDING; ctrl->ctrls_flags |= PR_CTRLS_HANDLED; } } else if (!action) { pr_log_debug(DEBUG5, "calling '%s' control handler", ctrl->ctrls_action); /* If no action was given, invoke every callback */ pr_unblock_ctrls(); ctrl->ctrls_cb_retval = ctrl->ctrls_cb(ctrl, (ctrl->ctrls_cb_args ? ctrl->ctrls_cb_args->nelts : 0), (ctrl->ctrls_cb_args ? (char **) ctrl->ctrls_cb_args->elts : NULL)); pr_block_ctrls(); if (ctrl->ctrls_cb_retval < 1) { ctrl->ctrls_flags &= ~PR_CTRLS_REQUESTED; ctrl->ctrls_flags &= ~PR_CTRLS_PENDING; ctrl->ctrls_flags |= PR_CTRLS_HANDLED; } } } return 0; }