commit 3565860b40ea4a8220d5029e3d74b437a9205cda Author: Jakob Kramer Date: Tue Jun 25 19:55:37 2013 +0200 added sponge diff --git a/Makefile b/Makefile index 9aeb5c4..7f91bac 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,7 @@ SRC = \ sleep.c \ sort.c \ split.c \ + sponge.c \ sync.c \ tail.c \ tee.c \ diff --git a/sponge.1 b/sponge.1 new file mode 100644 index 0000000..8c09cc7 --- /dev/null +++ b/sponge.1 @@ -0,0 +1,11 @@ +.TH SPONGE 1 sbase\-VERSION +.SH NAME +sponge \- soak up standard input and write to a file +.SH SYNOPSIS +.B sponge +.RI [ file ] +.SH DESCRIPTION +.B sponge +reads stdin and writes to the specified file or stdout otherwise. This +makes it possible to easily create pipes which read from and write to +the same file. diff --git a/sponge.c b/sponge.c new file mode 100644 index 0000000..c116905 --- /dev/null +++ b/sponge.c @@ -0,0 +1,46 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include "util.h" + +int +main(int argc, char *argv[]) +{ + FILE *fp, *tmpfp; + char *tmp_nam, buf[BUFSIZ]; + size_t n; + + ARGBEGIN { + default: + eprintf("usage: %s [file]\n", argv0); + } ARGEND; + + if(argc == 0) + /* maybe it’s better to just redirect stdin > stdout + * directly, in this case */ + fp = stdout; + else if(argc == 1) + if(!(fp = fopen(argv[0], "w"))) + eprintf("fopen %s:", argv[0]); + + if(!(tmp_nam = tmpnam(NULL))) + eprintf("tmpnam:"); + + if(!(tmpfp = fopen(tmp_nam, "w"))) + eprintf("fopen %s:", tmp_nam); + + while((n = fread(buf, 1, sizeof buf, stdin)) > 0) { + if(fwrite(buf, 1, n, (fp == stdout ? stdout : tmpfp)) != n) + eprintf("%s: write error:", buf); + } + + if(fp != stdout) + if(rename(tmp_nam, argv[0])) { + eprintf("could not create file:"); + fclose(fp); + } + + fclose(tmpfp); + + return 0; +}