/*********************************************************/
/* 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 ssize_t toks_output_service_info(struct toks_service_info * svcinfo)
{
char guidstr[40];
toks_uuid_to_string(
&svcinfo->uuid,
&guidstr);
return toks_dprintf(STDOUT_FILENO,
"toks_uuid:%s\n"
"toks_syspid:%d\n"
"toks_systid:%d\n"
"toks_ctrlpid:%d\n"
"toks_csyspid:%d\n"
"toks_allocated:%d\n"
"toks_available:%d\n"
"toks_tused:%d\n"
"toks_tfree:%d\n"
"toks_loglevel:%d\n",
guidstr,
svcinfo->syspid,
svcinfo->systid,
svcinfo->ctrlpid,
svcinfo->csyspid,
svcinfo->allocated,
svcinfo->available,
svcinfo->tused,
svcinfo->tfree,
svcinfo->loglevel);
}
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;
struct toks_service_info svcinfo;
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);
}
}
if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_NTOKENS_GET) {
toks_dprintf(STDOUT_FILENO,
"toks_ntokens:%d\n",
toks_get_driver_ntokens(dctx));
}
if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_NTOKENS_SET) {
status = toks_service_ioctl(
dctx,TOKS_IOCTL_SET_TOKEN_COUNT,
&(uintptr_t){toks_get_driver_ntokens(dctx)},
0);
ret = status ? 2 : 0;
switch (status) {
case NT_STATUS_SUCCESS:
toks_dprintf(STDERR_FILENO,
"%s: the service's ntokens parameter "
"was successfully set to %d\n",
toks_log_basename(argv[0]),
toks_get_driver_ntokens(dctx));
break;
default:
toks_dprintf(STDERR_FILENO,
"%s: the TOKS_IOCTL_SET_TOKEN_COUNT "
"ioctl operataion has failed "
"(check the system's documentation) [0x%x].",
toks_log_basename(argv[0]),status);
}
}
if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_LOGLEVEL_GET) {
toks_dprintf(STDOUT_FILENO,
"toks_loglevel:%d\n",
dctx->cctx->loglevel);
}
if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_LOGLEVEL_SET) {
status = toks_service_ioctl(
dctx,TOKS_IOCTL_SET_LOG_LEVEL,
&(uintptr_t){dctx->cctx->loglevel},
0);
ret = status ? 2 : 0;
switch (status) {
case NT_STATUS_SUCCESS:
toks_dprintf(STDERR_FILENO,
"%s: the service's log-level parameter "
"was successfully set to %d\n",
toks_log_basename(argv[0]),
dctx->cctx->loglevel);
break;
default:
toks_dprintf(STDERR_FILENO,
"%s: the TOKS_IOCTL_SET_LOG_LEVEL "
"ioctl operataion has failed "
"(check the system's documentation) [0x%x].",
toks_log_basename(argv[0]),status);
}
}
if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_SVCINFO_GET) {
status = toks_client_query_service(dctx,&svcinfo);
ret = status ? 2 : 0;
switch (status) {
case NT_STATUS_SUCCESS:
toks_output_service_info(&svcinfo);
break;
default:
toks_dprintf(STDERR_FILENO,
"%s: the TOKS_IOCTL_GET_SERVICE_INFO "
"ioctl operataion has failed "
"(check the system's documentation) [0x%x].",
toks_log_basename(argv[0]),status);
}
}
if (dctx->cctx->drvflags & TOKS_DRIVER_ACTION_SVCINFO_LOG) {
status = toks_service_ioctl(dctx,TOKS_IOCTL_LOG_SERVICE_INFO,0,0);
ret = status ? 2 : 0;
switch (status) {
case NT_STATUS_SUCCESS:
toks_dprintf(STDERR_FILENO,
"%s: a service info log record "
"was successfully created\n",
toks_log_basename(argv[0]));
break;
default:
toks_dprintf(STDERR_FILENO,
"%s: the TOKS_IOCTL_LOG_SERVICE_INFO "
"ioctl operataion has 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);
}