Index: usr.bin/sponge/Makefile =================================================================== --- /dev/null +++ usr.bin/sponge/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG= sponge + +.include Index: usr.bin/sponge/sponge.1 =================================================================== --- /dev/null +++ usr.bin/sponge/sponge.1 @@ -0,0 +1,60 @@ +.\" Eitan Adler. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd November 01, 2017 +.Dt SPONGE 1 +.Os +.Sh NAME +.Nm sponge +.Nd buffer stdin and write to stdout +.Sh SYNOPSIS +.Nm +.Op Fl a +.Ar filename +.Sh DESCRIPTION +The +.Nm +utility reads standard in until complete, and then opens +the output file, and then writes to it. +The following options are available: +.Bl -tag -width indent +.It Fl a +Opens +.Ar filename +in append mode. +.El +.Sh SEE ALSO +.Xr builtin 1 , +.Xr csh 1 , +.Xr getrusage 2 , +.Xr tee 1 +.Xr wait 2 +.Sh EXIT STATUS +.Ex -std +.Sh HISTORY +A +.Nm +utility appeared in +.At v3 . Index: usr.bin/sponge/sponge.c =================================================================== --- /dev/null +++ usr.bin/sponge/sponge.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include + +#define DEFAULT_BUFF_SIZE 16384 + +static int flag_append = 0; + +static void usage(void); +static void* safe_malloc(size_t size); +static void* safe_reallocf(void *ptr, size_t size); + +static void* safe_malloc(size_t size) +{ + void* ret; + ret = malloc(size); + if (ret == NULL) + { + perror("malloc failed"); + exit(1); + } + return ret; +} + +static void* safe_reallocf(void *ptr, size_t size) +{ + void* ret; + ret = reallocf(ptr, size); + if (ret == NULL) + { + perror("reallocf failed"); + exit(1); + } + return ret; +} + +static void +usage(void) +{ + printf("usage: sponge [-a] filename\n"); +} + +int +main(int argc, char* argv[]) +{ + char* buf; + char* bufstart; + char* outfile; + char* openflags = "w"; + size_t bufsize; + size_t bufused; + ssize_t i; + int opt; + FILE* fh; + + while ((opt = getopt(argc, argv, "ah")) != -1) + { + switch (opt) + { + case 'a': + flag_append=1; + break; + case 'h': + usage(); + exit(0); + default: + usage(); + exit(1); + } + } + + if (optind < argc) + { + outfile = argv[optind]; + } + + + bufsize = DEFAULT_BUFF_SIZE; + bufused = 0; + bufstart = safe_malloc(bufsize); + buf = bufstart; + + while ((i = read(STDIN_FILENO, buf, bufsize - bufused)) > 0) { + bufused += i; + if (bufused == bufsize) + { + bufsize *= 4; + bufstart = safe_reallocf(bufstart, bufsize); + } + buf = bufstart + bufused; + } + + assert (buf != NULL); + assert (bufstart != NULL); + + if (outfile) + { + if (flag_append) + { + openflags = "a"; + } + fh = fopen(outfile, openflags); + } + else + { + fh = stdout; + } + + if (fwrite(bufstart, bufused, 1, fh) < 0) + { + perror("error writing buf"); + exit(1); + } + if (outfile) + { + fclose(fh); + } +} Index: usr.bin/tee/tee.1 =================================================================== --- usr.bin/tee/tee.1 +++ usr.bin/tee/tee.1 @@ -72,6 +72,8 @@ except in the event of the .Fl i option. +.Sh SEE ALSO +.Xr sponge 1 .Sh EXIT STATUS .Ex -std .Sh STANDARDS