commit ba522d3c85e14ed4626a823f0cef8d42aef9d0bc from: smytht via: GitHub date: Mon May 27 14:59:30 2024 UTC ctl.c fix handling of interrupted edits fix handling of + interruption that previously caused lock files to remain and prevent further editing The default SIGINT handler does the wrong thing when a file is currently locked for editing. Please try the diff below. ensure that edited files get unlocked if the user types Ctrl-C at prompt While editing files, temporarily disable the default SIGINT handler which does a long jump to displaying a command prompt. Otherwise we would jump away without removing our lock on the file and future attempts to edit the file would fail. Issue found by Tom Smyth. Fixed by stsp@ Thanks commit - 7b14cfd98d4c0900c1b3d8b95ef388d895a9f363 commit + ba522d3c85e14ed4626a823f0cef8d42aef9d0bc blob - 700b931c36131a8b0513e60d55ab18b3a8da45d0 blob + d8d9e210e900e38322ae61e42335b5789eae6811 --- ctl.c +++ ctl.c @@ -985,14 +985,14 @@ call_editor(char *name, char **args, char *z) edit_file(tmpfile, daemons2->mode, daemons2->propername, args); } -static void +static int provide_example_config(char *filename) { char *name; char path[PATH_MAX]; char tmpprompt[sizeof(prompt)]; FILE *f = NULL, *example = NULL; - int ret, num; + int ret = 0, n, num; struct stat sb; size_t len, remain; @@ -1000,7 +1000,7 @@ provide_example_config(char *filename) f = fopen(filename, "a+"); if (f == NULL) - return; + return 0; if (fstat(fileno(f), &sb) == -1) goto done; @@ -1012,8 +1012,8 @@ provide_example_config(char *filename) if (name == NULL) goto done; - ret = snprintf(path, sizeof(path), "/etc/examples/%s", name); - if (ret < 0 || (size_t)ret >= sizeof(path)) + n = snprintf(path, sizeof(path), "/etc/examples/%s", name); + if (n < 0 || (size_t)n >= sizeof(path)) goto done; /* Snip off rdomain trailer at end of filename. */ @@ -1104,6 +1104,7 @@ done: restoreprompt(); if (example) fclose(example); + return ret; } int @@ -1112,6 +1113,7 @@ edit_file(char *tmpfile, mode_t mode, char *propername char *editor; int fd; int ret = 0; + sig_t sigint; /* acq lock, call editor, test config with cmd and args, release lock */ if ((editor = getenv("VISUAL")) == NULL) { @@ -1120,8 +1122,17 @@ edit_file(char *tmpfile, mode_t mode, char *propername } if ((fd = acq_lock(tmpfile)) > 0) { char *argv[] = { editor, tmpfile, NULL }; - provide_example_config(tmpfile); - ret = cmdargs(editor, argv); + + /* + * Temporarily disable command.c intr() handler to ensure + * we tidy up the lock file when the user hits Ctrl-C at + * at prompt. + */ + sigint = signal(SIGINT, SIG_IGN); + + ret = provide_example_config(tmpfile); + if (ret == 0) + ret = cmdargs(editor, argv); if (ret == 0 && chmod(tmpfile, mode) == -1) { printf("%% chmod %o %s: %s\n", mode, tmpfile, strerror(errno)); @@ -1130,6 +1141,7 @@ edit_file(char *tmpfile, mode_t mode, char *propername if (ret == 0 && args != NULL) ret = cmdargs(args[0], args); rls_lock(fd); + signal(SIGINT, sigint); /* Restore SIGINT handler. */ } else { printf ("%% %s configuration is locked for editing\n", propername);