diff --git a/src/confirm.c b/src/confirm.c new file mode 100644 index 0000000..2bfe73d --- /dev/null +++ b/src/confirm.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Dylan Lom + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "util.h" + +const char *argv0; + +/* + * Display msg, and prompt user for choice from opts. + * Returns index of chosen opt. + * + * First option (opts[0]) is default if nothing else matches + * Comparison is case insensitive + */ +int +confirm(const char *msg, const char **opts, int opts_count) +{ + if (opts_count < 2) return 0; + + char *opt0 = str_dupe(opts[0], sizeof(opts[0])); + printf("%s [%s", msg, str_toupper(opt0, strlen(opt0))); + free(opt0); + for (int i = 1; i < opts_count; i++) { + printf("/%s", opts[i]); + } + printf("]: "); + + char *resp = NULL; + size_t n = 0; + getline(&resp, &n, stdin); + str_trimr(resp, '\n', 1); + + for (int i = 0; i < opts_count; i++) { + if (strncasecmp(opts[i], resp, n) == 0) return i; + } + + return 0; +} + +/* + * Get user confirmation + * Examples: + * $ confirm + * $ confirm "Exit?" + * $ confirm "Download file?" n y + * $ confirm "What color?" red yellow blue + */ +int +main(int argc, const char *argv[]) +{ + SET_ARGV0(); + + // Options provided as args + if (argc > 1) return confirm(argv[0], argv+1, argc-1); + + const char **opts = STR_EALLOC(2); + opts[0] = "y"; + opts[1] = "n"; + return confirm(argc == 1 ? argv[0] : "Are you sure?", opts, 2); +} diff --git a/src/confirm.sh b/src/confirm.sh deleted file mode 100755 index f2f9eec..0000000 --- a/src/confirm.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env sh -# -# confirm: get user confirmation -# author: Dylan Lom -# -# Copyright (C) 2021 Dylan Lom -# -# Permission to use, copy, modify, and/or distribute this software for any purpose -# with or without fee is hereby granted. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -# FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -# THIS SOFTWARE. -# - -truthy "$1" \ - && msg="$1" \ - || msg="Are you sure you want to do that?" -printf "%s [Y/n]: " "$msg" -read resp -test ! "$resp" = 'N' -a ! "$resp" = 'n' - diff --git a/src/util.c b/src/util.c index 05c3262..41dfa0d 100644 --- a/src/util.c +++ b/src/util.c @@ -13,6 +13,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include @@ -51,6 +52,14 @@ ecalloc(size_t nmemb, size_t size) return ptr; } +char * +str_dupe(const char *s, size_t n) +{ + char *r = STR_EALLOC(n); + strncpy(r, s, n); + return r; +} + size_t str_pushc(char *s, char c, size_t s_size, size_t realloc_amount) { @@ -105,3 +114,12 @@ str_concat(int count, ...) return new_str; } + +char * +str_toupper(char *s, size_t n) +{ + for (size_t i = 0; i < n; i++) { + if islower(s[i]) s[i] = toupper(s[i]); + } + return s; +} diff --git a/src/util.h b/src/util.h index ff61bc7..6189c44 100644 --- a/src/util.h +++ b/src/util.h @@ -9,8 +9,10 @@ void edie(const char *fmt, ...); void *ecalloc(size_t nmemb, size_t size); +char *str_dupe(const char *s, size_t n); size_t str_pushc(char *s, char c, size_t size, size_t realloc_amount); int str_trimr(char *s, char c, int max_num); char *str_concat(int count, ...); +char *str_toupper(char *s, size_t n); #define STR_EALLOC(s) ecalloc((s), sizeof(char)) #define STR_MALLOC(s) calloc((s), sizeof(char))