diff options
Diffstat (limited to 'src/format.c')
-rw-r--r-- | src/format.c | 121 |
1 files changed, 99 insertions, 22 deletions
diff --git a/src/format.c b/src/format.c index c2e78ef..b6cc37d 100644 --- a/src/format.c +++ b/src/format.c @@ -3,6 +3,7 @@ #include <stdlib.h> #include "defaults.h" #include "format.h" +#include "plugin.h" void format_free_data(char *data) @@ -20,6 +21,8 @@ format_free_ndn_list(char **ndn_list) } } +/* Retrieve a single value for an attribute. If there are no values, or more + * than one, fail. */ static char * format_single(Slapi_PBlock *pb, Slapi_Entry *e, const char *attr, char ***visited_ndns) @@ -39,6 +42,7 @@ format_single(Slapi_PBlock *pb, Slapi_Entry *e, const char *attr, return ret; } +/* Find the matching closing marker. */ static const char * format_find_closer(const char *pair, const char *pattern) { @@ -62,7 +66,7 @@ format_find_closer(const char *pair, const char *pattern) * we visit (other than e) to the list of visited NDNs. Unless it's a literal, * treat the entire input format specifier as an expression. */ static int -format_expand(Slapi_PBlock *pb, Slapi_Entry *e, +format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt, char *outbuf, int outbuf_len, char ***visited_ndns, @@ -71,24 +75,25 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e, int i, j; int exp_len, level; const char *fmtstart, *fmtend, *match, *attribute; - char *tmp; + char *tmp, *fnname, *spd_id; char exp[outbuf_len * 2]; - const char *default_value, *alternate_value; + const char *default_value, *alternate_value, *paramstart, *paramend; size_t spn; - slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin", + spd_id = state->plugin_desc->spd_id; + slapi_log_error(SLAPI_LOG_PLUGIN, spd_id, "expanding %s\"%s\"%s\n", - literal ? "" : "%{", fmt, literal ? "" : "%{"); + literal ? "" : "%{", fmt, literal ? "" : "}"); - /* First, expand any subexpressions. */ + /* First, expand any subexpressions and call any "functions". */ level = 0; i = 0; j = 0; while (fmt[i] != '\0') { switch (fmt[i]) { case '%': - /* This might be a subexpression, or an escaped - * character. */ + /* This might be a subexpression, a "function" call, or + * an escaped character. */ switch (fmt[i + 1]) { case '%': /* It's just an escaped "%". */ @@ -102,8 +107,10 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e, /* Find the end of the subexpression. */ match = format_find_closer("{}", fmtstart + 1); if (match == NULL) { - slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin", - "expansion failed: no closing brace (2)\n"); + slapi_log_error(SLAPI_LOG_PLUGIN, + spd_id, + "expansion failed: " + "no closing brace\n"); return -1; } else { /* Mark the first character after the @@ -112,8 +119,11 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e, /* Make a copy of the subexpression. */ tmp = malloc(fmtend - fmtstart); if (tmp == NULL) { - slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin", - "expansion out of memory\n"); + slapi_log_error(SLAPI_LOG_PLUGIN, + spd_id, + "expansion " + "failed: out " + "of memory\n"); return -1; } memcpy(tmp, fmtstart + 2, @@ -121,7 +131,7 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e, tmp[fmtend - fmtstart - 3] = '\0'; /* Recursively expand the * subexpression. */ - exp_len = format_expand(pb, e, + exp_len = format_expand(state, pb, e, tmp, exp + j, sizeof(exp) - j, @@ -130,9 +140,14 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e, free(tmp); if ((exp_len < 0) || (exp_len + j >= (int) sizeof(exp))) { - /* We'd be out of space, FAIL. */ - slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin", - "expansion too big\n"); + /* We'd be out of space, + * FAIL. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + spd_id, + "expansion " + "failed: result" + " would be too " + "big\n"); return -1; } else { /* It fit, so keep going. */ @@ -142,6 +157,63 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e, } continue; break; + default: + /* Assume it's a "function" call. Pick out the + * name of the function. */ + paramstart = strchr(fmt + i, '{'); + if (paramstart == NULL) { + /* No start? Bad format. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + spd_id, + "expansion failed: " + "bad function " + "invocation\n"); + return -1; + } + paramend = strchr(paramstart + 1, '}'); + if (paramend == NULL) { + /* No matching end? Bad format. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + spd_id, + "expansion failed: " + "bad function " + "invocation\n"); + return -1; + } + fnname = malloc(paramstart - (fmt + i)); + if (fnname == NULL) { + /* Out of memory, FAIL. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + spd_id, + "expansion failed: " + "out of memory\n"); + return -1; + } + memcpy(fnname, fmt + i + 1, + paramstart - (fmt + i + 1)); + fnname[paramstart - (fmt + i + 1)] = '\0'; + /* Isolate the parameter string. */ + tmp = malloc(paramend - paramstart); + if (tmp == NULL) { + /* Out of memory, FAIL. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + spd_id, + "expansion failed: " + "out of memory\n"); + free(fnname); + return -1; + } + memcpy(tmp, paramstart + 1, + paramend - (paramstart + 1)); + tmp[paramend - paramstart] = '\0'; + slapi_log_error(SLAPI_LOG_PLUGIN, spd_id, + "calling \"%s\"(\"%s\")\n", + fnname, tmp); + free(fnname); + free(tmp); + i = (paramend - fmt) + 1; + continue; + break; } break; default: @@ -261,15 +333,16 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e, } static char * -format_format(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt, - char ***visited_ndns) +format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, + const char *fmt, char ***visited_ndns) { char buf[YPMAXRECORD], *tmp; const char *match, *fmtstart, *fmtend; unsigned int i, j; int exp_len; - i = format_expand(pb, e, fmt, buf, sizeof(buf), visited_ndns, TRUE); + i = format_expand(state, pb, e, fmt, buf, sizeof(buf), + visited_ndns, TRUE); if (i < sizeof(buf)) { buf[i] = '\0'; return strdup(buf); @@ -279,12 +352,13 @@ format_format(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt, } char * -format_get_data(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt, - char ***visited_ndns) +format_get_data(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, + const char *fmt, char ***visited_ndns) { Slapi_PBlock *local_pb; char ***ndn_list, **local_ndn_list, *ret; + /* Supply an NDN list if the caller didn't. */ if (visited_ndns != NULL) { ndn_list = visited_ndns; } else { @@ -292,6 +366,7 @@ format_get_data(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt, local_ndn_list = NULL; } + /* Supply a PBlock if the caller didn't. */ if (pb == NULL) { local_pb = slapi_pblock_new(); pb = local_pb; @@ -299,11 +374,13 @@ format_get_data(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt, local_pb = NULL; } - ret = format_format(pb, e, fmt, ndn_list); + ret = format_format(state, pb, e, fmt, ndn_list); + /* If we supplied a PBlock, clean it up. */ if (pb == local_pb) { slapi_pblock_destroy(local_pb); } + /* If we supplied an NDN list, clean it up. */ if (ndn_list == &local_ndn_list) { format_free_ndn_list(local_ndn_list); } |