Hi,
deraadt@ recently pointed out to me in private mail that it is good
for usability if interactive programs providing line editing
functionality are consistent what they do with Ctrl-C, ideally
discard the current input line and provide a fresh prompt.
At least that is what bc(1), ftp(1), sftp(1) and all shells do.
So i propose to do the same in cdio(1), which currently just exits
on Ctrl-C.
Sending to tech@ because i'm not quite sure which developer owns cdio(1),
or who might be interested. According to the CVS logs, naddy@ was the
last one to change user-visible functionality, and before that, there
was nothing but bug fixes and cleanup since 2010.
OK?
Ingo
P.S.
Note that the current "!siz" is fragile; el_gets(3) sets it to -1
on error. I'm polishing that while here.
P.P.S.
buf = (char *)el_gets(...) is ugly and potentially dangerous, the
manual page explicitly warns to not do that, but that's a job for
another day.
P.P.P.S.
Insects are the most successful class of animals on earth.
Even in OpenBSD, it is rarely possible to look at code without
finding something unrelated that could be improved, too.
Index: cdio.c
===================================================================
RCS file: /cvs/src/usr.bin/cdio/cdio.c,v
retrieving revision 1.80
diff -u -p -r1.80 cdio.c
--- cdio.c 18 Jan 2021 00:44:00 -0000 1.80
+++ cdio.c 12 Aug 2021 13:36:38 -0000
@@ -63,6 +63,7 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -158,6 +159,7 @@ int verbose = 1;
int msf = 1;
const char *cddb_host;
char **track_names;
+volatile sig_atomic_t signo;
EditLine *el = NULL; /* line-editing structure */
History *hist = NULL; /* line-editing history */
@@ -179,6 +181,7 @@ int pstatus(char *arg);
int play_next(char *arg);
int play_prev(char *arg);
int play_same(char *arg);
+void sigint_handler(int);
char *input(int *);
char *prompt(void);
void prtrack(struct cd_toc_entry *e, int lastflag, char *name);
@@ -1499,18 +1502,36 @@ status(int *trk, int *min, int *sec, int
return s.data->header.audio_status;
}
+void
+sigint_handler(int signo_arg)
+{
+ signo = signo_arg;
+}
+
char *
input(int *cmd)
{
+ struct sigaction sa;
char *buf;
int siz = 0;
char *p;
HistEvent hev;
+ memset(&sa, 0, sizeof(sa));
do {
- if ((buf = (char *) el_gets(el, &siz)) == NULL || !siz) {
- *cmd = CMD_QUIT;
+ signo = 0;
+ sa.sa_handler = sigint_handler;
+ if (sigaction(SIGINT, &sa, NULL) == -1)
+ err(1, "sigaction");
+ buf = (char *)el_gets(el, &siz);
+ sa.sa_handler = SIG_DFL;
+ if (sigaction(SIGINT, &sa, NULL) == -1)
+ err(1, "sigaction");
+ if (buf == NULL || siz <= 0) {
fprintf(stderr, "\r\n");
+ if (siz < 0 && errno == EINTR && signo == SIGINT)
+ continue;
+ *cmd = CMD_QUIT;
return (0);
}
if (strlen(buf) > 1)