Skip to content

Commit 2492421

Browse files
authored
Merge pull request #1190 from xexyl/prompts
Improve -i answers to prompt for y/n questions
2 parents 72bb367 + ccb6b59 commit 2492421

File tree

5 files changed

+125
-71
lines changed

5 files changed

+125
-71
lines changed

CHANGES.md

+10
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ tool - which is quite useful to know that the user is using the most recent
1919
version of the script. This was also done in `jparse/` but that doesn't matter
2020
here; it's only mentioned due to the sync.
2121

22+
Enhance `mkiocccentry` prompting with `-i answers` used. Instead of always
23+
answering yes even when an issue is found, unless the new option `-Y` is used,
24+
give the user a chance to confirm things are okay (in particular, it allows one
25+
to answer no to a question; it does not prompt you for everything as that would
26+
defeat the purpose of the answers file). The use of `-Y` is highly discouraged
27+
unless you are **certain** you're good to go and it is mostly used for
28+
`mkiocccentry_test.sh` which needs to be non-interactive.
29+
30+
Updated `MKIOCCCENTRY_VERSION` to `"1.2.35 2025-02-27"`.
31+
Updated `MKIOCCCENTRY_TEST_VERSION` to` "1.0.15 2025-02-26"`.
2232

2333

2434
## Release 2.3.44 2025-02-26

mkiocccentry.c

+93-54
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ static const char * const usage_msg0 =
125125
"\t\t\t NOTE: the judges will NOT use this option\n"
126126
"\t-E\t\texit non-zero after the first warning (def: do not)\n"
127127
"\t\t\t NOTE: one cannot use both -W and -E.\n"
128-
"\t-y\t\tanswer yes to most questions (use with EXTREME caution!)";
128+
"\t-y\t\tanswer yes to most questions (use with EXTREME caution!)\n"
129+
"\t-Y\t\tforce answer yes even when using -i answers";
129130
static const char * const usage_msg1 =
130131
"\t-t tar\t\tpath to tar(1) that supports the -J (xz) option (def: %s)\n"
131132
"\t-l ls\t\tpath to ls(1) (def: %s)\n"
@@ -184,6 +185,10 @@ static uintmax_t feathery = 3; /* for entertain option of txzchk (-e) */
184185
static bool silence_prompt = false; /* true ==> do not display prompts */
185186
static bool read_answers_flag_used = false; /* true ==> -i read answers from answers file */
186187
static bool seed_used = false; /* true ==> -d or -s seed given */
188+
static bool copying_topdir = false; /* true ==> copying topdir and checking submission dir */
189+
static bool saved_answer_yes = false; /* set to answer_yes before modifying it for scanning/copying topdir */
190+
static bool saved_silence_prompt = false; /* set to silence_prompt before modifying it for scanning/copying topdir */
191+
static bool force_yes = false; /* force -y even when scanning/copying/verifying in -i answers mode */
187192

188193
/*
189194
* forward declarations
@@ -245,7 +250,7 @@ main(int argc, char *argv[])
245250
*/
246251
input_stream = stdin; /* default to reading from standard in */
247252
program = argv[0];
248-
while ((i = getopt(argc, argv, ":hv:J:qVt:l:a:i:A:WT:ef:F:C:yds:m:I:")) != -1) {
253+
while ((i = getopt(argc, argv, ":hv:J:qVt:l:a:i:A:WT:ef:F:C:yYds:m:I:")) != -1) {
249254
switch (i) {
250255
case 'h': /* -h - print help to stderr and exit 2 */
251256
usage(2, program, ""); /*ooo*/
@@ -301,20 +306,21 @@ main(int argc, char *argv[])
301306
answers_flag_used = true;
302307
break;
303308
case 'i': /* -i input_recorded_answers */
309+
read_answers_flag_used = true;
310+
/*
311+
* set need_confirm to false to prevent problem where a user might
312+
* have a different file set
313+
*/
314+
need_confirm = false;
315+
/*
316+
* set answer_yes to prevent problem where a user might have a
317+
* different file set
318+
*/
319+
answer_yes = true;
320+
need_hints = false;
321+
silence_prompt = true;
304322
answers = optarg;
305-
read_answers_flag_used = true;
306-
/*
307-
* set need_confirm to false to prevent problem where a user might
308-
* have a different file set
309-
*/
310-
need_confirm = false;
311-
/*
312-
* set answer_yes to prevent problem where a user might have a
313-
* different file set
314-
*/
315323
answer_yes = true;
316-
need_hints = false;
317-
silence_prompt = true;
318324
break;
319325
case 'W': /* -W ignores all warnings (this does NOT the judges will! :) ) */
320326
ignore_warnings = true;
@@ -347,6 +353,11 @@ main(int argc, char *argv[])
347353
answer_yes = true;
348354
need_confirm = false;
349355
break;
356+
case 'Y': /* force yes even when we would normally temporarily undo it */
357+
force_yes = true;
358+
answer_yes = true;
359+
need_confirm = false;
360+
break;
350361
case 'd': /* alias for -s DEFAULT_SEED */
351362
answer_seed = DEFAULT_SEED;
352363
seed_used = true;
@@ -358,6 +369,7 @@ main(int argc, char *argv[])
358369
silence_prompt = true;
359370
/* set -E boolean */
360371
abort_on_warning = true;
372+
force_yes = true;
361373
break;
362374
case 's': /* set seed as seed & SEED_MASK */
363375
/*
@@ -381,6 +393,7 @@ main(int argc, char *argv[])
381393
silence_prompt = true;
382394
/* set -E boolean */
383395
abort_on_warning = true;
396+
force_yes = true;
384397
}
385398
break;
386399
case 'm': /* set path to make(1) */
@@ -643,6 +656,7 @@ main(int argc, char *argv[])
643656
}
644657
input_stream = answersp;
645658
}
659+
646660
/*
647661
* obtain the IOCCC contest ID
648662
*/
@@ -1190,6 +1204,7 @@ scan_topdir(char *args, struct info *infop, char const *make, char const *submis
11901204
not_reached();
11911205
}
11921206

1207+
11931208
/*
11941209
* list of required files (prog.c, Makefile and remarks.md) (this will be
11951210
* shown to the user too)
@@ -1803,13 +1818,29 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
18031818
* files list is empty (though in theory if that did happen we should never
18041819
* get here).
18051820
*/
1806-
18071821
/*
1808-
* free arrays IFF (if and only if) they are empty
1822+
* If -Y is not used and -i answers is used we need to temporarily disable
1823+
* the -y so that the user can verify different file sets (if something
1824+
* changes for example). Normally we don't need to do this as it would
1825+
* happen anyway but with -i answers it is disabled as it forces -y. If one
1826+
* is SURE they are okay they can use -Y instead and they won't be bothered
1827+
* even in this and the next function (check_submission_dir()).
1828+
*
1829+
* NOTE: we will undo these at the end of check_submission_dir().
1830+
*
1831+
* NOTE: we will always save the current status of the silence_prompt and
1832+
* answer_yes booleans.
18091833
*/
1810-
free_paths_array(&infop->required_files, true);
1811-
if (infop->required_files == NULL) {
1812-
err(4, __func__, "NULL required files list array");/*ooo*/
1834+
copying_topdir = true;
1835+
saved_silence_prompt = silence_prompt;
1836+
saved_answer_yes = answer_yes;
1837+
if (!force_yes) {
1838+
answer_yes = false;
1839+
silence_prompt = false;
1840+
}
1841+
1842+
if (paths_in_array(infop->required_files) <= 0) {
1843+
err(4, __func__, "required files list array is empty");/*ooo*/
18131844
not_reached();
18141845
}
18151846
/*
@@ -1933,7 +1964,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
19331964
}
19341965
print("%s\n", p);
19351966
}
1936-
if (!answer_yes && !read_answers_flag_used) {
1967+
if (!answer_yes) {
19371968
yorn = yes_or_no("\nIs this OK? [Yn]", true);
19381969
if (!yorn) {
19391970
print("we suggest you delete %s and try again\nwith the correct options used\n",
@@ -1981,7 +2012,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
19812012
}
19822013
print("%s\n", p);
19832014
}
1984-
if (!answer_yes && !read_answers_flag_used) {
2015+
if (!answer_yes) {
19852016
yorn = yes_or_no("\nIs this OK? [Yn]", true);
19862017
if (!yorn) {
19872018
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -2022,7 +2053,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
20222053
}
20232054
print("%s\n", p);
20242055
}
2025-
if (!answer_yes && !read_answers_flag_used) {
2056+
if (!answer_yes) {
20262057
yorn = yes_or_no("\nIs this OK? [Yn]", true);
20272058
if (!yorn) {
20282059
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -2072,7 +2103,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
20722103
}
20732104
print("%s\n", p);
20742105
}
2075-
if (!answer_yes && !read_answers_flag_used) {
2106+
if (!answer_yes) {
20762107
yorn = yes_or_no("\nIs this OK? [Yn]", true);
20772108
if (!yorn) {
20782109
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -2112,7 +2143,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
21122143
}
21132144
print("%s\n", p);
21142145
}
2115-
if (!answer_yes && !read_answers_flag_used) {
2146+
if (!answer_yes) {
21162147
yorn = yes_or_no("\nIs this OK? [Yn]", true);
21172148
if (!yorn) {
21182149
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -2149,7 +2180,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
21492180
}
21502181
print("%s\n", p);
21512182
}
2152-
if (!answer_yes && !read_answers_flag_used) {
2183+
if (!answer_yes) {
21532184
yorn = yes_or_no("\nIs this OK? [Yn]", true);
21542185
if (!yorn) {
21552186
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -2183,7 +2214,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
21832214
}
21842215
print("%s\n", p);
21852216
}
2186-
if (!answer_yes && !read_answers_flag_used) {
2217+
if (!answer_yes) {
21872218
yorn = yes_or_no("\nIs this OK? [Yn]", true);
21882219
if (!yorn) {
21892220
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -2243,7 +2274,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
22432274
print("%s\n", p);
22442275
}
22452276
}
2246-
if (!answer_yes && !read_answers_flag_used) {
2277+
if (!answer_yes) {
22472278
yorn = yes_or_no("\nIs this OK? [Yn]", true);
22482279
if (!yorn) {
22492280
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -3362,7 +3393,7 @@ check_submission_dir(struct info *infop, char *submit_path, char *topdir_path,
33623393
print("%s\n", p);
33633394
}
33643395

3365-
if (!answer_yes && !read_answers_flag_used) {
3396+
if (!answer_yes) {
33663397
yorn = yes_or_no("\nIs this OK? [Yn]", true);
33673398
if (!yorn) {
33683399
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -3421,7 +3452,7 @@ check_submission_dir(struct info *infop, char *submit_path, char *topdir_path,
34213452
}
34223453
}
34233454
}
3424-
if (!answer_yes && !read_answers_flag_used) {
3455+
if (!answer_yes) {
34253456
yorn = yes_or_no("\nIs this OK? [Yn]", true);
34263457
if (!yorn) {
34273458
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
@@ -3484,6 +3515,12 @@ check_submission_dir(struct info *infop, char *submit_path, char *topdir_path,
34843515
errp(114, __func__, "failed to close(cwd)");
34853516
not_reached();
34863517
}
3518+
/*
3519+
* undo special checks for -i answers
3520+
*/
3521+
copying_topdir = false;
3522+
silence_prompt = saved_silence_prompt;
3523+
answer_yes = saved_answer_yes;
34873524
}
34883525

34893526
/*
@@ -3986,6 +4023,7 @@ prompt(char const *str, size_t *lenp)
39864023
int ret; /* libc function return value */
39874024
size_t len; /* length of input */
39884025
char *buf; /* allocated input string */
4026+
FILE *stream = NULL; /* input_stream or stdin depending on options used */
39894027

39904028
/*
39914029
* firewall
@@ -3997,6 +4035,13 @@ prompt(char const *str, size_t *lenp)
39974035
not_reached();
39984036
}
39994037

4038+
if (copying_topdir) {
4039+
stream = stdin;
4040+
} else {
4041+
stream = input_stream;
4042+
}
4043+
4044+
40004045
/*
40014046
* prompt + :<space> if silence_prompt is false
40024047
*/
@@ -4051,7 +4096,7 @@ prompt(char const *str, size_t *lenp)
40514096
/*
40524097
* read user input - return input length
40534098
*/
4054-
buf = readline_dup(&linep, true, &len, input_stream);
4099+
buf = readline_dup(&linep, true, &len, stream);
40554100
if (buf == NULL) {
40564101
err(148, __func__, "EOF while reading prompt input");
40574102
not_reached();
@@ -5970,7 +6015,7 @@ get_abstract(struct info *infop)
59706015
* true ==> input is yes in some form,
59716016
* false ==> input is not yes or there was a read error.
59726017
*
5973-
* NOTE: The -y (answer_yes) as no impact on this function as
6018+
* NOTE: The -y (answer_yes) has no impact on this function as
59746019
* the yes or no input will be read regardless.
59756020
*/
59766021
static bool
@@ -5980,12 +6025,18 @@ noprompt_yes_or_no(void)
59806025
size_t len; /* length of input */
59816026
char *response; /* yes or no response */
59826027
char *p;
6028+
FILE *stream = NULL; /* we need this so we can prompt users with -i answers */
59836029

6030+
if (read_answers_flag_used && !answer_yes) {
6031+
stream = stdin;
6032+
} else {
6033+
stream = input_stream;
6034+
}
59846035
/*
59856036
* read user input - return input length
59866037
*/
59876038
errno = 0; /* pre-clear errno for warnp() */
5988-
response = readline_dup(&linep, true, &len, input_stream);
6039+
response = readline_dup(&linep, true, &len, stream);
59896040
if (response == NULL) {
59906041

59916042
/*
@@ -7402,16 +7453,14 @@ verify_submission_dir(char const *submission_dir, char const *ls)
74027453
ls_stream = NULL;
74037454

74047455
/*
7405-
* if either -d or -s seed are used, temporarily turn on prompting
7456+
* we make sure that unless -Y is used the user always has a chance to look
7457+
* at the final directory output
74067458
*/
7407-
if (seed_used) {
7408-
silence_prompt = false;
7409-
7410-
/*
7411-
* however, if -i input_recorded_answers is used, force prompting
7412-
*/
7413-
} else if (read_answers_flag_used) {
7414-
silence_prompt = false;
7459+
saved_silence_prompt = silence_prompt;
7460+
saved_answer_yes = answer_yes;
7461+
if (!force_yes) {
7462+
answer_yes = false;
7463+
silence_prompt = false;
74157464
}
74167465

74177466
/*
@@ -7430,23 +7479,13 @@ verify_submission_dir(char const *submission_dir, char const *ls)
74307479
"not the topdir where your submission files are) and then rerun this tool",
74317480
"again.",
74327481
NULL);
7433-
err(14, __func__, "user rejected listing of submission directory: %s", submission_dir);
7482+
err(5, __func__, "user rejected listing of submission directory: %s", submission_dir);/*ooo*/
74347483
not_reached();
74357484
}
74367485
}
74377486

7438-
/*
7439-
* if either -d or -s seed are used, silence prompting again
7440-
*/
7441-
if (seed_used) {
7442-
silence_prompt = true;
7443-
7444-
/*
7445-
* and of input_recorded_answers was used, silence prompting and turn back on -y
7446-
*/
7447-
} else if (read_answers_flag_used) {
7448-
silence_prompt = true;
7449-
}
7487+
silence_prompt = saved_silence_prompt;
7488+
answer_yes = saved_answer_yes;
74507489

74517490
/*
74527491
* free storage

soup/man/man1/mkiocccentry.1

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
.\" "Share and Enjoy!"
1010
.\" -- Sirius Cybernetics Corporation Complaints Division, JSON spec department. :-)
1111
.\"
12-
.TH mkiocccentry 1 "21 February 2025" "mkiocccentry" "IOCCC tools"
12+
.TH mkiocccentry 1 "27 February 2025" "mkiocccentry" "IOCCC tools"
1313
.SH NAME
1414
.B mkiocccentry
1515
\- make an IOCCC compressed tarball for an IOCCC entry
@@ -173,6 +173,11 @@ See:
173173
.ft R
174174
for information on the IOCCC rules and guidelines.
175175
.TP
176+
.B \-Y
177+
Force answer yes to questions even when you would otherwise be prompted.
178+
This is mostly for the test-suite and in particular for the reading of answers from a file.
179+
That is because when scanning the topdir and making directories and copying files from the topdir to the submission directory and checking that the directory ended up okay, we do prompt the user again.
180+
.TP
176181
.BI \-t\ tar
177182
Set path to
178183
.B tar

0 commit comments

Comments
 (0)