From 3b313e44472e1419710c83f1dc08b83796389430 Mon Sep 17 00:00:00 2001 From: Cody Boone Ferguson <53008573+xexyl@users.noreply.github.com> Date: Mon, 10 Mar 2025 03:47:02 -0700 Subject: [PATCH] Add -U UUID option - resolve #1229 Also fixed an error with -u uuidfile where it would not set the test boolean to true if the UUID was "true". The -u uuidfile and -U UUID options may not be used with -i answers, -d or -s seed. Updated man page for the above changes. **IMPORTANT NOTE**: you do NOT need to use this update in order to participate in the IOCCC28! --- CHANGES.md | 16 ++++ mkiocccentry.c | 140 ++++++++++++++++++++++++----------- mkiocccentry.h | 2 +- soup/man/man1/mkiocccentry.1 | 29 +++++++- soup/version.h | 2 +- 5 files changed, 141 insertions(+), 48 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8a781769..51efd340 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,22 @@ # Major changes to the IOCCC entry toolkit +## Release 2.4.5 2025-03-10 + +Add `-U UUID` option - resolve #1229. + +Also fixed an error with `-u uuidfile` where it would not set the `test` boolean +to true if the UUID was `"true"`. + +The `-u uuidfile` and `-U UUID` options may not be used with `-i answers`, `-d` +or `-s seed`. + +Updated man page for the above changes. + +**IMPORTANT NOTE**: you do NOT need to use this update in order to participate +in the IOCCC28! + + ## Release 2.4.4 2025-03-09 Resolve some (mostly top priority) issues. diff --git a/mkiocccentry.c b/mkiocccentry.c index a5125ad6..ecaac989 100644 --- a/mkiocccentry.c +++ b/mkiocccentry.c @@ -142,8 +142,12 @@ static const char * const usage_msg3 = "\t-A answers\twrite answers file even if it already exists\n" "\t-i answers\tread answers from file previously written by -a|-A answers\n" "\t\t\t NOTE: One cannot use both -a/-A answers and -i answers.\n" - "\t-u uuid\t\tread UUID from a file (def: prompt for UUID)\n" + "\t-u uuidfile\tread UUID from a file (def: prompt for UUID)\n" "\t\t\t NOTE: if an invalid UUID is in the file, it will try the usual way\n" + "\t\t\t NOTE: this option may not be used with -U UUID, -d, -s seed or -i answers\n" + "\t-U UUID\t\tset UUID to UUID\n" + "\t\t\t NOTE: if an invalid UUID is in the file, it will try the usual way\n" + "\t\t\t NOTE: this option may not be used with -u uuidfile, -d, -s seed or -i answers\n" "\t-s seed\t\tGenerate and use pseudo-random answers, seeding with\n" "\t\t\t seed & 0x%08u (def: do not)\n" "\t-d\t\tAlias for -s %u\n" @@ -222,8 +226,8 @@ main(int argc, char *argv[]) char *make = MAKE_PATH_0; /* path to make(1) executable */ char *answers = NULL; /* path to the answers file (recording input given on stdin) */ FILE *answersp = NULL; /* file pointer to the answers file */ - char *uuid = NULL; /* path to the UUID file */ - FILE *uuidp = NULL; /* file pointer to the UUID file */ + char *uuidfile = NULL; /* path to the UUID file */ + char *uuidstr = NULL; /* -U UUID option or UUID environmental var */ char *submission_dir = NULL; /* submission directory from which to form a compressed tarball */ char *tarball_path = NULL; /* path of the compressed tarball to form */ struct info info; /* data to form .info.json */ @@ -234,7 +238,8 @@ main(int argc, char *argv[]) bool ls_flag_used = false; /* true ==> -l /path/to/ls was given */ bool make_flag_used = false; /* true ==> -m /path/to/make was given */ bool answers_flag_used = false; /* true ==> -a write answers to answers file */ - bool read_uuid_flag_used = false; /* true ==> -u uuid used */ + bool read_uuid_flag_used = false; /* true ==> -u uuidfile used */ + bool uuid_flag_used = false; /* true ==> -U uuid used */ bool overwrite_answers_flag_used = false; /* true ==> don't prompt to overwrite answers if it already exists */ bool txzchk_flag_used = false; /* true ==> -T /path/to/txzchk was given */ bool fnamchk_flag_used = false; /* true ==> -F /path/to/fnamchk was given */ @@ -253,6 +258,7 @@ main(int argc, char *argv[]) */ memset(&auth, 0, sizeof(auth)); + /* * even though these stat structs are in file scope, make sure they are * zeroed out @@ -265,7 +271,7 @@ main(int argc, char *argv[]) */ input_stream = stdin; /* default to reading from standard in */ program = argv[0]; - while ((i = getopt(argc, argv, ":hv:J:qVt:l:a:i:A:WT:ef:F:C:yYds:m:I:u:")) != -1) { + while ((i = getopt(argc, argv, ":hv:J:qVt:l:a:i:A:WT:ef:F:C:yYds:m:I:u:U:")) != -1) { switch (i) { case 'h': /* -h - print help to stderr and exit 2 */ usage(2, program, ""); /*ooo*/ @@ -419,9 +425,13 @@ main(int argc, char *argv[]) append_path(&info.ignore_paths, optarg, true, false, false); break; case 'u': - uuid = optarg; + uuidfile = optarg; read_uuid_flag_used = true; break; + case 'U': + uuidstr = optarg; + uuid_flag_used = true; + break; case ':': /* option requires an argument */ case '?': /* illegal option */ default: /* anything else but should not actually happen */ @@ -477,7 +487,23 @@ main(int argc, char *argv[]) not_reached(); } if (seed_used && read_uuid_flag_used) { - err(3, __func__, "-u uuid cannot be used with either -d or -s seed");/*ooo*/ + err(3, __func__, "-u uuidfile cannot be used with either -d or -s seed");/*ooo*/ + not_reached(); + } + if (seed_used && uuidstr != NULL) { + err(3, __func__, "-U UUID cannot be used with -d or -s seed");/*ooo*/ + not_reached(); + } + if (read_uuid_flag_used && uuid_flag_used) { + err(3, __func__, "-u uuidfile and -U UUID cannot be used together");/*ooo*/ + not_reached(); + } + if ((read_uuid_flag_used || uuid_flag_used) && seed_used) { + err(3, __func__, "-U UUID or -u uuidfile cannot be used with -d or -s seed");/*ooo*/ + not_reached(); + } + if ((read_uuid_flag_used || uuid_flag_used) && read_answers_flag_used) { + err(3, __func__, "-U UUID or -u uuidfile cannot be used with -i answers");/*ooo*/ not_reached(); } if (ignore_warnings && abort_on_warning) { @@ -725,26 +751,10 @@ main(int argc, char *argv[]) input_stream = answersp; } - /* - * check if we should read input from UUID file - */ - if (read_uuid_flag_used && uuid != NULL && strlen(uuid) > 0) { - if (!is_read(uuid)) { - warn(__func__, "cannot read UUID file, will prompt for UUID"); - } else { - errno = 0; /* pre-clear errno for errp() */ - uuidp = fopen(uuid, "r"); - if (uuidp == NULL) { - warnp(__func__, "cannot open UUID file, will prompt for UUID"); - } - } - } - - /* * obtain the IOCCC contest ID */ - info.ioccc_id = get_contest_id(&info.test_mode, uuidp); + info.ioccc_id = get_contest_id(&info.test_mode, uuidfile, uuidstr); dbg(DBG_LOW, "Submission: IOCCC contest ID: %s", info.ioccc_id); /* @@ -1074,14 +1084,6 @@ main(int argc, char *argv[]) remarks_md = NULL; } - /* - * if uuid file is open, close it - */ - if (uuidp != NULL && is_open_file_stream(uuidp)) { - fclose(uuidp); - uuidp = NULL; - } - /* * All Done!!! All Done!!! -- Jessica Noll, Age 2 */ @@ -4323,7 +4325,9 @@ prompt(char const *str, size_t *lenp) * *testp will be set to true, otherwise it will be set to false. * * given: - * testp - pointer to boolean (in struct info) for test mode + * testp - pointer to boolean (in struct info) for test mode + * uuidfile - -u uuidfile option - path to file which if not NULL and is open can have a UUID + * uuidstr - -U UUID option (only used if -u uuidfile not used or is invalid) * * returns: * allocated contest ID string @@ -4332,13 +4336,14 @@ prompt(char const *str, size_t *lenp) * This function does not return on error or if the contest ID is malformed. */ static char * -get_contest_id(bool *testp, FILE *uuidp) +get_contest_id(bool *testp, char const *uuidfile, char *uuidstr) { char *malloc_ret = NULL; /* allocated return string */ char *linep = NULL; /* when reading from file */ size_t len; /* input string length */ bool valid = false; /* true ==> IOCCC_contest_id is valid */ bool seen_answers_header = false; + FILE *uuidfp = NULL; /* if -u uuidfile */ /* * firewall @@ -4349,17 +4354,66 @@ get_contest_id(bool *testp, FILE *uuidp) } /* - * explain contest ID unless uuidp != NULL + * if -U UUID not used check if -u uuidfile was used */ - if (uuidp != NULL && is_open_file_stream(uuidp)) { - malloc_ret = readline_dup(&linep, true, NULL, uuidp); - if (malloc_ret != NULL) { - if (valid_contest_id(malloc_ret)) { - return malloc_ret; + if (uuidstr == NULL) { + if (uuidfile != NULL) { + if (is_read(uuidfile)) { + errno = 0; /* pre-clear errno for warnp() */ + uuidfp = fopen(uuidfile, "r"); + if (uuidfp == NULL) { + warnp(__func__, "failed to open uuidfile, will prompt instead"); + } else { + uuidstr = readline_dup(&linep, true, NULL, uuidfp); + errno = 0; /* pre-clear errno for warnp() */ + if (fclose(uuidfp) != 0) { + warnp(__func__, "failed to fclose(uuidfp)"); + } + if (uuidstr != NULL) { + if (valid_contest_id(uuidstr)) { + if (strcmp(uuidstr, "test") == 0) { + + /* + * report test mode + */ + para("", + "IOCCC contest ID is test, entering test mode.", + NULL); + *testp = true; + } else { + *testp = false; + } + return uuidstr; + } + free(uuidstr); + uuidstr = NULL; + /* + * we will have to prompt the user instead + */ + } + } + } else { + warn(__func__, "-u uuidfile not readable, will prompt instead"); } - free(malloc_ret); - malloc_ret = NULL; - } + } + } else if (valid_contest_id(uuidstr)) { + /* + * case: IOCCC contest ID is test, quick return + */ + if (strcmp(uuidstr, "test") == 0) { + + /* + * report test mode + */ + para("", + "IOCCC contest ID is test, entering test mode.", + NULL); + *testp = true; + return uuidstr; + } else { + *testp = false; + return uuidstr; + } } /* * if we get here then the user has to input their uuid manually diff --git a/mkiocccentry.h b/mkiocccentry.h index a11a3e70..d86c818f 100644 --- a/mkiocccentry.h +++ b/mkiocccentry.h @@ -181,7 +181,7 @@ static void mkiocccentry_sanity_chks(struct info *infop, char const *workdir, ch char const *ls, char const *txzchk, char const *fnamchk, char const *chkentry, char const *make); static char *prompt(char const *str, size_t *lenp); -static char *get_contest_id(bool *testp, FILE *uuidp); +static char *get_contest_id(bool *testp, char const *uuidf, char *uuidstr); static int get_submit_slot(struct info *infop); static char *mk_submission_dir(char const *workdir, char const *ioccc_id, int submit_slot, char **tarball_path, time_t tstamp, bool test_mode); diff --git a/soup/man/man1/mkiocccentry.1 b/soup/man/man1/mkiocccentry.1 index 256d5d71..4a19b596 100644 --- a/soup/man/man1/mkiocccentry.1 +++ b/soup/man/man1/mkiocccentry.1 @@ -9,7 +9,7 @@ .\" "Share and Enjoy!" .\" -- Sirius Cybernetics Corporation Complaints Division, JSON spec department. :-) .\" -.TH mkiocccentry 1 "08 March 2025" "mkiocccentry" "IOCCC tools" +.TH mkiocccentry 1 "10 March 2025" "mkiocccentry" "IOCCC tools" .SH NAME .B mkiocccentry \- make an IOCCC compressed tarball for an IOCCC entry @@ -297,11 +297,34 @@ This option implies and disables some messages as well. However you will still be prompted to verify files and directories are okay. .TP -.BI \-u\ uuid +.BI \-u\ uuidfile Read UUID from a text file. -If this file cannot be read or does not have a valid UUID +If this file cannot be read or does not have a valid UUID by itself, .BR mkiocccentry (1) will prompt you as usual. +This option cannot be used with +.BI \-U\ UUID +or +.BI \-s\ seed +or +.BI \-i\ answers +or +.BR \-d . +.TP +.BI \-U\ UUID +Set UUID to +.IR UUID . +If this an invalid UUID +.BR mkiocccentry (1) +will prompt you as usual. +This option cannot be used with +.BI \-u\ uuidfile +or +.BI \-s\ seed +or +.BI \-i\ answers +or +.BR \-d . .TP .BI \-s\ seed Generate pseudo-random answers to the questions diff --git a/soup/version.h b/soup/version.h index 2dfc652f..501dfc75 100644 --- a/soup/version.h +++ b/soup/version.h @@ -83,7 +83,7 @@ * * NOTE: This should match the latest Release string in CHANGES.md */ -#define MKIOCCCENTRY_REPO_VERSION "2.4.4 2025-03-09" /* special release format: major.minor[.patch] YYYY-MM-DD */ +#define MKIOCCCENTRY_REPO_VERSION "2.4.5 2025-03-10" /* special release format: major.minor[.patch] YYYY-MM-DD */ /*