Blame src/output/ntux_output_error.c

da20d8
/***********************************************************/
da20d8
/*  ntux: native translation und extension                 */
14ffae
/*  Copyright (C) 2016--2021  SysDeer Technologies, LLC    */
da20d8
/*  Released under GPLv2 and GPLv3; see COPYING.NTUX.      */
da20d8
/***********************************************************/
da20d8
da20d8
#include <stdio.h>
da20d8
#include <string.h>
da20d8
#include <unistd.h>
da20d8
#include <psxabi/sys_errno.h>
da20d8
da20d8
#include <ntux/ntux.h>
da20d8
#include "ntux_driver_impl.h"
da20d8
#include "ntux_nolibc_impl.h"
da20d8
#include "ntux_strerr_impl.h"
da20d8
da20d8
static const char aclr_reset[]   = "\x1b[0m";
da20d8
static const char aclr_bold[]    = "\x1b[1m";
da20d8
da20d8
static const char aclr_red[]     = "\x1b[31m";
da20d8
static const char aclr_green[]   = "\x1b[32m";
da20d8
static const char aclr_blue[]    = "\x1b[34m";
da20d8
static const char aclr_magenta[] = "\x1b[35m";
da20d8
da20d8
static const char * ntux_output_error_header(const struct ntux_error_info * erri)
da20d8
{
da20d8
	if (erri->eflags & NTUX_ERROR_CHILD)
da20d8
		return "exec error upon";
da20d8
da20d8
	else if (erri->eflags & NTUX_ERROR_TOP_LEVEL)
da20d8
		return "error logged in";
da20d8
da20d8
	else if (erri->eflags & NTUX_ERROR_NESTED)
da20d8
		return "< returned to >";
da20d8
da20d8
	else
da20d8
		return "distorted state";
da20d8
}
da20d8
da20d8
static const char * ntux_output_unit_header(const struct ntux_error_info * erri)
da20d8
{
da20d8
	if (!(erri->eflags & NTUX_ERROR_CUSTOM))
da20d8
		return "while opening";
da20d8
da20d8
	else
da20d8
		return "while querying";
da20d8
}
da20d8
980d09
static const char * ntux_output_chmod_strerror(
980d09
	const struct ntux_driver_ctx *	dctx,
980d09
	const struct ntux_error_info *	erri)
980d09
{
980d09
	(void)dctx;
980d09
980d09
	if (erri->elibcode == NTUX_ERR_CONFLICTING_ARGUMENTS)
980d09
		return "chmod conflicting arguments: +P cannot be used together with --refobj";
980d09
980d09
	else if (erri->elibcode == NTUX_ERR_NON_POSIX_DESCRIPTOR)
980d09
		return "chmod: cannot amend a referenced non-posix security descriptor";
980d09
980d09
	else
980d09
		return "ntux_output_chmod_strerror(): unhandled custom error";
980d09
}
980d09
da20d8
static const char * ntux_output_strerror(
da20d8
	const struct ntux_driver_ctx *	dctx,
da20d8
	const struct ntux_error_info *	erri)
da20d8
{
da20d8
	struct ntux_driver_ctx_impl *	ictx;
da20d8
da20d8
	if (erri->eflags & NTUX_ERROR_NATIVE) {
da20d8
		ictx = ntux_get_driver_ictx(dctx);
da20d8
		ntux_sprintf(ictx->errsbuf,"system error: 0x%X",erri->elibcode);
da20d8
		return ictx->errsbuf;
da20d8
	}
da20d8
162c96
	if ((erri->eflags & NTUX_ERROR_CUSTOM) && (erri->elibcode == NTUX_ERR_NOT_IMPLEMENTED))
162c96
		return "status: support for one or more option values is not yet implemented";
162c96
980d09
	else if ((erri->eflags & NTUX_ERROR_CUSTOM) && (erri->elibcode == NTUX_ERR_CONFLICTING_ARGUMENTS))
980d09
		return ntux_output_chmod_strerror(dctx,erri);
980d09
980d09
	else if ((erri->eflags & NTUX_ERROR_CUSTOM) && (erri->elibcode == NTUX_ERR_NON_POSIX_DESCRIPTOR))
980d09
		return ntux_output_chmod_strerror(dctx,erri);
980d09
162c96
	else if (erri->eflags & NTUX_ERROR_CUSTOM)
da20d8
		return "flow error: unexpected condition or other";
da20d8
da20d8
	else if (erri->eflags & NTUX_ERROR_NESTED)
da20d8
		return "";
da20d8
da20d8
	else if (erri->eflags & NTUX_ERROR_CHILD)
da20d8
		return "(see child process error messages)";
da20d8
da20d8
	else if (erri->esyscode == ENOBUFS)
ba22ee
		return "input error: string length exceeds buffer size";
da20d8
da20d8
	else
da20d8
		return ntux_strerror(dctx,erri->esyscode);
da20d8
}
da20d8
da20d8
static int ntux_output_error_record_plain(
da20d8
	const struct ntux_driver_ctx *	dctx,
da20d8
	const struct ntux_error_info *	erri)
da20d8
{
da20d8
	const char * epath;
da20d8
	const char * errdesc = ntux_output_strerror(dctx,erri);
58ff53
	int          fderr   = ntux_driver_fderr(dctx);
da20d8
da20d8
	epath = erri->euctx
da20d8
		? *erri->euctx->path
da20d8
		: erri->eunit;
da20d8
da20d8
	if (epath && !(erri->eflags & NTUX_ERROR_NESTED))
395925
		if (ntux_dprintf(
58ff53
				fderr,
395925
				"%s: [%s] '%s':\n",
da20d8
				dctx->program,
da20d8
				ntux_output_unit_header(erri),
da20d8
				epath) < 0)
da20d8
			return -1;
da20d8
395925
	if (ntux_dprintf(
58ff53
			fderr,
395925
			"%s: %s %s(), line %d%s%s.\n",
da20d8
			dctx->program,
da20d8
			ntux_output_error_header(erri),
da20d8
			erri->efunction,
da20d8
			erri->eline,
da20d8
			strlen(errdesc) ? ": " : "",
da20d8
			errdesc) < 0)
da20d8
		return -1;
da20d8
395925
	return 0;
da20d8
}
da20d8
da20d8
static int ntux_output_error_record_annotated(
da20d8
	const struct ntux_driver_ctx *	dctx,
da20d8
	const struct ntux_error_info *	erri)
da20d8
{
da20d8
	const char * epath;
da20d8
	const char * errdesc = ntux_output_strerror(dctx,erri);
58ff53
	int          fderr   = ntux_driver_fderr(dctx);
da20d8
da20d8
	epath = erri->euctx
da20d8
		? *erri->euctx->path
da20d8
		: erri->eunit;
da20d8
da20d8
	if (epath && !(erri->eflags & NTUX_ERROR_NESTED))
395925
		if (ntux_dprintf(
58ff53
				fderr,
da20d8
				"%s%s%s:%s %s[%s]%s %s%s'%s'%s:\n",
da20d8
da20d8
				aclr_bold,aclr_magenta,
da20d8
				dctx->program,
da20d8
				aclr_reset,
da20d8
da20d8
				aclr_bold,
da20d8
				ntux_output_unit_header(erri),
da20d8
				aclr_reset,
da20d8
da20d8
				aclr_bold,aclr_red,
da20d8
				epath,
da20d8
				aclr_reset) < 0)
da20d8
			return -1;
da20d8
395925
	if (ntux_dprintf(
58ff53
			fderr,
da20d8
			"%s%s%s:%s %s%s%s %s%s%s()%s, %s%sline %d%s%s%s%s%s.\n",
da20d8
da20d8
			aclr_bold,aclr_magenta,
da20d8
			dctx->program,
da20d8
			aclr_reset,
da20d8
da20d8
			aclr_bold,
da20d8
			ntux_output_error_header(erri),
da20d8
			aclr_reset,
da20d8
da20d8
			aclr_bold,aclr_blue,
da20d8
			erri->efunction,
da20d8
			aclr_reset,
da20d8
da20d8
			aclr_bold,aclr_green,
da20d8
			erri->eline,
da20d8
			aclr_reset,
da20d8
			strlen(errdesc) ? ": " : "",
da20d8
da20d8
			aclr_bold,
da20d8
			ntux_output_strerror(dctx,erri),
da20d8
			aclr_reset) < 0)
da20d8
		return -1;
da20d8
395925
	return 0;
da20d8
}
da20d8
da20d8
int ntux_output_error_record(
da20d8
	const struct ntux_driver_ctx *	dctx,
da20d8
	const struct ntux_error_info *	erri)
da20d8
{
da20d8
	if (dctx->cctx->drvflags & NTUX_DRIVER_ANNOTATE_NEVER)
da20d8
		return ntux_output_error_record_plain(dctx,erri);
da20d8
da20d8
	else if (dctx->cctx->drvflags & NTUX_DRIVER_ANNOTATE_ALWAYS)
da20d8
		return ntux_output_error_record_annotated(dctx,erri);
da20d8
58ff53
	else if (isatty(ntux_driver_fderr(dctx)))
da20d8
		return ntux_output_error_record_annotated(dctx,erri);
da20d8
da20d8
	else
da20d8
		return ntux_output_error_record_plain(dctx,erri);
da20d8
}
da20d8
da20d8
static int ntux_output_error_vector_plain(const struct ntux_driver_ctx * dctx)
da20d8
{
da20d8
	struct ntux_error_info ** perr;
da20d8
da20d8
	for (perr=dctx->errv; *perr; perr++)
da20d8
		if (ntux_output_error_record_plain(dctx,*perr))
da20d8
			return -1;
da20d8
da20d8
	return 0;
da20d8
}
da20d8
da20d8
static int ntux_output_error_vector_annotated(const struct ntux_driver_ctx * dctx)
da20d8
{
da20d8
	struct ntux_error_info ** perr;
da20d8
da20d8
	for (perr=dctx->errv; *perr; perr++)
da20d8
		if (ntux_output_error_record_annotated(dctx,*perr))
da20d8
			return -1;
da20d8
da20d8
	return 0;
da20d8
}
da20d8
da20d8
int ntux_output_error_vector(const struct ntux_driver_ctx * dctx)
da20d8
{
da20d8
	if (dctx->cctx->drvflags & NTUX_DRIVER_ANNOTATE_NEVER)
da20d8
		return ntux_output_error_vector_plain(dctx);
da20d8
da20d8
	else if (dctx->cctx->drvflags & NTUX_DRIVER_ANNOTATE_ALWAYS)
da20d8
		return ntux_output_error_vector_annotated(dctx);
da20d8
58ff53
	else if (isatty(ntux_driver_fderr(dctx)))
da20d8
		return ntux_output_error_vector_annotated(dctx);
da20d8
da20d8
	else
da20d8
		return ntux_output_error_vector_plain(dctx);
da20d8
}