Blob Blame History Raw
/*********************************************************/
/*  toksvc: a framework-native token broker service      */
/*  Copyright (C) 2020  Z. Gilboa                        */
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
/*********************************************************/

#include <ntapi/ntapi.h>
#include <stdio.h>
#include <unistd.h>

#include <toksvc/toksvc.h>
#include "toksvc_init_impl.h"
#include "toksvc_driver_impl.h"
#include "toksvc_dprintf_impl.h"
#include "toksvc_nolibc_impl.h"
#include "toksvc_log_impl.h"

#ifndef TOKS_DRIVER_FLAGS
#define TOKS_DRIVER_FLAGS	TOKS_DRIVER_VERBOSITY_ERRORS \
				| TOKS_DRIVER_DAEMON_ALWAYS   \
				| TOKS_DRIVER_VERBOSITY_USAGE
#endif

static const char vermsg[] = "%s%s%s (git://midipix.org/toksvc): "
			     "version %s%d.%d.%d%s.\n"
			     "[commit reference: %s%s%s]\n";

static const char * const toks_ver_color[6] = {
		"\x1b[1m\x1b[35m","\x1b[0m",
		"\x1b[1m\x1b[32m","\x1b[0m",
		"\x1b[1m\x1b[34m","\x1b[0m"
};

static const char * const toks_ver_plain[6] = {
		"","",
		"","",
		"",""
};

static ssize_t toks_version(struct toks_driver_ctx * dctx)
{
	const struct toks_source_version * verinfo;
	const char * const * verclr;

	verinfo = toks_source_version();
	verclr  = isatty(STDOUT_FILENO) ? toks_ver_color : toks_ver_plain;

	return toks_dprintf(
			STDOUT_FILENO,vermsg,
			verclr[0],dctx->program,verclr[1],
			verclr[2],verinfo->major,verinfo->minor,
			verinfo->revision,verclr[3],
			verclr[4],verinfo->commit,verclr[5]);
}

static int toks_exit(struct toks_driver_ctx * dctx, int nerrors)
{
	toks_free_driver_ctx(dctx);
	return nerrors ? 2 : 0;
}

int toks_main(char ** argv, char ** envp)
{
	int				ret;
	int32_t				status;
	struct toks_driver_ctx *	dctx;
	struct toks_token_string	toks;

	if ((ret = toks_init()))
		return ret;

	if ((ret = toks_get_driver_ctx(argv,envp,TOKS_DRIVER_FLAGS,&dctx)))
		return (ret == TOKS_USAGE)
			? !argv || !argv[0] || !argv[1]
			: 2;

	if (dctx->cctx->drvflags & TOKS_DRIVER_VERSION)
		if ((toks_version(dctx)) < 0)
			return toks_exit(dctx,2);

	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_ACQUIRE) {
		ret = (status = toks_client_acquire(dctx))
			? 2 : 0;

		switch (status) {
			case NT_STATUS_SUCCESS:
				break;

			case NT_STATUS_TIMEOUT:
				toks_dprintf(STDERR_FILENO,
					"%s: the operataion timed out [0x%x].\n",
					toks_log_basename(argv[0]),status);
				break;

			default:
				toks_dprintf(STDERR_FILENO,
					"%s: the operataion has failed [0x%x].\n",
					toks_log_basename(argv[0]),status);
		}

		if (ret == 0) {
			toks_client_token_to_str(dctx,&toks);
			toks_dprintf(STDOUT_FILENO,"%s\n",toks.token);
		}
	}

	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_RELEASE) {
		ret = toks_client_release(dctx)
			? 2 : 0;

		if (ret == 0) {
			toks_client_token_to_str(dctx,&toks);
			toks_dprintf(STDOUT_FILENO,"token %s has been released\n",toks.token);
		}

		if (ret == 2) {
			toks_dprintf(STDERR_FILENO,"error: invalid token");
		}
	}

	if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_ABORT) {
		ret = (status = toks_service_abort(dctx))
			? 2 : 0;

		switch (status) {
			case NT_STATUS_SUCCESS:
				toks_dprintf(STDERR_FILENO,
					"%s: the server responded with no error.\n",
					toks_log_basename(argv[0]),status);
				break;

			case NT_STATUS_ACCESS_DENIED:
				toks_dprintf(STDERR_FILENO,
					"%s: the abort operataion timed (access denied) [0x%x].\n",
					toks_log_basename(argv[0]),status);
				break;

			default:
				toks_dprintf(STDERR_FILENO,
					"%s: the abort operataion failed ",
					"(check the system's documentation) [0x%x].",
					toks_log_basename(argv[0]),status);
		}
	}

	return (dctx->cctx->drvflags & TOKS_DRIVER_MODE_SERVER)
		? NT_STATUS_SERVICE_NOTIFICATION
		: toks_exit(dctx,ret);
}