- node = malloc(sizeof *node);
- if (!node)
- errno = ENOMEM;
- else {
- node->type = type;
- node->children[0] = left;
- node->children[1] = right;
- }
- return node;
-}
-
-/**
- * Frees the node and its possible subnodes
- * @param node the node to free
- */
-static void node_free(struct node *node)
-{
- struct node *left, *right;
-
- if (node) {
- switch (node->type) {
- case Text:
- free(node);
- break;
- case And:
- case Or:
- left = node->children[0];
- right = node->children[1];
- free(node);
- node_free(left);
- node_free(right);
- break;
- case Not:
- left = node->children[0];
- free(node);
- node_free(left);
- break;
- }
- }
-}
-
-/**
- * Checks the permissions for the 'node' using the 'check' function
- * and its 'closure'.
- * @param node the node to check
- * @param check the function that checks if a pernmission of 'name' is granted for 'closure'
- * @param closure the context closure for the function 'check'
- * @return 1 if the permission is granted or 0 otherwise
- */
-static int node_check(struct node *node, int (*check)(void *closure, const char *name), void *closure)
-{
- for(;;) {
- switch (node->type) {
- case Text:
- return check(closure, node->text);
- case And:
- if (!node_check(node->children[0], check, closure))
- return 0;
- break;
- case Or:
- if (node_check(node->children[0], check, closure))
- return 1;
- break;
- case Not:
- return !node_check(node->children[0], check, closure);
- }
- node = node->children[1];
- }
-}
-
-/*********************************************************************
-*** SECTION parse
-*********************************************************************/
-
-/**
- * the symbol types
- */
-enum symbol
-{
- TEXT, /**< a common text, name of a permission */
- AND, /**< and keyword */
- OR, /**< or keyword */
- NOT, /**< not keyword */
- OBRA, /**< open bracket */
- CBRA, /**< close bracket */
- END /**< end of input */
-};
-
-/**
- * structure for parsing permission description
- */
-struct parse
-{
- const char *desc; /**< initial permission description */
- const char *symbol; /**< current symbol parsed */
- size_t symlen; /**< length of the current symbol */
- enum symbol type; /**< type of the current symbol */
-};
-
-/**
- * updates parse to point to the next symbol if any
- * @param parse parser state to update
- */
-static void parse_next(struct parse *parse)
-{
- const char *scan;
- size_t len;
-
- /* skip current symbol */
- scan = &parse->symbol[parse->symlen];
-
- /* skip white spaces */
- while (*scan && isspace(*scan))
- scan++;
-
- /* scan the symbol */
- switch (*scan) {
- case 0:
- len = 0;
- parse->type = END;
- break;
- case '(':
- len = 1;
- parse->type = OBRA;
- break;
- case ')':
- len = 1;
- parse->type = CBRA;
- break;
- default:
- /* compute the length */
- len = 0;
- while (scan[len] && !isspace(scan[len]) && scan[len] != ')' && scan[len] != '(')
- len++;
- parse->type = TEXT;
-
- /* fall to keyword if any */
- switch(len) {
- case 2:
- if (!strncasecmp(scan, "or", len))
- parse->type = OR;
- break;
- case 3:
- if (!strncasecmp(scan, "and", len))
- parse->type = AND;
- else if (!strncasecmp(scan, "not", len))
- parse->type = NOT;
- break;
- }
- break;
- }
- parse->symbol = scan;
- parse->symlen = len;
-}
-
-/**
- * Init the parser state 'parse' for the description 'desc'
- * @param parse the parser state to initialise
- * @param desc the description of the permissions to be parsed
- */
-static void parse_init(struct parse *parse, const char *desc)
-{
- parse->desc = desc;
- parse->symbol = desc;
- parse->symlen = 0;
- parse_next(parse);
-}
-
-/*********************************************************************
-*** SECTION node_parse
-*********************************************************************/
-
-static struct node *node_parse_or(struct parse *parse);
-
-/**
- * Parse a permission name
- * @param parser the parser state
- * @return the parsed node or NULL in case of error
- * in case of error errno is set to EINVAL or ENOMEM
- */
-static struct node *node_parse_text(struct parse *parse)
-{
- struct node *node;