logo

utils-std

Collection of commonly available Unix tools
commit: 59a64b48f468b19a6a2aa8322e6807fcc7ce2892
parent 29c71c751b82e06d6ec8bcd0cc722c0f2500657d
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Wed, 10 Apr 2024 12:33:02 +0200

lib/consent: split off consent functions from cmd/rm.c

Diffstat:

MMakefile4++++
Mcmd/rm.c138++++++-------------------------------------------------------------------------
Alib/consent.c137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/consent.h12++++++++++++
4 files changed, 162 insertions(+), 129 deletions(-)

diff --git a/Makefile b/Makefile @@ -102,3 +102,7 @@ cmd/mknod: cmd/mknod.c lib/mode.c Makefile cmd/seq: cmd/seq.c Makefile rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} $(CC) -std=c99 $(CFLAGS) -o $@ cmd/seq.c -lm $(LDFLAGS) $(LDSTATIC) + +cmd/rm: cmd/rm.c lib/consent.c lib/consent.h Makefile + rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} + $(CC) -std=c99 $(CFLAGS) -o $@ cmd/rm.c lib/consent.c $(LDFLAGS) $(LDSTATIC) diff --git a/cmd/rm.c b/cmd/rm.c @@ -9,16 +9,16 @@ #define _NETBSD_SOURCE #endif +#include "../lib/consent.h" + #include <assert.h> -#include <ctype.h> // isprint -#include <dirent.h> // fdopendir, readdir, closedir -#include <errno.h> // errno -#include <fcntl.h> // AT_FDCWD -#include <langinfo.h> // nl_langinfo -#include <limits.h> // PATH_MAX -#include <locale.h> // setlocale -#include <regex.h> // regcomp -#include <stdarg.h> // va_list +#include <ctype.h> // isprint +#include <dirent.h> // fdopendir, readdir, closedir +#include <errno.h> // errno +#include <fcntl.h> // AT_FDCWD +#include <limits.h> // PATH_MAX +#include <locale.h> // setlocale +#include <stdarg.h> // va_list #include <stdbool.h> #include <stdio.h> // fprintf, getline #include <stdlib.h> // free @@ -29,126 +29,6 @@ bool opt_d = false, force = false, recurse = false, verbose = false, opt_i = false; char *argv0 = "rm"; -// Needs to be executed after setlocale -regex_t consent_yesexpr_r; -regex_t consent_noexpr_r; -static void -consent_init() -{ - char *yesexpr = nl_langinfo(YESEXPR); - int yesexpr_ret = regcomp(&consent_yesexpr_r, yesexpr, REG_EXTENDED | REG_NOSUB); - if(yesexpr_ret != 0) - { - char errstr[64] = ""; - regerror(yesexpr_ret, &consent_yesexpr_r, errstr, 100); - fprintf( - stderr, "%s: Got errorneous yesexpr regex /%s/ from locale: %s\n", argv0, yesexpr, errstr); - - errno = 0; - fprintf(stderr, "%s: Fallbacking to /^[Yy]/\n", argv0); - yesexpr_ret = regcomp(&consent_yesexpr_r, "^[Yy]", REG_EXTENDED | REG_NOSUB); - assert(yesexpr_ret == 0); - } - assert(errno == 0); - - char *noexpr = nl_langinfo(NOEXPR); - int noexpr_ret = regcomp(&consent_noexpr_r, noexpr, REG_EXTENDED | REG_NOSUB); - if(noexpr_ret != 0) - { - char errstr[64] = ""; - regerror(noexpr_ret, &consent_noexpr_r, errstr, 100); - fprintf( - stderr, "%s: Got errorneous noexpr regex /%s/ from locale: %s\n", argv0, noexpr, errstr); - - errno = 0; - fprintf(stderr, "%s: Fallbacking to /^[Nn]/\n", argv0); - noexpr_ret = regcomp(&consent_noexpr_r, "^[Nn]", REG_EXTENDED | REG_NOSUB); - assert(noexpr_ret == 0); - } - assert(errno == 0); -} - -static void -consent_finish() -{ - regfree(&consent_yesexpr_r); - regfree(&consent_noexpr_r); -} - -// Consent therefore defaults to no -static bool -consentf(const char *restrict fmt, ...) -{ - bool result = false; - char *line = NULL; - size_t len = 0; - - va_list ap; - - assert(errno == 0); - va_start(ap, fmt); - /* flawfinder: ignore */ - int ret = vfprintf(stderr, fmt, ap); - va_end(ap); - - if(ret < 0) - { - fprintf(stderr, "%s: Failed to print user prompt: %s\n", argv0, strerror(errno)); - errno = 0; - goto end; - } - - assert(errno == 0); - ssize_t nread = getline(&line, &len, stdin); - if(nread < 0) - { - fprintf(stderr, "\n%s: Failed getting user entry via getline: %s\n", argv0, strerror(errno)); - errno = 0; - goto end; - } - - if(nread == 0) - { - fprintf(stderr, "%s: Got empty response, considering it false\n", argv0); - errno = 0; - goto end; - } - - // Doesn't echoes if not a TTY - if(!isatty(0)) write(2, line, nread); - // isatty changes errno if not a TTY *sigh* - errno = 0; - - if(line[nread - 1] == '\n') line[--nread] = 0; - - if(line[0] == 0 || line[0] == '\n' || line[0] == '\r') - { - fprintf(stderr, "%s: Got empty response, considering it false\n", argv0); - goto end; - } - - if(regexec(&consent_yesexpr_r, line, 0, 0, 0) == 0) - { - result = true; - goto end; - } - - if(regexec(&consent_noexpr_r, line, 0, 0, 0) == 0) - { - result = false; - goto end; - } - - fprintf(stderr, - "%s: User entry \"%s\" neither affirmative nor negative, considering it false\n", - argv0, - line); - -end: - if(len != 0) free(line); - return result; -} - static int do_unlinkat(int fd, char *name, char *acc_path) { diff --git a/lib/consent.c b/lib/consent.c @@ -0,0 +1,137 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L + +#include "./consent.h" + +#include <assert.h> +#include <errno.h> +#include <langinfo.h> // nl_langinfo +#include <regex.h> // regcomp +#include <stdarg.h> // va_list +#include <stdio.h> // fprintf, getline, +#include <stdlib.h> // free +#include <string.h> // strerror +#include <unistd.h> // isatty, write + +// Needs to be executed after setlocale +regex_t consent_yesexpr_r; +regex_t consent_noexpr_r; +void +consent_init() +{ + char *yesexpr = nl_langinfo(YESEXPR); + int yesexpr_ret = regcomp(&consent_yesexpr_r, yesexpr, REG_EXTENDED | REG_NOSUB); + if(yesexpr_ret != 0) + { + char errstr[64] = ""; + regerror(yesexpr_ret, &consent_yesexpr_r, errstr, 100); + fprintf( + stderr, "%s: Got errorneous yesexpr regex /%s/ from locale: %s\n", argv0, yesexpr, errstr); + + errno = 0; + fprintf(stderr, "%s: Fallbacking to /^[Yy]/\n", argv0); + yesexpr_ret = regcomp(&consent_yesexpr_r, "^[Yy]", REG_EXTENDED | REG_NOSUB); + assert(yesexpr_ret == 0); + } + assert(errno == 0); + + char *noexpr = nl_langinfo(NOEXPR); + int noexpr_ret = regcomp(&consent_noexpr_r, noexpr, REG_EXTENDED | REG_NOSUB); + if(noexpr_ret != 0) + { + char errstr[64] = ""; + regerror(noexpr_ret, &consent_noexpr_r, errstr, 100); + fprintf( + stderr, "%s: Got errorneous noexpr regex /%s/ from locale: %s\n", argv0, noexpr, errstr); + + errno = 0; + fprintf(stderr, "%s: Fallbacking to /^[Nn]/\n", argv0); + noexpr_ret = regcomp(&consent_noexpr_r, "^[Nn]", REG_EXTENDED | REG_NOSUB); + assert(noexpr_ret == 0); + } + assert(errno == 0); +} + +void +consent_finish() +{ + regfree(&consent_yesexpr_r); + regfree(&consent_noexpr_r); +} + +// Consent therefore defaults to no +bool +consentf(const char *restrict fmt, ...) +{ + bool result = false; + char *line = NULL; + size_t len = 0; + + va_list ap; + + assert(errno == 0); + va_start(ap, fmt); + /* flawfinder: ignore */ + int ret = vfprintf(stderr, fmt, ap); + va_end(ap); + + if(ret < 0) + { + fprintf(stderr, "%s: Failed to print user prompt: %s\n", argv0, strerror(errno)); + errno = 0; + goto end; + } + + assert(errno == 0); + ssize_t nread = getline(&line, &len, stdin); + if(nread < 0) + { + fprintf(stderr, "\n%s: Failed getting user entry via getline: %s\n", argv0, strerror(errno)); + errno = 0; + goto end; + } + + if(nread == 0) + { + fprintf(stderr, "%s: Got empty response, considering it false\n", argv0); + errno = 0; + goto end; + } + + // Doesn't echoes if not a TTY + if(!isatty(0)) write(2, line, nread); + // isatty changes errno if not a TTY *sigh* + errno = 0; + + if(line[nread - 1] == '\n') line[--nread] = 0; + + if(line[0] == 0 || line[0] == '\n' || line[0] == '\r') + { + fprintf(stderr, "%s: Got empty response, considering it false\n", argv0); + goto end; + } + + if(regexec(&consent_yesexpr_r, line, 0, 0, 0) == 0) + { + result = true; + goto end; + } + + if(regexec(&consent_noexpr_r, line, 0, 0, 0) == 0) + { + result = false; + goto end; + } + + fprintf(stderr, + "%s: User entry \"%s\" neither affirmative nor negative, considering it false\n", + argv0, + line); + +end: + if(len != 0) free(line); + return result; +} diff --git a/lib/consent.h b/lib/consent.h @@ -0,0 +1,12 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#include <stdbool.h> + +extern char *argv0; + +// Consent therefore defaults to no, including in cases of error +bool consentf(const char *restrict fmt, ...); +void consent_finish(); +void consent_init();