Blame src/service/toks_service_start.c

1a07be
/*********************************************************/
1a07be
/*  toksvc: a framework-native token broker service      */
d91fa0
/*  Copyright (C) 2020  SysDeer Technologies, LLC        */
1a07be
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
1a07be
/*********************************************************/
1a07be
1a07be
#include <psxtypes/psxtypes.h>
1a07be
#include <ntapi/ntapi.h>
1a07be
1a07be
#include <toksvc/toksvc.h>
1a07be
#include "toksvc_driver_impl.h"
1a07be
#include "toksvc_daemon_impl.h"
1a07be
b59b0a
#define TOKS_STR(x)  #x
b59b0a
#define TOKS_XSTR(x) TOKS_STR(x)
b59b0a
b59b0a
static char toks_service_image[] = TOKS_XSTR(TOKS_SERVICE_IMAGE);
1a07be
1a07be
static int32_t toks_spawn_child_exit_code(void * hprocess)
1a07be
{
1a07be
	nt_process_basic_information pbi;
1a07be
1a07be
	if (ntapi->zw_query_information_process(
1a07be
			hprocess,
1a07be
			NT_PROCESS_BASIC_INFORMATION,
1a07be
			&pbi,sizeof(pbi),
1a07be
			&(uint32_t){0}))
1a07be
		return NT_STATUS_GENERIC_COMMAND_FAILED;
1a07be
1a07be
	return pbi.exit_status;
1a07be
}
1a07be
1a07be
static int toks_spawn_impl(
1a07be
	struct toks_driver_ctx *        dctx,
1a07be
	struct toks_common_ctx *        cctx,
1a07be
	int                             ntokens,
1a07be
	int32_t                         ctrlpid,
1a07be
	int32_t                         csyspid)
1a07be
{
1a07be
	int32_t				status;
1a07be
	nt_spawn_process_params		sparams;
1a07be
	nt_runtime_data			rtctx;
1a07be
	nt_rtdata *			self;
1a07be
	char *				img;
1a07be
	void *				hroot;
1a07be
	void *				hlog;
1a07be
	const char *			logfile;
1a07be
	char **				pearg;
1a07be
	char *				eargv[10];
1a07be
	char				tokbuf[32];
1a07be
	char				pidbuf[32];
cd7e30
	char				logbuf[32];
2c8e4f
	char				guidstr[40];
8cf1b0
	void *				hduo[2];
1a07be
1a07be
	/* init */
1a07be
	self = toks_get_driver_rtdata(dctx);
1a07be
	img  = toks_service_image;
1a07be
1a07be
	if (!(hroot = cctx->hroot) && cctx->sysroot)
1a07be
		if ((status = toks_open_dir(&hroot,0,cctx->sysroot,false)))
1a07be
			return status;
1a07be
1a07be
	if (hroot && (img[0] == '/'))
1a07be
		img++;
1a07be
1a07be
	logfile = cctx->logfile;
1a07be
1a07be
	if (hroot && logfile && (logfile[0] == '/'))
1a07be
		logfile++;
1a07be
1a07be
	if (logfile && (status = toks_open_log_file(&hlog,hroot,logfile,false)))
1a07be
		return status;
1a07be
1a07be
	/* eargv */
1a07be
	pearg    = eargv;
1a07be
	*pearg++ = img;
1a07be
1a07be
	ntapi->sprintf(tokbuf,"%d",ntokens);
1a07be
	*pearg++ = "-t";
1a07be
	*pearg++ = tokbuf;
1a07be
cd7e30
	ntapi->sprintf(logbuf,"%d",cctx->loglevel);
cd7e30
	*pearg++ = "-O";
cd7e30
	*pearg++ = logbuf;
cd7e30
2c8e4f
	if (cctx->uuid) {
0021e3
		toks_uuid_to_string(cctx->uuid,&guidstr);
2c8e4f
		*pearg++ = "-u";
2c8e4f
		*pearg++ = guidstr;
2c8e4f
	}
2c8e4f
1a07be
	if (ctrlpid) {
1a07be
		ntapi->sprintf(pidbuf,"%d",ctrlpid);
52fec3
		*pearg++ = "-l";
1a07be
		*pearg++ = pidbuf;
1a07be
	} else if (csyspid) {
1a07be
		ntapi->sprintf(pidbuf,"%d",csyspid);
52fec3
		*pearg++ = "-L";
1a07be
		*pearg++ = pidbuf;
1a07be
	}
1a07be
1a07be
	*pearg++ = 0;
1a07be
1a07be
	/* sparams */
1a07be
	ntapi->tt_aligned_block_memset(
1a07be
		&sparams,0,sizeof(sparams));
1a07be
1a07be
	sparams.rtctx    = &rtctx;
1a07be
	sparams.patharg  = img;
1a07be
	sparams.argv     = eargv;
1a07be
	sparams.envp     = self->envp;
1a07be
	sparams.hroot    = hroot ? hroot : self->hroot;
1a07be
1a07be
	if ((status = toks_open_file(&sparams.himage,hroot,img,true)))
1a07be
		return status;
1a07be
1a07be
	/* rtctx */
1a07be
	ntapi->tt_aligned_block_memset(
1a07be
		&rtctx,0,sizeof(rtctx));
1a07be
1a07be
	ntapi->tt_aligned_block_memcpy(
1a07be
		(uintptr_t *)&rtctx.cid_parent,
1a07be
		(uintptr_t *)&self->cid_self,
1a07be
		sizeof(nt_cid));
1a07be
1a07be
	rtctx.hlog  = hlog;
1a07be
	rtctx.hcwd  = self->hcwd;
1a07be
	rtctx.hroot = sparams.hroot;
1a07be
	rtctx.flags = self->flags | NT_RUNTIME_DATA_TTY_TOP_LEVEL;
1a07be
1a07be
	rtctx.dbg_level = 0;
1a07be
	rtctx.log_level = self->log_level;
1a07be
1a07be
	rtctx.hstdin      = NT_INVALID_HANDLE_VALUE;
1a07be
	rtctx.hstdout     = NT_INVALID_HANDLE_VALUE;
1a07be
	rtctx.hstderr     = NT_INVALID_HANDLE_VALUE;
1a07be
1a07be
	rtctx.stdin_type  = NT_FILE_TYPE_UNKNOWN;
1a07be
	rtctx.stdout_type = NT_FILE_TYPE_UNKNOWN;
1a07be
	rtctx.stderr_type = NT_FILE_TYPE_UNKNOWN;
1a07be
8cf1b0
	/* service synchronization */
8cf1b0
	if ((status = ntapi->tt_create_inheritable_event(
8cf1b0
			&rtctx.hsync,
8cf1b0
			NT_NOTIFICATION_EVENT,
8cf1b0
			NT_EVENT_NOT_SIGNALED)))
8cf1b0
		return status;
8cf1b0
1a07be
	/* hoppla */
1a07be
	status = ntapi->tt_spawn_native_process(&sparams);
1a07be
1a07be
	if (sparams.himage)
1a07be
		ntapi->zw_close(sparams.himage);
1a07be
1a07be
	if (status)
1a07be
		return status;
1a07be
1a07be
	/* child ready? */
1a07be
	if (!(sparams.eready.signal_state))
1a07be
		status = toks_spawn_child_exit_code(sparams.hprocess);
1a07be
8cf1b0
	/* service synchronization */
8cf1b0
	hduo[0] = sparams.hprocess;
8cf1b0
	hduo[1] = rtctx.hsync;
8cf1b0
8cf1b0
	ntapi->zw_wait_for_multiple_objects(
8cf1b0
		2,hduo,
8cf1b0
		NT_WAIT_ANY,
8cf1b0
		NT_SYNC_NON_ALERTABLE,
8cf1b0
		0);
8cf1b0
1a07be
	/* finalize */
1a07be
	ntapi->zw_close(sparams.hprocess);
1a07be
	ntapi->zw_close(sparams.hthread);
1a07be
1a07be
	/* all done */
1a07be
	return status;
1a07be
}
1a07be
1a07be
int32_t toks_service_start(
1a07be
	struct toks_common_ctx *    cctx,
1a07be
	int                         ntokens,
1a07be
	int32_t                     ctrlpid,
1a07be
	int32_t                     csyspid)
1a07be
{
1a07be
	int32_t                     status;
1a07be
	struct toks_driver_ctx *    dctx;
1a07be
	char *                      eargv[2];
1a07be
1a07be
	eargv[0] = "toksvc.driver";
1a07be
	eargv[1] = 0;
1a07be
1a07be
	status = toks_get_driver_ctx(eargv,0,TOKS_DRIVER_VERSION,&dctx);
1a07be
1a07be
	if (status == NT_STATUS_SUCCESS) {
1a07be
		status = toks_spawn_impl(dctx,cctx,ntokens,ctrlpid,csyspid);
1a07be
		toks_free_driver_ctx(dctx);
1a07be
	}
1a07be
1a07be
	return status;
1a07be
}