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