/*
 * A simple querier, for testing libqick.a.
 *
 * usage: simpleq -q "arbitrary query string"
 *    or: simpleq -i <file_containing_arbitrary_queries
 *    or: simpleq -m field value
 *    or: simpleq -f field value return-field
 */

#include <stdio.h>
#include <string.h>
#include "qick.h"

static char rcsid[] = "$Id: simpleq.c,v 2.2 2000/08/18 19:27:34 dgc Exp $";

char *A0;

main(int ac, char *av[])
{
	qick_t		*qh;
	qir_t		*qir;
	char		*s, qbuf[1024];
	int		 i;
	qip_t		*dpol, *check;
	qit_t		*qt;

	/* My name */
	if ((A0 = strrchr(av[0], '/')) == NULL)
		A0 = av[0];
	else
		++A0;

	/* Check cmdline */
	if (ac == 1 || !strcmp(av[1], "-h")) {
		fprintf(stderr, "usage: %s -q \"arbitrary query string\"\n",
			A0);
		fprintf(stderr,
			"   or: %s -i <file_containing_arbitrary_queries\n",
			A0);
		fprintf(stderr, "   or: %s -m field value\n", A0);
		fprintf(stderr, "   or: %s -f field value return-field\n", A0);
		exit(4);
	}

	/* Initialize the library. */
	if ((qh = qick_init()) == NULL) {
		fprintf(stderr, "%s: cannot initialize qick library\n", A0);
		exit(2);
	}

	qi_server(qh, QI_SERVER);

	/* Get a handle on the default policy. */
	dpol = qip_default(qh);

	/* Create a new policy head, and name it "check". */
	check = qip_new(qh, "check");

	/*
	 * Create a policy term, linked to the default policy.
	 */
	qt = qip_extend(check, NULL);
	qit_setlink(qt, dpol);

	/*
	 * Get a new policy term.  Make the new term compare
	 * the alias with "dgc".
	 */
	qt = qip_extend(check, NULL);
	qit_setmatch(qt, "alias", "^dgc$", QI_POLICY_RE_BASIC, NULL, 0);

	/*
	 * Logically OR this with the default policy, and concatenate them as
	 * the check policy.  Net effect: if user is per-default legit,
	 * OR if his alias is "dgc", he passes the policy.
	 */
	qt = qip_extend(check, NULL);
	qit_setop(qt, QI_POLICY_OR);

	/* Check cmdline */
	if (!strcmp(av[1], "-q")) {
		qir = qi_lookup(qh, av[2]);
		if (qir == NULL) {
			fprintf(stderr, "null\n");
			exit(5);
		}
		qir_trace(qir);
		for (i = 3; av[i] != NULL; ++i) {
			s = qi_field(qir, av[i]);
			fprintf(stderr, "%s\t= %s\n", av[i], S(s));
			fflush(stderr);
		}

		/* Execute the policy, tracing the execution on stderr. */
		i = qip_trace(check, qir);

		fprintf(stderr, "policy results: %s\n",
				i == QI_POLICY_TRUE ? "true" :
				i == QI_POLICY_FALSE ? "false" :
				i == QI_POLICY_OVERFLOW ? "over" :
				i == QI_POLICY_UNDERFLOW ? "under" :
				"???");
	} else if (strcmp(av[1], "-i") == 0) {
		printf("query> ");
		while (fgets(qbuf, 1023, stdin) != NULL) {
			if (*qbuf == '\0') {
				printf("\nquery> ");
				continue;
			}
			qir = qi_lookup(qh, qbuf);
			if (qir == NULL) {
				fprintf(stderr, "null\n");
				printf("\nquery> ");
				continue;
			}
			qir_trace(qir);

			/* Execute the policy, tracing the execution */
			i = qip_trace(check, qir);

			fprintf(stderr, "policy results: %s\n",
					i == QI_POLICY_TRUE ? "true" :
					i == QI_POLICY_FALSE ? "false" :
					i == QI_POLICY_OVERFLOW ? "over" :
					i == QI_POLICY_UNDERFLOW ? "under" :
					"???");

			qir_free(qir);
			printf("\nquery> ");
		}
	} else if (strcmp(av[1], "-m") == 0) {
		qir = qi_lookup(qh, "query %s=%s", av[2], av[3]);
		if (qir == NULL) {
			fprintf(stderr, "null\n");
			exit(5);
		}
		fprintf(stderr, "qir = %08x\n", qir);
		qir_trace(qir);
	} else if (strcmp(av[1], "-f") == 0) {
		s = qi_lookup_simple(qh, av[2], av[3], av[4]);
		fprintf(stderr, "query %s=%s return %s: %s\n",
			av[2], av[3], av[4], S(s));
	}

	exit(0);
}

