Files
gno/bin/tee/tee.c
T

181 lines
3.7 KiB
C
Raw Normal View History

/*
* tee - send a copy of stdin to a file as well as stdout.
*
1999-07-03 14:46:37 +00:00
* Version 1.1 and later by Devin Reade <gdr@gno.org>
*
1997-10-30 03:35:21 +00:00
* tee originally appeared with GNO v1.x, but was fully buffered.
* This is a complete re-write which by default uses full buffering
* for the output file, but _no_ buffering on stdin and stdout.
* This buffering behavior can be changed slightly by the -b flag.
1996-09-03 03:56:08 +00:00
*
1999-07-03 14:46:37 +00:00
* $Id: tee.c,v 1.5 1999/07/03 14:33:38 gdr-ftp Exp $
*/
1996-09-03 03:56:08 +00:00
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
1997-10-30 03:35:21 +00:00
#include <err.h>
1997-10-30 03:35:21 +00:00
#ifdef __STACK_CHECK__
#include <gno/gno.h>
static void
showstack (void) {
fprintf(stderr,"stack usage: %d bytes\n", _endStackCheck());
return;
1996-09-03 03:56:08 +00:00
}
1997-10-30 03:35:21 +00:00
#endif /* __STACK_CHECK__ */
#define BUFFERSIZE 512
1997-10-30 03:35:21 +00:00
char *versionstr = "version 1.3 by Devin Reade";
1996-09-03 03:56:08 +00:00
char *usagestr = "[ -abiV ] filename\n\
\t-a\tappend to filename\n\
\t-i\tignore SIGINT\n";
char buf2[BUFFERSIZE];
1997-10-30 03:35:21 +00:00
static void usage(const char *pname);
1996-09-03 03:56:08 +00:00
int
main(int argc, char **argv)
{
int c, b_flag;
1997-10-30 03:35:21 +00:00
char *mode, *master;
1996-09-03 03:56:08 +00:00
FILE *fp, *fp2;
int characters;
1996-09-03 03:56:08 +00:00
extern int optind;
1996-09-03 03:56:08 +00:00
/*
* initialization
*/
1997-10-30 03:35:21 +00:00
#ifdef __STACK_CHECK__
_beginStackCheck();
atexit(showstack);
#endif
1996-09-03 03:56:08 +00:00
mode = "w+";
b_flag = 0;
1996-09-03 03:56:08 +00:00
/*
* parse the command line
*/
while ((c = getopt(argc, argv, "abiV")) != EOF) {
switch (c) {
case 'a':
/* append to instead of truncate output file */
mode = "a+";
break;
1996-09-03 03:56:08 +00:00
case 'b':
/* do line buffering */
b_flag++;
break;
1996-09-03 03:56:08 +00:00
case 'i':
/* ignore SIGINT */
signal(SIGINT, SIG_IGN);
break;
1996-09-03 03:56:08 +00:00
case 'V':
/* FALLTHROUGH */
default:
1997-10-30 03:35:21 +00:00
usage(argv[0]);
1996-09-03 03:56:08 +00:00
/* NOTREACHED */
}
}
if ((argc - optind) < 1) {
1997-10-30 03:35:21 +00:00
usage(argv[0]);
1996-09-03 03:56:08 +00:00
}
1996-09-03 03:56:08 +00:00
/*
* open the output file
*/
1997-10-30 03:35:21 +00:00
master = argv[optind];
if ((fp = fopen(master, mode)) == NULL) {
err(1, "couldn't open master file %s", master);
1996-09-03 03:56:08 +00:00
}
1996-09-03 03:56:08 +00:00
/*
* loop until done with the first file
*/
if (b_flag) {
/* line buffering */
setvbuf(stdin, NULL, _IOLBF, 1024);
setvbuf(stdout, NULL, _IOLBF, 1024);
characters = BUFFERSIZE;
1997-10-30 03:35:21 +00:00
/* poll until EOF seen on input or an error occurs */
while (fgets(buf2, characters, stdin) != NULL &&
fputs(buf2, stdout) != EOF &&
fputs(buf2, fp) != EOF);
1996-09-03 03:56:08 +00:00
} else {
/* no buffering */
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
characters = 2; /* a value of 2 gives one character reads */
1996-09-03 03:56:08 +00:00
1997-10-30 03:35:21 +00:00
/* avoid ORCA/C v2.1.1b2 optimization problem */
#undef fgetc
#undef fputc
/* poll until EOF seen on input or an error occurs */
while (((c = fgetc(stdin)) != EOF) &&
(fputc(c, stdout) != EOF) &&
(fputc(c, fp) != EOF));
}
fflush(fp);
fflush(stdout);
1996-09-03 03:56:08 +00:00
/*
* make additional copies if necessary
*/
optind++;
if (argc <= optind) {
fclose(fp);
1997-10-30 03:35:21 +00:00
exit(0);
1996-09-03 03:56:08 +00:00
}
while (argc > optind) {
size_t count;
1996-09-03 03:56:08 +00:00
/* rewind the master file */
rewind(fp);
1996-09-03 03:56:08 +00:00
/* open the new file */
if ((fp2 = fopen(argv[optind], mode)) == NULL) {
1997-10-30 03:35:21 +00:00
err(1, "couldn't open duplicate file %s", argv[optind]);
1996-09-03 03:56:08 +00:00
}
1996-09-03 03:56:08 +00:00
/* make the copy */
while (!feof(fp) && !(ferror(fp))) {
count = fread(buf2, sizeof(char), BUFFERSIZE, fp);
1996-09-03 03:56:08 +00:00
if (count > 0) {
fwrite(buf2, sizeof(char), count, fp2);
if (ferror(fp2)) {
1997-10-30 03:35:21 +00:00
err(1, "error writing duplicate file %s", argv[optind]);
}
}
1996-09-03 03:56:08 +00:00
}
1996-09-03 03:56:08 +00:00
fclose(fp2);
if (ferror(fp)) {
1997-10-30 03:35:21 +00:00
err(1, "error reading master file %s", master);
1996-09-03 03:56:08 +00:00
}
optind++;
}
fclose(fp);
1997-10-30 03:35:21 +00:00
exit(0);
}
static void
usage (const char *pname) {
fprintf(stderr,"%s %s\nUsage:\t%s %s\n", pname, versionstr,
pname, usagestr);
exit(1);
}