Index: libabac/abac.c
===================================================================
--- libabac/abac.c	(revision 202a7f97d0dc5cb5eb2b43332f0711eafa4d7170)
+++ libabac/abac.c	(revision 8bd77b59df89993868555d3b87f91fc241b09228)
@@ -1,1 +1,296 @@
-abac_pl.c
+
+/* abac.c using prolog */
+
+#include <assert.h>
+#include <err.h>
+#include <glob.h>
+
+#include <chunk.h>
+
+#include "abac_internal.h"
+
+#include "abac_pl_yap.h"
+#include "abac_util.h"
+#include "abac_verifier.h"
+
+static int debug=0;
+
+struct _abac_context_t {
+    abac_pl_t *pl;
+};
+
+/**
+ * Init the library.
+ */
+void libabac_init(void) {
+    void libabac_deinit(void);
+    static int has_been_init = 0;
+
+    // called every time a context is created, so only do it once
+    if (!has_been_init) {
+        abac_verifier_init();
+        atexit(libabac_deinit);
+        has_been_init = 1;
+    }
+}
+
+/**
+ * Deinit the library.
+ */
+void libabac_deinit(void) {
+    abac_verifier_deinit();
+}
+
+/**
+ * Create a new abac context.
+ */
+abac_context_t *abac_context_new(void) {
+    libabac_init();
+
+    abac_context_t *ctx = abac_xmalloc(sizeof(abac_context_t));
+    ctx->pl = abac_pl_new();
+    return ctx;
+}
+
+/**
+ * Deep copy an abac context. -- XXX dummy stub
+ */
+abac_context_t *abac_context_dup(abac_context_t *ctx) {
+    assert(ctx != NULL);
+    abac_context_t *dup = abac_xmalloc(sizeof(abac_context_t));
+    return dup;
+}
+
+
+/**
+ * Free an abac context.
+ */
+void abac_context_free(abac_context_t *ctx) {
+    assert(ctx != NULL);
+
+    abac_pl_free(ctx->pl);
+    free(ctx);
+}
+
+/**
+ * Load an ID cert from an abac_id_t.
+ */
+int abac_context_load_id_id(abac_context_t *ctx, abac_id_t *id) {
+    assert(ctx != NULL); assert(id);
+    abac_id_credential_t *id_cert=NULL;
+    int ret = abac_verifier_load_id_id(id,&id_cert);
+    if(id_cert) {
+        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
+    }
+    return ret;
+}
+
+/**
+ * Load an ID cert from a file.
+ */
+int abac_context_load_id_file(abac_context_t *ctx, char *filename) {
+    assert(ctx != NULL); assert(filename != NULL);
+    abac_id_credential_t *id_cert=NULL;
+    int ret = abac_verifier_load_id_file(filename,&id_cert);
+    if(id_cert) {
+        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
+    }
+    return ret;
+}
+
+/**
+ * Load an ID cert from a chunk.
+ */
+int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert) {
+    assert(ctx != NULL);
+    abac_id_credential_t *id_cert=NULL;
+    chunk_t cert_chunk = { cert.ptr, cert.len };
+    int ret=abac_verifier_load_id_chunk(cert_chunk,&id_cert);
+    if(id_cert) {
+        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
+    }
+    return ret;
+}
+
+/**
+ * Load an attribute cert from an abac_attribute_t.
+ */
+int abac_context_load_attribute_attribute(abac_context_t *ctx, abac_attribute_t *ptr)
+{
+/* XXX */
+    int ret=0;
+    return ret;
+}
+
+/**
+ * Load an attribute cert from a file.
+ */
+int abac_context_load_attribute_file(abac_context_t *ctx, char *filename) {
+    int ret, add_ret;
+    abac_credential_t *cred;
+
+    assert(ctx != NULL); assert(filename != NULL);
+
+    ret = abac_verifier_load_attribute_cert_file(filename, &cred);
+    if (ret == ABAC_CERT_SUCCESS) {
+        add_ret = abac_pl_add_credential(ctx->pl, cred);
+        assert(add_ret != ABAC_PL_CRED_INVALID);
+    }
+
+    return ret;
+}
+
+/**
+ * Load an attribute cert from a chunk.
+ */
+int abac_context_load_attribute_chunk(abac_context_t *ctx, abac_chunk_t cert) {
+    int ret, add_ret;
+    abac_credential_t *cred;
+
+    assert(ctx != NULL);
+
+    chunk_t cert_chunk = { cert.ptr, cert.len };
+
+    ret = abac_verifier_load_attribute_cert_chunk(cert_chunk, &cred);
+    if (ret == ABAC_CERT_SUCCESS) {
+        add_ret = abac_pl_add_credential(ctx->pl, cred);
+        assert(add_ret != ABAC_PL_CRED_INVALID);
+        abac_credential_free(cred);
+    }
+
+    return ret;
+}
+
+#define ID_PAT "/*_ID.{der,pem}"
+#define ATTR_PAT "/*_attr.der"
+#define ATTR_FILE_PAT "/*_attr.file"
+
+/**
+ * Load a directory full of certs.
+ */
+void abac_context_load_directory(abac_context_t *ctx, char *path) {
+    char *glob_pat;
+    glob_t glob_buf;
+    int i, ret;
+
+    assert(ctx != NULL); assert(path != NULL);
+
+    int dirlen = strlen(path);
+    glob_pat = abac_xmalloc(dirlen + sizeof(ID_PAT));
+    memcpy(glob_pat, path, dirlen);
+
+    // first load ID certs
+    memcpy(glob_pat + dirlen, ID_PAT, sizeof(ID_PAT));
+    glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error
+    for (i = 0; i < glob_buf.gl_pathc; ++i) {
+        char *cert_file = glob_buf.gl_pathv[i];
+
+        if(debug) printf("--> ID cert... %s\n", cert_file);
+        ret = abac_context_load_id_file(ctx, cert_file);
+        if (ret != ABAC_CERT_SUCCESS)
+            warnx("Couldn't load ID cert %s", cert_file);
+    }
+    globfree(&glob_buf);
+
+    // then load attr certs
+    memcpy(glob_pat + dirlen, ATTR_PAT, sizeof(ATTR_PAT));
+    glob(glob_pat, 0, NULL, &glob_buf); // TODO check for error
+    for (i = 0; i < glob_buf.gl_pathc; ++i) {
+        char *cert_file = glob_buf.gl_pathv[i];
+
+        if(debug) printf("--> attr file... %s\n", cert_file);
+        ret = abac_context_load_attribute_file(ctx, cert_file);
+        if (ret != ABAC_CERT_SUCCESS)
+            warnx("Couldn't load attribute cert %s", cert_file);
+    }
+    globfree(&glob_buf);
+
+    free(glob_pat);
+}
+
+/**
+ * Run a query on the data in an abac context. Returns a NULL-terminated array
+ * of abac_credential_t. Success/failure in *success.
+ * queryfor(either role or oset), with(either keyid or object type)
+ */
+abac_credential_t **abac_context_query(abac_context_t *ctx, char *queryfor, char *with, int *success) {
+    if(debug) {
+         printf("abac_context_query about(%s) with(%s)\n", queryfor, with);
+    }
+    abac_credential_t **credentials = NULL, *cur;
+    assert(ctx != NULL); assert(queryfor != NULL);
+    assert(with != NULL); assert(success != NULL);
+
+    abac_stack_t *result = abac_pl_query(ctx->pl, queryfor, with);
+
+    int size = abac_stack_size(result);
+    if (size > 0) {
+        *success = 1;
+    } else {
+    // XXX NOT SURE YET..
+    // return partial proof
+	*success = 0;
+    }
+
+    // make the array (leave space to NULL terminate it)
+    //      n.b., even if the list is empty, we still return an array that
+    //            only contains the NULL terminator
+    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
+    int i = 0;
+    if(size) {
+        while(i<size) { 
+            cur=(abac_credential_t *) abac_stack_pop(result);
+            credentials[i++] = cur;
+        } 
+    }
+    credentials[i] = NULL;
+
+    if(result)
+        abac_stack_free(result);
+
+    return credentials;
+}
+
+/**
+ * A NULL-terminated array of all the credentials in the context.
+ */
+abac_credential_t **abac_context_credentials(abac_context_t *ctx) {
+    abac_credential_t **credentials = NULL, *cur;
+    assert(ctx != NULL);
+
+    abac_stack_t *result = abac_pl_credentials(ctx->pl);
+    int size = abac_stack_size(result);
+
+    // make the array (leave space to NULL terminate it)
+    //      n.b., even if the list is empty, we still return an array that
+    //            only contains the NULL terminator
+    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
+    int i = 0;
+    if(size) {
+        while(i<size) { 
+            cur=(abac_credential_t *) abac_stack_pop(result);
+            /* if not in there yet, add into it */
+            credentials[i++] = cur;
+        } 
+    }
+    credentials[i] = NULL;
+
+    if(result)
+        abac_stack_free(result);
+    return credentials;
+}
+
+/**
+ * Frees a NULL-terminated list of credentials.
+ */
+void abac_context_credentials_free(abac_credential_t **credentials) {
+    int i;
+
+    if (credentials == NULL)
+        return;
+
+    for (i = 0; credentials[i] != NULL; ++i)
+        abac_credential_free(credentials[i]);
+    free(credentials);
+}
+
