dd: Use sigaction(2) to obviate select(2) - ubase - suckless linux base utils | |
git clone git://git.suckless.org/ubase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 55795531f03ccb5a41cf80fd564b862c103252cc | |
parent fae9ca81a2eaf3534299b7ca3033b1e6605f9ab2 | |
Author: Eric Pruitt <[email protected]> | |
Date: Tue, 10 Oct 2017 16:27:27 +0100 | |
dd: Use sigaction(2) to obviate select(2) | |
By setting the SIGINT handler with sigaction(2), automatic retries of | |
the splice(2) syscall can be disabled by not setting SA_RESTART. This | |
makes it possible to use Ctrl+C even if the "if" operand refers to the | |
controlling terminal. The SIGINT message has also been moved outside | |
the signal handler since fprintf(3) is not an async-signal-safe | |
function. | |
Diffstat: | |
M dd.c | 61 ++++++++++++++++-------------… | |
1 file changed, 32 insertions(+), 29 deletions(-) | |
--- | |
diff --git a/dd.c b/dd.c | |
@@ -8,7 +8,6 @@ | |
*/ | |
#include <sys/ioctl.h> | |
#include <sys/mount.h> | |
-#include <sys/select.h> | |
#include <sys/stat.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
@@ -38,6 +37,15 @@ struct dd_config { | |
static int sigint = 0; | |
+static void | |
+sig_int(int unused_1, siginfo_t *unused_2, void *unused_3) | |
+{ | |
+ (void) unused_1; | |
+ (void) unused_2; | |
+ (void) unused_3; | |
+ sigint = 1; | |
+} | |
+ | |
static int | |
prepare_copy(struct dd_config *ddc, int *ifd, int *ofd) | |
{ | |
@@ -147,7 +155,6 @@ copy_splice(struct dd_config *ddc) | |
int ifd, ofd, p[2] = {-1, -1}; | |
ssize_t r = 0; | |
size_t n = 0; | |
- fd_set rfd, wfd; | |
if (prepare_copy(ddc, &ifd, &ofd) < 0) | |
return -1; | |
@@ -165,27 +172,24 @@ copy_splice(struct dd_config *ddc) | |
#endif | |
n = ddc->bs; | |
for (;ddc->b_out != ddc->count && !sigint;) { | |
- FD_ZERO(&rfd); | |
- FD_ZERO(&wfd); | |
- FD_SET(ifd, &rfd); | |
- FD_SET(ofd, &wfd); | |
- r = select(ifd > ofd ? ifd + 1 : ofd + 1, &rfd, &wfd, NULL, NU… | |
if (r < 0) | |
break; | |
- if (FD_ISSET(ifd, &rfd) == 1 && FD_ISSET(ofd, &wfd) == 1) { | |
- if (n > ddc->count - ddc->b_out) | |
- n = ddc->count - ddc->b_out; | |
- r = splice(ifd, NULL, p[1], NULL, n, SPLICE_F_MORE); | |
- if (r <= 0) | |
- break; | |
- ++ddc->rec_in; | |
- r = splice(p[0], NULL, ofd, NULL, r, SPLICE_F_MORE); | |
- if (r <= 0) | |
- break; | |
- ddc->b_out += r; | |
- ++ddc->rec_out; | |
- } | |
+ if (n > ddc->count - ddc->b_out) | |
+ n = ddc->count - ddc->b_out; | |
+ r = splice(ifd, NULL, p[1], NULL, n, SPLICE_F_MORE); | |
+ if (r <= 0) | |
+ break; | |
+ ++ddc->rec_in; | |
+ r = splice(p[0], NULL, ofd, NULL, r, SPLICE_F_MORE); | |
+ if (r <= 0) | |
+ break; | |
+ ddc->b_out += r; | |
+ ++ddc->rec_out; | |
} | |
+ | |
+ if (sigint) | |
+ fprintf(stderr, "SIGINT! Aborting ...\n"); | |
+ | |
close(ifd); | |
close(ofd); | |
close(p[0]); | |
@@ -227,14 +231,6 @@ print_stat(const struct dd_config *ddc) | |
} | |
static void | |
-sig_int(int unused) | |
-{ | |
- (void) unused; | |
- fprintf(stderr, "SIGINT! Aborting ...\n"); | |
- sigint = 1; | |
-} | |
- | |
-static void | |
usage(void) | |
{ | |
eprintf("usage: %s [-h] [if=infile] [of=outfile] [bs[=N]] [seek=N] " | |
@@ -248,6 +244,7 @@ main(int argc, char *argv[]) | |
int i = 0; | |
char buf[1024]; | |
struct dd_config config; | |
+ struct sigaction sa; | |
argv0 = argv[0]; | |
memset(&config, 0, sizeof(config)); | |
@@ -286,7 +283,13 @@ main(int argc, char *argv[]) | |
} | |
signal(SIGPIPE, SIG_IGN); | |
- signal(SIGINT, sig_int); | |
+ | |
+ sa.sa_flags = SA_SIGINFO; | |
+ sigemptyset(&sa.sa_mask); | |
+ sa.sa_sigaction = sig_int; | |
+ | |
+ if (sigaction(SIGINT, &sa, NULL) == -1) | |
+ weprintf("sigaction"); | |
if (copy(&config) < 0) | |
weprintf("copy:"); |