summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@localhost.localdomain>2008-05-13 17:19:11 -0400
committerNalin Dahyabhai <nalin@localhost.localdomain>2008-05-13 17:19:11 -0400
commit6aee466569e68cf0a8b4d3acb0f9f425714a3cbb (patch)
tree3491c1d32c03d185522ab9ad5cf804a6e6f5e7a6 /src
parent8c9f613312516963b0513fa88f6957fa7fb47566 (diff)
downloadslapi-nis-6aee466569e68cf0a8b4d3acb0f9f425714a3cbb.tar.gz
slapi-nis-6aee466569e68cf0a8b4d3acb0f9f425714a3cbb.tar.xz
slapi-nis-6aee466569e68cf0a8b4d3acb0f9f425714a3cbb.zip
- implement format specifier-based evaluation for entries
Diffstat (limited to 'src')
-rw-r--r--src/defaults.h4
-rw-r--r--src/format.c245
2 files changed, 245 insertions, 4 deletions
diff --git a/src/defaults.h b/src/defaults.h
index 2f651c0..96872ad 100644
--- a/src/defaults.h
+++ b/src/defaults.h
@@ -1,3 +1,3 @@
#define DEFAULT_ENTRY_FILTER "(&(nisMapName=%m)(objectClass=nisObject))"
-#define DEFAULT_KEY_ATTRIBUTE "cn"
-#define DEFAULT_VALUE_ATTRIBUTE "nisMapEntry"
+#define DEFAULT_KEY_ATTRIBUTE "%{cn}"
+#define DEFAULT_VALUE_ATTRIBUTE "%{nisMapEntry}"
diff --git a/src/format.c b/src/format.c
index 87ae640..c2e78ef 100644
--- a/src/format.c
+++ b/src/format.c
@@ -1,5 +1,7 @@
#include <sys/types.h>
+#include <rpcsvc/yp.h>
#include <stdlib.h>
+#include "defaults.h"
#include "format.h"
void
@@ -19,12 +21,12 @@ format_free_ndn_list(char **ndn_list)
}
static char *
-format_format(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
+format_single(Slapi_PBlock *pb, Slapi_Entry *e, const char *attr,
char ***visited_ndns)
{
char **values, *ret;
int count;
- values = slapi_entry_attr_get_charray(e, fmt);
+ values = slapi_entry_attr_get_charray(e, attr);
for (count = 0; (values != NULL) && (values[count] != NULL); count++) {
continue;
}
@@ -37,6 +39,245 @@ format_format(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
return ret;
}
+static const char *
+format_find_closer(const char *pair, const char *pattern)
+{
+ int i, level = 0;
+ for (i = 0; pattern[i] != '\0'; i++) {
+ if (pattern[i] == pair[0]) {
+ level++;
+ } else {
+ if (pattern[i] == pair[1]) {
+ level--;
+ }
+ }
+ if (level == 0) {
+ return &pattern[i];
+ }
+ }
+ return NULL;
+}
+
+/* Recursively expand the expression into the output buffer, adding any entries
+ * 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,
+ const char *fmt,
+ char *outbuf, int outbuf_len,
+ char ***visited_ndns,
+ PRBool literal)
+{
+ int i, j;
+ int exp_len, level;
+ const char *fmtstart, *fmtend, *match, *attribute;
+ char *tmp;
+ char exp[outbuf_len * 2];
+ const char *default_value, *alternate_value;
+ size_t spn;
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "expanding %s\"%s\"%s\n",
+ literal ? "" : "%{", fmt, literal ? "" : "%{");
+
+ /* First, expand any subexpressions. */
+ level = 0;
+ i = 0;
+ j = 0;
+ while (fmt[i] != '\0') {
+ switch (fmt[i]) {
+ case '%':
+ /* This might be a subexpression, or an escaped
+ * character. */
+ switch (fmt[i + 1]) {
+ case '%':
+ /* It's just an escaped "%". */
+ exp[j++] = '%';
+ i += 2;
+ continue;
+ break;
+ case '{':
+ /* Find the beginning of the subexpression. */
+ fmtstart = fmt + i;
+ /* 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");
+ return -1;
+ } else {
+ /* Mark the first character after the
+ * subexpression. */
+ fmtend = match + 1;
+ /* 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");
+ return -1;
+ }
+ memcpy(tmp, fmtstart + 2,
+ fmtend - fmtstart - 3);
+ tmp[fmtend - fmtstart - 3] = '\0';
+ /* Recursively expand the
+ * subexpression. */
+ exp_len = format_expand(pb, e,
+ tmp,
+ exp + j,
+ sizeof(exp) - j,
+ visited_ndns,
+ FALSE);
+ 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");
+ return -1;
+ } else {
+ /* It fit, so keep going. */
+ i = (match + 1) - fmt;
+ j += exp_len;
+ }
+ }
+ continue;
+ break;
+ }
+ break;
+ default:
+ /* Default is just a literal character. */
+ exp[j++] = fmt[i++];
+ break;
+ }
+ }
+ exp[j] = '\0';
+
+ if (literal) {
+ /* It's a literal string, so we're actually done. */
+ i = strlen(exp);
+ if (i <= outbuf_len) {
+ memcpy(outbuf, exp, i);
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "expanded to \"%s\"\n", exp);
+ return i;
+ } else {
+ /* It's an expression, so evaluate it. */
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "looking up simple expression \%\{\"%s\"}\n", exp);
+ /* Check if it uses a default/alternate value. */
+ spn = strcspn(exp, ":");
+ if (spn == strlen(exp)) {
+ /* Simple expression: expect it to be a single-valued
+ * attribute. */
+ tmp = format_single(pb, e, exp, visited_ndns);
+ if (tmp != NULL) {
+ /* Copy the string to the output buffer if
+ * there's space for it. */
+ i = strlen(tmp);
+ if (i <= outbuf_len) {
+ memcpy(outbuf, tmp, i);
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "expanded to \"%s\"\n", tmp);
+ free(tmp);
+ /* Return the length of the expanded
+ * expression. */
+ return i;
+ } else {
+ /* No value found? FAIL. */
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "no value for \"%s\"\n", exp);
+ return -1;
+ }
+ } else {
+ /* Make a copy of the attribute name. */
+ exp[spn] = '\0';
+ attribute = exp;
+ alternate_value = NULL;
+ default_value = NULL;
+ /* Figure out if there's an alternate or default value
+ * given. */
+ switch (exp[spn + 1]) {
+ case '+':
+ alternate_value = exp + spn + 2;
+ break;
+ case '-':
+ default_value = exp + spn + 2;
+ break;
+ default:
+ default_value = exp + spn + 1;
+ break;
+ }
+ /* Retrieve the value. */
+ tmp = format_single(pb, e, attribute, visited_ndns);
+ if (tmp == NULL) {
+ /* The attribute is undefined, or we're
+ * treating it as if it is. */
+ if (default_value != NULL) {
+ /* Supply the default value. */
+ i = strlen(default_value);
+ if (i <= outbuf_len) {
+ memcpy(outbuf, default_value,
+ i);
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "expanded to \"%s\"\n", default_value);
+ return i;
+ } else {
+ /* No value, and no default: FAIL. */
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "failed to expand: no valid value, no default\n");
+ return -1;
+ }
+ } else {
+ /* There's no value defined (or it's
+ * multi-valued, which is usually trouble). */
+ if (alternate_value != NULL) {
+ /* Supply the alternate value. */
+ i = strlen(alternate_value);
+ if (i <= outbuf_len) {
+ memcpy(outbuf, alternate_value,
+ i);
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "expanded to \"%s\"\n", alternate_value);
+ free(tmp);
+ return i;
+ } else {
+ /* Supply the looked-up value. */
+ i = strlen(tmp);
+ if (i <= outbuf_len) {
+ memcpy(outbuf, tmp, i);
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ "expanded to \"%s\"\n", tmp);
+ free(tmp);
+ return i;
+ }
+ }
+ }
+ }
+}
+
+static char *
+format_format(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);
+ if (i < sizeof(buf)) {
+ buf[i] = '\0';
+ return strdup(buf);
+ } else {
+ return NULL;
+ }
+}
+
char *
format_get_data(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
char ***visited_ndns)