mirror of
https://github.com/vim/vim.git
synced 2025-10-05 05:34:07 -04:00
Problem: The tee command is not available on MS-Windows. Solution: Adjust tee.c for MSVC and add a makefile. (Yasuhiro Matsumoto)
162 lines
3.8 KiB
C
162 lines
3.8 KiB
C
/* vim:set ts=4 sw=4:
|
|
*
|
|
* Copyright (c) 1996, Paul Slootman
|
|
*
|
|
* Author: Paul Slootman
|
|
* (paul@wurtel.hobby.nl, paul@murphy.nl, paulS@toecompst.nl)
|
|
* Modifications for MSVC: Yasuhiro Matsumoto
|
|
*
|
|
* This source code is released into the public domain. It is provided on an
|
|
* as-is basis and no responsibility is accepted for its failure to perform
|
|
* as expected. It is worth at least as much as you paid for it!
|
|
*
|
|
* tee.c - pipe fitting
|
|
*
|
|
* tee reads stdin, and writes what it reads to each of the specified
|
|
* files. The primary reason of existence for this version is a quick
|
|
* and dirty implementation to distribute with Vim, to make one of the
|
|
* most useful features of Vim possible on OS/2: quickfix.
|
|
*
|
|
* Of course, not using tee but instead redirecting make's output directly
|
|
* into a temp file and then processing that is possible, but if we have a
|
|
* system capable of correctly piping (unlike DOS, for example), why not
|
|
* use it as well as possible? This tee should also work on other systems,
|
|
* but it's not been tested there, only on OS/2.
|
|
*
|
|
* tee is also available in the GNU shellutils package, which is available
|
|
* precompiled for OS/2. That one probably works better.
|
|
*/
|
|
|
|
#ifndef _MSC_VER
|
|
# include <unistd.h>
|
|
#endif
|
|
#include <malloc.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
|
|
#ifdef _WIN32
|
|
# define sysconf(x) -1
|
|
#endif
|
|
|
|
void usage(void)
|
|
{
|
|
fprintf(stderr,
|
|
"tee usage:\n\
|
|
\ttee [-a] file ... file_n\n\
|
|
\n\
|
|
\t-a\tappend to files instead of truncating\n\
|
|
\nTee reads its input, and writes to each of the specified files,\n\
|
|
as well as to the standard output.\n\
|
|
\n\
|
|
This version supplied with Vim 4.2 to make ':make' possible.\n\
|
|
For a more complete and stable version, consider getting\n\
|
|
[a port of] the GNU shellutils package.\n\
|
|
");
|
|
}
|
|
|
|
/*
|
|
* fread only returns when count is read or at EOF.
|
|
* We could use fgets, but I want to be able to handle binary blubber.
|
|
*/
|
|
|
|
int
|
|
myfread(char *buf, int elsize /*ignored*/, int max, FILE *fp)
|
|
{
|
|
int c;
|
|
int n = 0;
|
|
|
|
while ((n < max) && ((c = getchar()) != EOF))
|
|
{
|
|
*(buf++) = c;
|
|
n++;
|
|
if (c == '\n' || c == '\r')
|
|
break;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
|
|
void
|
|
main(int argc, char *argv[])
|
|
{
|
|
int append = 0;
|
|
int numfiles;
|
|
int opt;
|
|
int maxfiles;
|
|
FILE **filepointers;
|
|
int i;
|
|
char buf[BUFSIZ];
|
|
int n;
|
|
int optind = 1;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (argv[i][0] != '-')
|
|
break;
|
|
if (!strcmp(argv[i], "-a"))
|
|
append++;
|
|
else
|
|
usage();
|
|
optind++;
|
|
}
|
|
|
|
numfiles = argc - optind;
|
|
|
|
if (numfiles == 0)
|
|
{
|
|
fprintf(stderr, "doesn't make much sense using tee without any file name arguments...\n");
|
|
usage();
|
|
exit(2);
|
|
}
|
|
|
|
maxfiles = sysconf(_SC_OPEN_MAX); /* or fill in 10 or so */
|
|
if (maxfiles < 0)
|
|
maxfiles = 10;
|
|
if (numfiles + 3 > maxfiles) /* +3 accounts for stdin, out, err */
|
|
{
|
|
fprintf(stderr, "Sorry, there is a limit of max %d files.\n", maxfiles - 3);
|
|
exit(1);
|
|
}
|
|
filepointers = calloc(numfiles, sizeof(FILE *));
|
|
if (filepointers == NULL)
|
|
{
|
|
fprintf(stderr, "Error allocating memory for %d files\n", numfiles);
|
|
exit(1);
|
|
}
|
|
for (i = 0; i < numfiles; i++)
|
|
{
|
|
filepointers[i] = fopen(argv[i+optind], append ? "ab" : "wb");
|
|
if (filepointers[i] == NULL)
|
|
{
|
|
fprintf(stderr, "Can't open \"%s\"\n", argv[i+optind]);
|
|
exit(1);
|
|
}
|
|
}
|
|
setmode(fileno(stdin), O_BINARY);
|
|
fflush(stdout); /* needed for _fsetmode(stdout) */
|
|
setmode(fileno(stdout), O_BINARY);
|
|
|
|
while ((n = myfread(buf, sizeof(char), sizeof(buf), stdin)) > 0)
|
|
{
|
|
fwrite(buf, sizeof(char), n, stdout);
|
|
fflush(stdout);
|
|
for (i = 0; i < numfiles; i++)
|
|
{
|
|
if (filepointers[i] &&
|
|
fwrite(buf, sizeof(char), n, filepointers[i]) != n)
|
|
{
|
|
fprintf(stderr, "Error writing to file \"%s\"\n", argv[i+optind]);
|
|
fclose(filepointers[i]);
|
|
filepointers[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < numfiles; i++)
|
|
{
|
|
if (filepointers[i])
|
|
fclose(filepointers[i]);
|
|
}
|
|
|
|
exit(0);
|
|
}
|