Blame src/driver/toks_driver_ctx.c

2420c2
/*********************************************************/
2420c2
/*  toksvc: a framework-native token broker service      */
2420c2
/*  Copyright (C) 2020  Z. Gilboa                        */
2420c2
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
2420c2
/*********************************************************/
2420c2
2420c2
#include <ntapi/ntapi.h>
2420c2
#include <ntapi/nt_atomic.h>
2420c2
2420c2
#include <stdint.h>
2420c2
2420c2
#include <toksvc/toksvc.h>
2420c2
#include "toksvc_init_impl.h"
2420c2
#include "toksvc_nolibc_impl.h"
2420c2
2420c2
#define ARGV_DRIVER
2420c2
2420c2
#include "toksvc_version.h"
2420c2
#include "toksvc_daemon_impl.h"
2420c2
#include "toksvc_dprintf_impl.h"
2420c2
#include "toksvc_driver_impl.h"
2420c2
#include "argv/argv.h"
2420c2
2420c2
/* pty integration */
2420c2
#include <psxtypes/section/freestd.h>
2420c2
2420c2
__attr_section_decl__(".freestd")
2420c2
static const nt_tty_affiliation tty_affiliation
2420c2
	__attr_section__(".freestd")
2420c2
	= NT_TTY_AFFILIATION_DEFAULT;
2420c2
2420c2
/* ntapi accessor table */
2420c2
const ntapi_vtbl * toks_ntapi;
2420c2
2420c2
/* daemon */
2420c2
static struct toks_daemon_ctx toks_daemon_ctx;
2420c2
2420c2
/* package info */
2420c2
static const struct toks_source_version toks_src_version = {
2420c2
	TOKS_TAG_VER_MAJOR,
2420c2
	TOKS_TAG_VER_MINOR,
2420c2
	TOKS_TAG_VER_PATCH,
2420c2
	TOKSVC_GIT_VERSION
2420c2
};
2420c2
2420c2
struct toks_driver_ctx_alloc {
2420c2
	struct argv_meta *		meta;
2420c2
	struct toks_driver_ctx_impl	ctx;
2420c2
	uint64_t			guard;
2420c2
};
2420c2
2420c2
struct toks_split_vector {
2420c2
	char **		targv;
2420c2
	char **		eargv;
2420c2
};
2420c2
2420c2
static uint32_t toks_argv_flags(uint32_t flags)
2420c2
{
2420c2
	uint32_t ret = ARGV_CLONE_VECTOR;
2420c2
2420c2
	if (flags & TOKS_DRIVER_VERBOSITY_NONE)
2420c2
		ret |= ARGV_VERBOSITY_NONE;
2420c2
2420c2
	if (flags & TOKS_DRIVER_VERBOSITY_ERRORS)
2420c2
		ret |= ARGV_VERBOSITY_ERRORS;
2420c2
2420c2
	if (flags & TOKS_DRIVER_VERBOSITY_STATUS)
2420c2
		ret |= ARGV_VERBOSITY_STATUS;
2420c2
2420c2
	return ret;
2420c2
}
2420c2
2420c2
static int toks_driver_usage(
2420c2
	const char *			program,
2420c2
	const char *			arg,
2420c2
	const struct argv_option **	optv,
2420c2
	struct argv_meta *		meta)
2420c2
{
2420c2
	char header[512];
2420c2
2420c2
	snprintf(header,sizeof(header),
2420c2
		"Usage: %s [options] <file>...\n" "Options:\n",
2420c2
		program);
2420c2
2420c2
	argv_usage(STDOUT_FILENO,header,optv,arg);
2420c2
	argv_free(meta);
2420c2
2420c2
	return TOKS_USAGE;
2420c2
}
2420c2
2420c2
static struct toks_driver_ctx_impl * toks_driver_ctx_alloc(
2420c2
	struct argv_meta *		meta,
2420c2
	const struct toks_common_ctx *	cctx)
2420c2
{
2420c2
	struct toks_driver_ctx_alloc *	ictx;
2420c2
	size_t				size;
2420c2
	nt_runtime_data *		rtdata;
2420c2
2420c2
	if (ntapi->tt_get_runtime_data(&rtdata,0))
2420c2
		return 0;
2420c2
2420c2
	size =  sizeof(struct toks_driver_ctx_alloc);
2420c2
2420c2
	if (!(ictx = calloc(1,size)))
2420c2
		return 0;
2420c2
2420c2
	if (cctx)
2420c2
		memcpy(&ictx->ctx.cctx,cctx,sizeof(*cctx));
2420c2
2420c2
	ictx->meta = meta;
2420c2
	ictx->ctx.rtdata = rtdata;
2420c2
	return &ictx->ctx;
2420c2
}
2420c2
2420c2
static int toks_get_driver_ctx_fail(struct argv_meta * meta)
2420c2
{
2420c2
	argv_free(meta);
2420c2
	return -1;
2420c2
}
2420c2
2420c2
#define TOKS_SARGV_ELEMENTS		1024
2420c2
2420c2
static int toks_split_argv(
2420c2
	char **				argv,
2420c2
	struct toks_split_vector *	sargv)
2420c2
{
2420c2
	ptrdiff_t	argc;
2420c2
	char **		parg;
2420c2
2420c2
	/* argc */
2420c2
	for (parg=argv; *parg; )
2420c2
		parg++;
2420c2
2420c2
	if ((argc = parg - argv) >= TOKS_SARGV_ELEMENTS)
2420c2
		return -1;
2420c2
2420c2
	/* clone argv into targv */
2420c2
	ntapi->tt_aligned_block_memset(
2420c2
		(uintptr_t *)sargv->targv,
2420c2
		0,TOKS_SARGV_ELEMENTS*sizeof(char *));
2420c2
2420c2
	ntapi->tt_aligned_block_memcpy(
2420c2
		(uintptr_t *)sargv->targv,
2420c2
		(uintptr_t *)argv,
2420c2
		argc*sizeof(char *));
2420c2
2420c2
	/* eargv */
2420c2
	for (parg=sargv->targv; *parg; parg++) {
2420c2
		if (!(strcmp(*parg,"-e")) || !(strcmp(*parg,"--exec"))) {
2420c2
			sargv->eargv = &argv[parg-sargv->targv];
2420c2
			sargv->eargv++;
2420c2
			*parg = 0;
2420c2
			return 0;
2420c2
		}
2420c2
	}
2420c2
2420c2
	return 0;
2420c2
}
2420c2
2420c2
int toks_get_driver_ctx(
2420c2
	char **				argv,
2420c2
	char **				envp,
2420c2
	uint32_t			flags,
2420c2
	struct toks_driver_ctx **	pctx)
2420c2
{
2420c2
	struct toks_driver_ctx_impl *	ctx;
2420c2
	struct toks_common_ctx		cctx;
2420c2
	struct toks_split_vector	sargv;
2420c2
	const struct argv_option *	optv[TOKS_OPTV_ELEMENTS];
2420c2
	struct argv_meta *		meta;
2420c2
	struct argv_entry *		entry;
2420c2
	const char *			program;
2420c2
	char *				targv[TOKS_SARGV_ELEMENTS];
2420c2
2420c2
	(void)envp;
2420c2
2420c2
	if (toks_init())
2420c2
		return -1;
2420c2
2420c2
	argv_optv_init(toks_default_options,optv);
2420c2
2420c2
	sargv.targv = targv;
2420c2
	sargv.eargv = 0;
2420c2
2420c2
	if (toks_split_argv(argv,&sargv))
2420c2
		return -1;
2420c2
2420c2
	if (!(meta = argv_get(
2420c2
			sargv.targv,optv,
2420c2
			toks_argv_flags(flags),
2420c2
			STDERR_FILENO)))
2420c2
		return -1;
2420c2
2420c2
	program = argv_program_name(argv[0]);
2420c2
	memset(&cctx,0,sizeof(cctx));
2420c2
	cctx.drvflags = flags;
2420c2
	cctx.eargv = sargv.eargv;
2420c2
2420c2
	if (!argv[1] && (flags & TOKS_DRIVER_VERBOSITY_USAGE))
2420c2
		return toks_driver_usage(program,0,optv,meta);
2420c2
2420c2
	for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
2420c2
		if (entry->fopt) {
2420c2
			switch (entry->tag) {
2420c2
				case TAG_HELP:
2420c2
					if (flags & TOKS_DRIVER_VERBOSITY_USAGE)
2420c2
						return toks_driver_usage(program,entry->arg,optv,meta);
2420c2
2420c2
				case TAG_VERSION:
2420c2
					cctx.drvflags |= TOKS_DRIVER_VERSION;
2420c2
					break;
2420c2
2420c2
				case TAG_DAEMON:
2420c2
					if (!strcmp("always",entry->arg))
2420c2
						cctx.drvflags |= TOKS_DRIVER_DAEMON_ALWAYS;
2420c2
2420c2
					else if (!strcmp("never",entry->arg))
2420c2
						cctx.drvflags |= TOKS_DRIVER_DAEMON_NEVER;
2420c2
2420c2
					break;
2420c2
2420c2
				case TAG_SYSROOT:
2420c2
					cctx.sysroot = entry->arg;
2420c2
					break;
2420c2
			}
2420c2
		} else
2420c2
			/* strict */
2420c2
			return toks_driver_usage(program,0,optv,meta);
2420c2
	}
2420c2
2420c2
	if (cctx.sysroot && toks_open_dir(&cctx.hroot,0,cctx.sysroot,false)) {
2420c2
		if (flags & TOKS_DRIVER_VERBOSITY_ERRORS)
2420c2
			toks_dprintf(STDERR_FILENO,
2420c2
				"%s: error: could not open sysroot directory '%s'",
2420c2
				program,cctx.sysroot);
2420c2
		return toks_get_driver_ctx_fail(meta);
2420c2
	}
2420c2
2420c2
	if (!(ctx = toks_driver_ctx_alloc(meta,&cctx)))
2420c2
		return toks_get_driver_ctx_fail(meta);
2420c2
2420c2
	if (toks_daemon_init(&toks_daemon_ctx,cctx.drvflags))
2420c2
		return toks_get_driver_ctx_fail(meta);
2420c2
2420c2
	ctx->ctx.program	= program;
2420c2
	ctx->ctx.cctx		= &ctx->cctx;
2420c2
2420c2
	*pctx = &ctx->ctx;
2420c2
	return TOKS_OK;
2420c2
}
2420c2
2420c2
static void toks_free_driver_ctx_impl(struct toks_driver_ctx_alloc * ictx)
2420c2
{
2420c2
	argv_free(ictx->meta);
2420c2
	free(ictx);
2420c2
}
2420c2
2420c2
void toks_free_driver_ctx(struct toks_driver_ctx * ctx)
2420c2
{
2420c2
	struct toks_driver_ctx_alloc *	ictx;
2420c2
	uintptr_t			addr;
2420c2
2420c2
	if (ctx) {
2420c2
		addr = (uintptr_t)ctx - offsetof(struct toks_driver_ctx_impl,ctx);
2420c2
		addr = addr - offsetof(struct toks_driver_ctx_alloc,ctx);
2420c2
		ictx = (struct toks_driver_ctx_alloc *)addr;
2420c2
		toks_free_driver_ctx_impl(ictx);
2420c2
	}
2420c2
}
2420c2
2420c2
const struct toks_source_version * toks_source_version(void)
2420c2
{
2420c2
	return &toks_src_version;
2420c2
}