Merged in changes for 1.3.5.

This commit is contained in:
Jim Meyering
1992-11-19 21:03:49 +00:00
parent ceda697482
commit 750bb6aa69
14 changed files with 245 additions and 51 deletions
+3 -2
View File
@@ -20,7 +20,7 @@
possible. -David Ihnat (312) 784-4544 ignatz@homebru.chi.il.us
POSIX changes, bug fixes, long-named options, and cleanup
by David MacKenzie <djm@ai.mit.edu>.
by David MacKenzie <djm@gnu.ai.mit.edu>.
Options:
--bytes=byte-list
@@ -57,6 +57,7 @@
A FILE of `-' means standard input. */
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
#include <ctype.h>
#ifndef isblank
@@ -527,7 +528,7 @@ cut_fields (stream)
if (fieldfound)
{
/* Something was found. Print it. */
if (outbufptr[-1] == delim)
if ((unsigned char) outbufptr[-1] == delim)
--outbufptr; /* Suppress trailing delimiter. */
fwrite (outbuf, sizeof (char), outbufptr - outbuf, stdout);
+2 -1
View File
@@ -31,8 +31,9 @@
--initial
-i Only convert initial tabs on each line to spaces.
David MacKenzie <djm@ai.mit.edu> */
David MacKenzie <djm@gnu.ai.mit.edu> */
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
#include <ctype.h>
#ifndef isblank
+2 -1
View File
@@ -15,8 +15,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by David MacKenzie. */
/* Written by David MacKenzie, djm@gnu.ai.mit.edu. */
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
#include <ctype.h>
#ifndef isblank
+1 -1
View File
@@ -31,7 +31,7 @@
is given.
By default, prints the first 10 lines (head -n 10).
David MacKenzie <djm@ai.mit.edu> */
David MacKenzie <djm@gnu.ai.mit.edu> */
#include <stdio.h>
#include <getopt.h>
+1
View File
@@ -17,6 +17,7 @@
Written by Mike Haertel, mike@gnu.ai.mit.edu. */
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
#include <ctype.h>
#ifndef isblank
+1 -1
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by Scott Bartram (nancy!scott@uunet.uu.net)
Revised by David MacKenzie (djm@ai.mit.edu) */
Revised by David MacKenzie (djm@gnu.ai.mit.edu) */
#include <stdio.h>
#include <sys/types.h>
+9 -22
View File
@@ -43,7 +43,7 @@ char *alloca ();
#include <float.h>
#endif
#ifdef __GNUC__
#ifdef __STDC__
typedef long double LONG_DOUBLE;
#else
typedef double LONG_DOUBLE;
@@ -541,7 +541,7 @@ print_double (n_bytes, block, fmt_string)
error (2, errno, "standard output");
}
#ifdef __GNUC__
#ifdef __STDC__
static void
print_long_double (n_bytes, block, fmt_string)
long unsigned int n_bytes;
@@ -861,9 +861,10 @@ decode_one_format (s, next, tspec)
switch (size_spec)
{
/* Don't use %#e; not all systems support it. */
case FP_SINGLE:
print_function = print_float;
pre_fmt_string = "%%%d.%d#e%%c";
pre_fmt_string = "%%%d.%de%%c";
fmt_string = xmalloc (strlen (pre_fmt_string));
sprintf (fmt_string, pre_fmt_string,
FLT_DIG + 8, FLT_DIG);
@@ -871,16 +872,16 @@ decode_one_format (s, next, tspec)
case FP_DOUBLE:
print_function = print_double;
pre_fmt_string = "%%%d.%d#e%%c";
pre_fmt_string = "%%%d.%de%%c";
fmt_string = xmalloc (strlen (pre_fmt_string));
sprintf (fmt_string, pre_fmt_string,
DBL_DIG + 8, DBL_DIG);
break;
#ifdef __GNUC__
#ifdef __STDC__
case FP_LONG_DOUBLE:
print_function = print_long_double;
pre_fmt_string = "%%%d.%d#le%%c";
pre_fmt_string = "%%%d.%dle%%c";
fmt_string = xmalloc (strlen (pre_fmt_string));
sprintf (fmt_string, pre_fmt_string,
LDBL_DIG + 8, LDBL_DIG);
@@ -1569,25 +1570,11 @@ main (argc, argv)
/* The next several cases map the old, pre-POSIX format
specification options to the corresponding POSIX format
specs. GNU od accepts any combination of old- and
new-style options. If only POSIX format specs are used
and more than one is used, they are accumulated. If only
old-style options are used, all but the last are ignored.
If both types of specs are used in the same command, the
last old-style option and any POSIX specs following it
are accumulated. To illustrate, `od -c -t a' is the same
as `od -t ca', but `od -t a -c' is the same as `od -c'. */
new-style options. Format specification options accumulate. */
#define CASE_OLD_ARG(old_char,new_string) \
case old_char: \
{ \
const char *next; \
int tmp; \
assert (n_specs_allocated >= 1); \
tmp = decode_one_format (new_string, &next, &(spec[0])); \
n_specs = 1; \
assert (tmp == 0); \
assert (*next == '\0'); \
} \
assert (decode_format_string (new_string) == 0); \
break
CASE_OLD_ARG ('a', "a");
+1 -1
View File
@@ -24,7 +24,7 @@
version, to include \b, \f, \r, and \v.
POSIX changes, bug fixes, long-named options, and cleanup
by David MacKenzie <djm@ai.mit.edu>.
by David MacKenzie <djm@gnu.ai.mit.edu>.
Options:
--serial
+2 -1
View File
@@ -16,9 +16,10 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Written December 1988 by Mike Haertel.
The author may be reached (Email) at the address mike@ai.mit.edu,
The author may be reached (Email) at the address mike@gnu.ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
#include <ctype.h>
#ifndef isblank
+1 -1
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by Jay Lepreau (lepreau@cs.utah.edu).
GNU enhancements by David MacKenzie (djm@ai.mit.edu). */
GNU enhancements by David MacKenzie (djm@gnu.ai.mit.edu). */
/* Copy each FILE, or the standard input if none are given or when a
FILE name of "-" is encountered, to the standard output with the
+217 -18
View File
@@ -1,4 +1,4 @@
/* tail -- output last part of file(s)
/* tail -- output the last part of file(s)
Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,6 @@
-f, --follow Loop forever trying to read more characters at the
end of the file, on the assumption that the file
is growing. Ignored if reading from a pipe.
Cannot be used if more than one file is given.
-k Tail by N kilobytes.
-N, -l, -n, --lines=N Tail by N lines.
-m Tail by N megabytes.
@@ -43,12 +42,14 @@
By default, prints the last 10 lines (tail -n 10).
Original version by Paul Rubin <phr@ocf.berkeley.edu>.
Extensions by David MacKenzie <djm@ai.mit.edu>. */
Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
tail -f for multiple files by Ian Lance Taylor <ian@cygnus.com>. */
#include <stdio.h>
#include <getopt.h>
#include <ctype.h>
#include <sys/types.h>
#include <signal.h>
#include "system.h"
#ifdef isascii
@@ -67,9 +68,15 @@
If 0, tail in lines. */
static int unit_size;
/* If nonzero, read from end of file until killed. */
/* If nonzero, read from the end of one file until killed. */
static int forever;
/* If nonzero, read from the end of multiple files until killed. */
static int forever_multiple;
/* Array of file descriptors if forever_multiple is 1. */
static int *file_descs;
/* If nonzero, count from start of file instead of end. */
static int from_start;
@@ -97,6 +104,7 @@ static int tail_file ();
static int tail_lines ();
static long atou();
static void dump_remainder ();
static void tail_forever ();
static void parse_unit ();
static void usage ();
static void write_header ();
@@ -130,11 +138,12 @@ main (argc, argv)
means the value has not been set. */
long number = -1;
int c; /* Option character. */
int fileind; /* Index in ARGV of first file name. */
program_name = argv[0];
have_read_stdin = 0;
unit_size = 0;
forever = from_start = print_headers = 0;
forever = forever_multiple = from_start = print_headers = 0;
if (argc > 1
&& ((argv[1][0] == '-' && ISDIGIT (argv[1][1]))
@@ -254,18 +263,27 @@ main (argc, argv)
if (unit_size > 1)
number *= unit_size;
fileind = optind;
if (optind < argc - 1 && forever)
error (1, 0, "cannot follow the ends of multiple files");
{
forever_multiple = 1;
forever = 0;
file_descs = (int *) xmalloc ((argc - optind) * sizeof (int));
}
if (header_mode == always
|| (header_mode == multiple_files && optind < argc - 1))
print_headers = 1;
if (optind == argc)
exit_status |= tail_file ("-", number);
exit_status |= tail_file ("-", number, 0);
for (; optind < argc; ++optind)
exit_status |= tail_file (argv[optind], number);
exit_status |= tail_file (argv[optind], number, optind - fileind);
if (forever_multiple)
tail_forever (argv + fileind, argc - fileind);
if (have_read_stdin && close (0) < 0)
error (1, errno, "-");
@@ -276,14 +294,16 @@ main (argc, argv)
/* Display the last NUMBER units of file FILENAME.
"-" for FILENAME means the standard input.
FILENUM is this file's index in the list of files the user gave.
Return 0 if successful, 1 if an error occurred. */
static int
tail_file (filename, number)
tail_file (filename, number, filenum)
char *filename;
long number;
int filenum;
{
int fd;
int fd, errors;
if (!strcmp (filename, "-"))
{
@@ -291,24 +311,48 @@ tail_file (filename, number)
filename = "standard input";
if (print_headers)
write_header (filename);
return tail (filename, 0, number);
errors = tail (filename, 0, number);
if (forever_multiple)
file_descs[filenum] = errors ? -1 : 0;
}
else
{
/* Not standard input. */
fd = open (filename, O_RDONLY);
if (fd >= 0)
if (fd == -1)
{
if (forever_multiple)
file_descs[filenum] = -1;
error (0, errno, "%s", filename);
errors = 1;
}
else
{
int errors;
if (print_headers)
write_header (filename);
errors = tail (filename, fd, number);
if (close (fd) == 0)
return errors;
if (forever_multiple)
{
if (errors)
{
close (fd);
file_descs[filenum] = -1;
}
else
file_descs[filenum] = fd;
}
else
{
if (close (fd))
{
error (0, errno, "%s", filename);
errors = 1;
}
}
}
error (0, errno, "%s", filename);
return 1;
}
return errors;
}
static void
@@ -808,6 +852,161 @@ output:
}
}
#ifndef SIGUSR1
#define SIGUSR1 SIGSYS
#endif
/* To support tail_forever we use a signal handler that just quietly
exits. We are going to fork once for each file; we send a SIGUSR1
to kill the children if an error occurs. */
static RETSIGTYPE
sigusr1 (sig)
int sig;
{
exit (0);
}
/* Print error message MESSAGE for errno ERRNUM;
send SIGUSR1 to the KIDS processes in PIDS;
exit with status 1. */
static void
kill_kids (errnum, message, pids, kids)
int errnum;
char *message;
int *pids;
int kids;
{
int i;
error (0, errnum, message);
for (i = 0; i < kids; i++)
kill (pids[i], SIGUSR1);
exit (1);
}
/* The number of bytes that a pipe can hold (atomic read or write). */
#ifndef PIPE_BUF
#define PIPE_BUF 512
#endif
/* Tail NFILES (>1) files forever until killed. The file names are in NAMES.
The open file descriptors are in `file_descs'. Fork a process for each
file, let all the processes write to a single pipe, and then read
the pipe. */
/* Should we reap the zombies with wait? */
static void
tail_forever (names, nfiles)
char **names;
int nfiles;
{
int pipe_descs[2];
int *pids;
int i;
char *buffer = xmalloc (PIPE_BUF); /* malloc assures `int' alignment. */
int bytes_read;
int ilast;
if (pipe (pipe_descs) < 0)
error (1, errno, "cannot make pipe");
pids = (int *) xmalloc (nfiles * sizeof (int));
/* fork once for each file. If this is too ugly for you, don't use
tail -f on multiple files. Maybe we could use select as an
alternative, though it's less portable. Is it worth the bother? */
signal (SIGUSR1, sigusr1);
for (i = 0; i < nfiles; i++)
{
if (file_descs[i] == -1)
continue;
pids[i] = fork ();
if (pids[i] == -1)
kill_kids (errno, "cannot fork", pids, i);
if (pids[i] == 0)
{
/* Child. */
int offset;
close (pipe_descs[0]);
/* Each child reads continually from a file and writes to
the pipe. Each write to a pipe is the index of the file
being read, followed by the number of bytes read from the
file, followed by the actual bytes. Each child is
careful to write no more than PIPE_BUF bytes to the pipe,
so that the data from the various children does not get
intermixed. */
/* The file index for this child is always the same. */
*(int *) buffer = i;
offset = sizeof i + sizeof bytes_read;
while (1)
{
while ((bytes_read = read (file_descs[i], buffer + offset,
PIPE_BUF - offset)) > 0)
{
*(int *) (buffer + sizeof i) = bytes_read;
if (write (pipe_descs[1], buffer, offset + bytes_read)
!= offset + bytes_read)
_exit (0); /* Somebody killed our parent? */
}
if (bytes_read == -1)
{
error (0, errno, "%s", names[i]);
_exit (1);
}
sleep (1);
}
}
}
/* Parent. */
close (pipe_descs[1]);
/* Wait for input to come in on the pipe. Read the file index
and the number of bytes. Then read that many bytes and print
them out. Repeat until all the children have closed the pipe. */
ilast = -1;
while ((bytes_read = read (pipe_descs[0], buffer,
sizeof i + sizeof bytes_read)) > 0)
{
int igot; /* Index of latest process that wrote. */
if (bytes_read != sizeof i + sizeof bytes_read)
kill_kids (errno, "read error", pids, nfiles); /* Yikes. */
/* Extract the file index and the number of bytes. */
igot = *(int *) buffer;
bytes_read = *(int *) (buffer + sizeof i);
if (print_headers && igot != ilast)
write_header (names[igot]);
ilast = igot;
errno = 0;
if (read (pipe_descs[0], buffer, bytes_read) != bytes_read)
kill_kids (errno, "read error", pids, nfiles);
if (write (1, buffer, bytes_read) != bytes_read)
kill_kids (errno, "write error", pids, nfiles);
}
for (i = 0; i < nfiles; i++)
kill (pids[i], SIGUSR1);
free (buffer);
}
static void
parse_unit (str)
char *str;
+2 -1
View File
@@ -15,8 +15,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by Jim Meyering. */
/* Written by Jim Meyering, meyering@cs.utexas.edu. */
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
#include <ctype.h>
#ifndef isblank
+2 -1
View File
@@ -33,8 +33,9 @@
-a Use tabs wherever they would replace 2 or more spaces,
not just at the beginnings of lines.
David MacKenzie <djm@ai.mit.edu> */
David MacKenzie <djm@gnu.ai.mit.edu> */
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
#include <ctype.h>
#ifndef isblank
+1
View File
@@ -17,6 +17,7 @@
/* Written by Richard Stallman and David MacKenzie. */
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
#include <ctype.h>
#ifndef isblank