ubase

suckless linux base utils
git clone git://git.2f30.org/ubase.git
Log | Files | Refs | README | LICENSE

commit 55795531f03ccb5a41cf80fd564b862c103252cc
parent fae9ca81a2eaf3534299b7ca3033b1e6605f9ab2
Author: Eric Pruitt <eric.pruitt@gmail.com>
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:
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, NULL); 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:");